@voqalize/avatar 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/LICENSE-APACHE-2.0 +201 -0
  2. package/README.md +26 -95
  3. package/assets/README.md +30 -18
  4. package/assets/tanvi.glb +0 -0
  5. package/assets/tanya.glb +0 -0
  6. package/assets/tara.glb +0 -0
  7. package/assets/tess.glb +0 -0
  8. package/assets/tushar.glb +0 -0
  9. package/client/internal.ts +24 -0
  10. package/client/supports.ts +6 -7
  11. package/client/three/assets.ts +7 -3
  12. package/client/three/budgets.ts +1 -1
  13. package/client/three/{tara-rig.ts → character-rig.ts} +682 -540
  14. package/client/three/createCharacter.ts +109 -0
  15. package/client/three/holds.ts +8 -3
  16. package/client/three/internal.ts +8 -7
  17. package/client/three/motion-limits.json +10 -2
  18. package/client/three/sequences.ts +5 -5
  19. package/client/three/tanvi-asset.ts +6 -0
  20. package/client/three/tanvi.ts +30 -0
  21. package/client/three/tanya.ts +18 -58
  22. package/client/three/tara.ts +19 -60
  23. package/client/three/tess-asset.ts +6 -0
  24. package/client/three/tess.ts +30 -0
  25. package/client/three/tushar.ts +18 -55
  26. package/dist/internal.d.ts +2 -2
  27. package/dist/internal.d.ts.map +1 -1
  28. package/dist/internal.js +16 -1
  29. package/dist/internal.js.map +1 -1
  30. package/dist/supports.d.ts +6 -7
  31. package/dist/supports.d.ts.map +1 -1
  32. package/dist/supports.js +6 -7
  33. package/dist/supports.js.map +1 -1
  34. package/dist/three/assets.d.ts +2 -0
  35. package/dist/three/assets.d.ts.map +1 -1
  36. package/dist/three/assets.js +7 -3
  37. package/dist/three/assets.js.map +1 -1
  38. package/dist/three/budgets.d.ts +1 -1
  39. package/dist/three/budgets.js +1 -1
  40. package/dist/three/character-rig.d.ts +366 -0
  41. package/dist/three/character-rig.d.ts.map +1 -0
  42. package/dist/three/{tara-rig.js → character-rig.js} +633 -526
  43. package/dist/three/character-rig.js.map +1 -0
  44. package/dist/three/createCharacter.d.ts +60 -0
  45. package/dist/three/createCharacter.d.ts.map +1 -0
  46. package/dist/three/createCharacter.js +84 -0
  47. package/dist/three/createCharacter.js.map +1 -0
  48. package/dist/three/holds.d.ts +7 -2
  49. package/dist/three/holds.d.ts.map +1 -1
  50. package/dist/three/holds.js +8 -3
  51. package/dist/three/holds.js.map +1 -1
  52. package/dist/three/internal.d.ts +7 -7
  53. package/dist/three/internal.d.ts.map +1 -1
  54. package/dist/three/internal.js +6 -6
  55. package/dist/three/internal.js.map +1 -1
  56. package/dist/three/motion-limits.json +10 -2
  57. package/dist/three/sequences.d.ts +5 -5
  58. package/dist/three/sequences.js +5 -5
  59. package/dist/three/tanvi-asset.d.ts +7 -0
  60. package/dist/three/tanvi-asset.d.ts.map +1 -0
  61. package/dist/three/tanvi-asset.js +7 -0
  62. package/dist/three/tanvi-asset.js.map +1 -0
  63. package/dist/three/tanvi.d.ts +24 -0
  64. package/dist/three/tanvi.d.ts.map +1 -0
  65. package/dist/three/tanvi.js +24 -0
  66. package/dist/three/tanvi.js.map +1 -0
  67. package/dist/three/tanya.d.ts +16 -28
  68. package/dist/three/tanya.d.ts.map +1 -1
  69. package/dist/three/tanya.js +15 -43
  70. package/dist/three/tanya.js.map +1 -1
  71. package/dist/three/tara.d.ts +17 -22
  72. package/dist/three/tara.d.ts.map +1 -1
  73. package/dist/three/tara.js +16 -45
  74. package/dist/three/tara.js.map +1 -1
  75. package/dist/three/tess-asset.d.ts +7 -0
  76. package/dist/three/tess-asset.d.ts.map +1 -0
  77. package/dist/three/tess-asset.js +7 -0
  78. package/dist/three/tess-asset.js.map +1 -0
  79. package/dist/three/tess.d.ts +24 -0
  80. package/dist/three/tess.d.ts.map +1 -0
  81. package/dist/three/tess.js +24 -0
  82. package/dist/three/tess.js.map +1 -0
  83. package/dist/three/tushar.d.ts +16 -25
  84. package/dist/three/tushar.d.ts.map +1 -1
  85. package/dist/three/tushar.js +15 -40
  86. package/dist/three/tushar.js.map +1 -1
  87. package/package.json +10 -49
  88. package/src/avatar.d.ts +67 -2
  89. package/src/avatar.js +131 -255
  90. package/src/faces.js +1 -1
  91. package/src/gaze.js +20 -47
  92. package/src/idle.js +69 -27
  93. package/src/prosody.js +109 -15
  94. package/src/rig.d.ts +7 -0
  95. package/src/speech-timing.js +9 -0
  96. package/src/visemes.js +107 -13
  97. package/client/arjun.ts +0 -26
  98. package/client/createCanvasAvatar.ts +0 -72
  99. package/client/interviewer-female.ts +0 -4
  100. package/client/interviewer-male.ts +0 -4
  101. package/client/ishita.ts +0 -26
  102. package/client/kabir.ts +0 -26
  103. package/client/meera.ts +0 -26
  104. package/client/naina.ts +0 -26
  105. package/client/professional-female-a.ts +0 -4
  106. package/client/professional-female-b.ts +0 -4
  107. package/client/professional-male-a.ts +0 -4
  108. package/client/professional-male-b.ts +0 -4
  109. package/client/vikram.ts +0 -26
  110. package/dist/arjun.d.ts +0 -7
  111. package/dist/arjun.d.ts.map +0 -1
  112. package/dist/arjun.js +0 -20
  113. package/dist/arjun.js.map +0 -1
  114. package/dist/createCanvasAvatar.d.ts +0 -22
  115. package/dist/createCanvasAvatar.d.ts.map +0 -1
  116. package/dist/createCanvasAvatar.js +0 -47
  117. package/dist/createCanvasAvatar.js.map +0 -1
  118. package/dist/interviewer-female.d.ts +0 -4
  119. package/dist/interviewer-female.d.ts.map +0 -1
  120. package/dist/interviewer-female.js +0 -3
  121. package/dist/interviewer-female.js.map +0 -1
  122. package/dist/interviewer-male.d.ts +0 -4
  123. package/dist/interviewer-male.d.ts.map +0 -1
  124. package/dist/interviewer-male.js +0 -3
  125. package/dist/interviewer-male.js.map +0 -1
  126. package/dist/ishita.d.ts +0 -7
  127. package/dist/ishita.d.ts.map +0 -1
  128. package/dist/ishita.js +0 -20
  129. package/dist/ishita.js.map +0 -1
  130. package/dist/kabir.d.ts +0 -7
  131. package/dist/kabir.d.ts.map +0 -1
  132. package/dist/kabir.js +0 -20
  133. package/dist/kabir.js.map +0 -1
  134. package/dist/meera.d.ts +0 -7
  135. package/dist/meera.d.ts.map +0 -1
  136. package/dist/meera.js +0 -20
  137. package/dist/meera.js.map +0 -1
  138. package/dist/naina.d.ts +0 -7
  139. package/dist/naina.d.ts.map +0 -1
  140. package/dist/naina.js +0 -20
  141. package/dist/naina.js.map +0 -1
  142. package/dist/professional-female-a.d.ts +0 -4
  143. package/dist/professional-female-a.d.ts.map +0 -1
  144. package/dist/professional-female-a.js +0 -3
  145. package/dist/professional-female-a.js.map +0 -1
  146. package/dist/professional-female-b.d.ts +0 -4
  147. package/dist/professional-female-b.d.ts.map +0 -1
  148. package/dist/professional-female-b.js +0 -3
  149. package/dist/professional-female-b.js.map +0 -1
  150. package/dist/professional-male-a.d.ts +0 -4
  151. package/dist/professional-male-a.d.ts.map +0 -1
  152. package/dist/professional-male-a.js +0 -3
  153. package/dist/professional-male-a.js.map +0 -1
  154. package/dist/professional-male-b.d.ts +0 -4
  155. package/dist/professional-male-b.d.ts.map +0 -1
  156. package/dist/professional-male-b.js +0 -3
  157. package/dist/professional-male-b.js.map +0 -1
  158. package/dist/three/tara-rig.d.ts +0 -409
  159. package/dist/three/tara-rig.d.ts.map +0 -1
  160. package/dist/three/tara-rig.js.map +0 -1
  161. package/dist/vikram.d.ts +0 -7
  162. package/dist/vikram.d.ts.map +0 -1
  163. package/dist/vikram.js +0 -20
  164. package/dist/vikram.js.map +0 -1
  165. package/src/canvas/author/parts/eye.mjs +0 -722
  166. package/src/canvas/author/parts/hand.mjs +0 -1156
  167. package/src/canvas/author/parts/mouth.mjs +0 -741
  168. package/src/canvas/author/parts/nose.mjs +0 -100
  169. package/src/canvas/author/parts/skin-detail.mjs +0 -67
  170. package/src/canvas/author/path.mjs +0 -283
  171. package/src/canvas/author/rig.mjs +0 -405
  172. package/src/canvas/avatars/round/face.d.mts +0 -3
  173. package/src/canvas/avatars/round/face.mjs +0 -1307
  174. package/src/canvas/create-rig.d.ts +0 -15
  175. package/src/canvas/create-rig.js +0 -100
  176. package/src/canvas/data/img/professional-female-a-hair-back.webp +0 -0
  177. package/src/canvas/data/img/professional-female-a-hair-front.webp +0 -0
  178. package/src/canvas/data/img/professional-female-a-top-body.webp +0 -0
  179. package/src/canvas/data/img/professional-female-b-hair-back.webp +0 -0
  180. package/src/canvas/data/img/professional-female-b-hair-front.webp +0 -0
  181. package/src/canvas/data/img/professional-female-b-top-body.webp +0 -0
  182. package/src/canvas/data/img/professional-male-a-hair-back.webp +0 -0
  183. package/src/canvas/data/img/professional-male-a-hair-front.webp +0 -0
  184. package/src/canvas/data/img/professional-male-a-top-body.webp +0 -0
  185. package/src/canvas/data/img/professional-male-b-hair-back.webp +0 -0
  186. package/src/canvas/data/img/professional-male-b-hair-front.webp +0 -0
  187. package/src/canvas/data/img/professional-male-b-top-body.webp +0 -0
  188. package/src/canvas/data/img/round-m3-hair-back.webp +0 -0
  189. package/src/canvas/data/img/round-m3-hair-front.webp +0 -0
  190. package/src/canvas/data/img/round-m3-top-body.webp +0 -0
  191. package/src/canvas/data/img/round-w1-hair-back.webp +0 -0
  192. package/src/canvas/data/img/round-w1-hair-front.webp +0 -0
  193. package/src/canvas/data/img/round-w1-top-body.webp +0 -0
  194. package/src/canvas/data/interviewer-female.rig.json +0 -1
  195. package/src/canvas/data/interviewer-male.rig.json +0 -1
  196. package/src/canvas/data/professional-female-a.rig.json +0 -1
  197. package/src/canvas/data/professional-female-b.rig.json +0 -1
  198. package/src/canvas/data/professional-male-a.rig.json +0 -1
  199. package/src/canvas/data/professional-male-b.rig.json +0 -1
  200. package/src/canvas/src/live.js +0 -508
  201. package/src/canvas/src/render2d.js +0 -218
  202. package/src/canvas/src/rig.js +0 -297
  203. package/src/canvas/src/vocab.js +0 -96
package/src/visemes.js CHANGED
@@ -36,19 +36,50 @@
36
36
  import {
37
37
  CUE_TRACK_LEAD_MS,
38
38
  MIN_VISIBLE_CUE_MS,
39
+ ROUND_LEAD_MS,
39
40
  SPEECH_TRACK_TAIL_MS,
40
41
  } from './speech-timing.js';
41
42
 
43
+ /**
44
+ * The mouth every face owes the server, at the loudest a cue can say (`i` 1).
45
+ *
46
+ * **The apertures are measured speech, not taste.** The anchor is the open
47
+ * vowel: Huber & Chandrasekaran 2006 (JSLHR 49:1368, Table 2; Optotrak, 30
48
+ * adults, a sentence read aloud) open "Bobby"'s [ɑ] by 7.84 mm of lower lip
49
+ * over the jaw, 7.32 of jaw and 2.49 of upper lip — 17.65 mm of inter-lip
50
+ * opening, pooled over one comfortable and three loud conditions. Their Table 1
51
+ * puts comfortable at 0.83 of that pool (4.86 mm against a loud 6.06–6.35), so
52
+ * ordinary speech opens an [ɑ] **14.6 mm**, and `D` is sized so that it does at
53
+ * `i` 0.5 — which is where PyGato puts an engine's ordinary speaking level
54
+ * (`pygato.lipsync.intensity`). The same paper is the check on the parts this
55
+ * does not set: the jaw's share comes out at 6.6 mm against their ~6.1, and the
56
+ * upper lip at 1.7 mm against ~2.1 — the upper lip is the stable one, a third
57
+ * of the lower's travel, and the rig already had it so.
58
+ *
59
+ * Millimetres are face units at **176.7 mm** a unit (chin to hairline): Lin &
60
+ * Chen 2017 (PLoS ONE 12:e0188638) give women's menton–sellion as 107.8 mm,
61
+ * and sellion sits at 0.61 of the unit on every character here. Their mouth
62
+ * width (44.9 mm) would say 157 — these faces are drawn with slightly wide
63
+ * mouths, and the vertical measure is the one an aperture is.
64
+ *
65
+ * No source reachable gave per-vowel apertures in millimetres, so the other
66
+ * letters keep the ratios to `D` they were authored with and are scaled by the
67
+ * same factor (0.617 of their excursion from rest). Upper-teeth show is part
68
+ * of the opening and scales with it — except on `G`, where teeth on the lip
69
+ * *is* the shape. A mouth this size is what "the mouth is moving a lot" was
70
+ * asking for: the table it replaced opened an ordinary [ɑ] 26 mm, as far as the
71
+ * loud speech in that study opens a shout.
72
+ */
42
73
  export const VISEME_SHAPES = {
43
74
  X: { mouthOpen: 0.02, mouthWidth: 0.42, mouthRound: 0.10, mouthPress: 0.15, mouthTuck: 0, teethUpper: 0.00, tongue: 0.0 },
44
75
  A: { mouthOpen: 0.00, mouthWidth: 0.40, mouthRound: 0.18, mouthPress: 0.55, mouthTuck: 0, teethUpper: 0.00, tongue: 0.0 },
45
- B: { mouthOpen: 0.16, mouthWidth: 0.54, mouthRound: 0.05, mouthPress: 0.10, mouthTuck: 0, teethUpper: 0.75, tongue: 0.0 },
46
- C: { mouthOpen: 0.45, mouthWidth: 0.58, mouthRound: 0.05, mouthPress: 0.00, mouthTuck: 0, teethUpper: 0.45, tongue: 0.0 },
47
- D: { mouthOpen: 0.85, mouthWidth: 0.52, mouthRound: 0.02, mouthPress: 0.00, mouthTuck: 0, teethUpper: 0.25, tongue: 0.15 },
48
- E: { mouthOpen: 0.34, mouthWidth: 0.28, mouthRound: 0.55, mouthPress: 0.00, mouthTuck: 0, teethUpper: 0.15, tongue: 0.0 },
49
- F: { mouthOpen: 0.22, mouthWidth: 0.10, mouthRound: 0.95, mouthPress: 0.10, mouthTuck: 0, teethUpper: 0.00, tongue: 0.0 },
50
- G: { mouthOpen: 0.20, mouthWidth: 0.46, mouthRound: 0.10, mouthPress: 0.40, mouthTuck: 1.00, teethUpper: 1.00, tongue: 0.0 },
51
- H: { mouthOpen: 0.40, mouthWidth: 0.48, mouthRound: 0.05, mouthPress: 0.00, mouthTuck: 0, teethUpper: 0.35, tongue: 0.90 },
76
+ B: { mouthOpen: 0.11, mouthWidth: 0.54, mouthRound: 0.05, mouthPress: 0.10, mouthTuck: 0, teethUpper: 0.46, tongue: 0.0 },
77
+ C: { mouthOpen: 0.29, mouthWidth: 0.58, mouthRound: 0.05, mouthPress: 0.00, mouthTuck: 0, teethUpper: 0.28, tongue: 0.0 },
78
+ D: { mouthOpen: 0.53, mouthWidth: 0.52, mouthRound: 0.02, mouthPress: 0.00, mouthTuck: 0, teethUpper: 0.15, tongue: 0.15 },
79
+ E: { mouthOpen: 0.22, mouthWidth: 0.28, mouthRound: 0.55, mouthPress: 0.00, mouthTuck: 0, teethUpper: 0.09, tongue: 0.0 },
80
+ F: { mouthOpen: 0.14, mouthWidth: 0.10, mouthRound: 0.95, mouthPress: 0.10, mouthTuck: 0, teethUpper: 0.00, tongue: 0.0 },
81
+ G: { mouthOpen: 0.13, mouthWidth: 0.46, mouthRound: 0.10, mouthPress: 0.40, mouthTuck: 1.00, teethUpper: 1.00, tongue: 0.0 },
82
+ H: { mouthOpen: 0.25, mouthWidth: 0.48, mouthRound: 0.05, mouthPress: 0.00, mouthTuck: 0, teethUpper: 0.22, tongue: 0.90 },
52
83
  };
53
84
 
54
85
  export const VISEME_LETTERS = Object.keys(VISEME_SHAPES);
@@ -56,6 +87,40 @@ export const VISEME_LETTERS = Object.keys(VISEME_SHAPES);
56
87
  /** Resting mouth used when nothing is speaking. */
57
88
  export const SILENT = 'X';
58
89
 
90
+ /** The shapes that are a contact, not an aperture: lips together, lip to teeth. */
91
+ const CLOSURES = new Set(['A', 'G']);
92
+
93
+ /**
94
+ * How far the mandible falls for a given aperture — `jaw` is "follows
95
+ * mouthOpen but slower" (`params.js`) and this is the slower.
96
+ *
97
+ * It is exported because it is not a preference: **every amplitude behind the
98
+ * lips was calibrated at this ratio**, so a driver that picks its own moves the
99
+ * mandible relative to the lip that hides it. The lower arch is the surface
100
+ * that shows it, because it rides `jaw` alone while the lip peels off it on
101
+ * `mouthOpen`: what is seen of the arch is the difference between two much
102
+ * larger travels (`avatar-3d/scripts/morphs.ARCH_DROP`), so it goes to nothing
103
+ * at a ratio only a little above this one. A face driven at 1:1 opens wide and
104
+ * shows no lower teeth at any aperture — the arch descends as fast as the lip
105
+ * uncovering it, which is what mocap did until it read this number instead of
106
+ * ARKit's `jawOpen` directly.
107
+ */
108
+ export const JAW_OF_OPEN = 0.7;
109
+
110
+ /**
111
+ * How much of a shape's excursion a cue's loudness buys, as `k = LOUDNESS_FLOOR
112
+ * + (1 - LOUDNESS_FLOOR) * i`.
113
+ *
114
+ * Louder speech is the same movement made bigger, and not by much: +10 dB
115
+ * opens the lips and jaw 1.28x as far (Huber & Chandrasekaran 2006, Table 1:
116
+ * 4.86 mm comfortable, 6.06–6.35 loud; Schulman 1989 calls it "amplification
117
+ * of normal movement patterns"). `i` spans 16 dB with ordinary speech at 0.5,
118
+ * so 0.5 either side is 8 dB and 1.22x — k runs 0.776 : 1 : 1.224 across it,
119
+ * which normalised to the loud end is this floor. The quiet side is the loud
120
+ * side's slope extended; nothing measured it.
121
+ */
122
+ const LOUDNESS_FLOOR = 0.634;
123
+
59
124
  /**
60
125
  * Scale a shape by loudness. Only the "effortful" channels scale — a quiet 'D'
61
126
  * is a small D, not a different shape.
@@ -63,7 +128,7 @@ export const SILENT = 'X';
63
128
  export function shapeFor(letter, intensity = 1) {
64
129
  const base = VISEME_SHAPES[letter] || VISEME_SHAPES[SILENT];
65
130
  const rest = VISEME_SHAPES.X;
66
- const k = 0.45 + 0.55 * Math.max(0, Math.min(1, intensity));
131
+ const k = LOUDNESS_FLOOR + (1 - LOUDNESS_FLOOR) * Math.max(0, Math.min(1, intensity));
67
132
  return {
68
133
  mouthOpen: rest.mouthOpen + (base.mouthOpen - rest.mouthOpen) * k,
69
134
  mouthWidth: rest.mouthWidth + (base.mouthWidth - rest.mouthWidth) * k,
@@ -72,7 +137,7 @@ export function shapeFor(letter, intensity = 1) {
72
137
  mouthTuck: base.mouthTuck,
73
138
  teethUpper: base.teethUpper * k,
74
139
  tongue: base.tongue,
75
- jaw: (rest.mouthOpen + (base.mouthOpen - rest.mouthOpen) * k) * 0.7,
140
+ jaw: (rest.mouthOpen + (base.mouthOpen - rest.mouthOpen) * k) * JAW_OF_OPEN,
76
141
  };
77
142
  }
78
143
 
@@ -127,7 +192,7 @@ export function normalizeCues(cues) {
127
192
  if (prev && head.t - prev.t < MIN_VISIBLE_CUE_MS) {
128
193
  // Too short to read. Keep whichever is more visually salient: a closure
129
194
  // (A/G) carries more lip-reading information than a mid-open vowel.
130
- if (v === 'A' || v === 'G') {
195
+ if (CLOSURES.has(v)) {
131
196
  // The short cue can sit between two identical closures (G → F → G).
132
197
  // Its replacement would otherwise create a duplicate visible shape;
133
198
  // preserving the first G is both the stable wire form and the face the
@@ -209,6 +274,14 @@ export class VisemeTrack {
209
274
  this.cues = merged;
210
275
  // Re-seek rather than trusting the old index against a re-normalized array.
211
276
  this._idx = 0;
277
+ // A sentence can arrive after the one before it has played out — a TTS
278
+ // whose next sentence lags its own audio does this routinely — and the
279
+ // track had stopped at that sentence's tail. Resume on the same clock, or
280
+ // the face holds still through audio the user can hear.
281
+ if (!this.playing && this.clock && merged.length) {
282
+ const last = merged[merged.length - 1];
283
+ this.playing = last.v !== SILENT || this.clock() + LEAD_MS <= last.t + this.tailMs;
284
+ }
212
285
  }
213
286
 
214
287
  stop() {
@@ -218,7 +291,19 @@ export class VisemeTrack {
218
291
  this._idx = 0;
219
292
  }
220
293
 
221
- /** @returns {{letter: string, intensity: number, phone: string | null} | null} */
294
+ /**
295
+ * The shape to aim at now, which is not always the cue under the clock.
296
+ *
297
+ * Rounding starts before its sound, because it is the kind of gesture a
298
+ * viewer reads a word by (speech-timing.js has the measurements): `round`
299
+ * carries the pucker of a rounded vowel coming up within `ROUND_LEAD_MS`, for
300
+ * the mixer to hold against the current shape's own. It does not reach
301
+ * across a rest. A closure's early onset is not drawn here — the server
302
+ * already starts every closure cue ahead of its phone, and a second lead on
303
+ * top of that closed the lips a whole vowel early.
304
+ *
305
+ * @returns {{letter: string, intensity: number, phone: string | null, round: number} | null}
306
+ */
222
307
  sample() {
223
308
  if (!this.playing || !this.cues.length || !this.clock) return null;
224
309
  const now = this.clock() + LEAD_MS;
@@ -237,8 +322,17 @@ export class VisemeTrack {
237
322
  }
238
323
 
239
324
  const cue = this.cues[this._idx];
240
- if (cue.t > now) return { letter: SILENT, intensity: 1, phone: null };
241
- return { letter: cue.v, intensity: cue.i == null ? 1 : cue.i, phone: cue.p ?? null };
325
+ if (cue.t > now) return { letter: SILENT, intensity: 1, phone: null, round: 0 };
326
+ let round = 0;
327
+ for (let j = this._idx + 1; j < this.cues.length; j++) {
328
+ const ahead = this.cues[j];
329
+ if (ahead.v === SILENT || ahead.t - now > ROUND_LEAD_MS) break;
330
+ // Across consonants too: protrusion before a rounded vowel grows with the
331
+ // consonants in front of it (Noiray et al. 2011, JASA 129:340), so the
332
+ // lips of "sm-" in "smooth" are already on their way.
333
+ round = Math.max(round, VISEME_SHAPES[ahead.v].mouthRound);
334
+ }
335
+ return { letter: cue.v, intensity: cue.i == null ? 1 : cue.i, phone: cue.p ?? null, round };
242
336
  }
243
337
  }
244
338
 
package/client/arjun.ts DELETED
@@ -1,26 +0,0 @@
1
- /** Professional Indian male interviewer, authored to read at call-tile size. */
2
-
3
- import { createCanvasAvatar } from './createCanvasAvatar.js';
4
- import type { CanvasAvatarOptions } from './createCanvasAvatar.js';
5
- import type { AvatarInstance } from './createAvatar.js';
6
-
7
- const RIG_URL = new URL('../src/canvas/data/interviewer-male.rig.json', import.meta.url);
8
- const IMAGES = {
9
- 'round-m3-hair-back.webp': new URL('../src/canvas/data/img/round-m3-hair-back.webp', import.meta.url),
10
- 'round-m3-top-body.webp': new URL('../src/canvas/data/img/round-m3-top-body.webp', import.meta.url),
11
- 'round-m3-hair-front.webp': new URL('../src/canvas/data/img/round-m3-hair-front.webp', import.meta.url),
12
- } as const;
13
- const FACE = () => import('../src/canvas/avatars/round/face.mjs');
14
-
15
- export type { CanvasAvatarOptions };
16
- // Same mixer, same clip library, so the same declaration (`supports.ts`).
17
- export { supports } from './supports.js';
18
-
19
- export function createAvatar(options: CanvasAvatarOptions): AvatarInstance {
20
- return createCanvasAvatar(options, {
21
- rigUrl: RIG_URL,
22
- images: IMAGES,
23
- face: FACE,
24
- label: 'Arjun — professional male interviewer avatar',
25
- });
26
- }
@@ -1,72 +0,0 @@
1
- /** Shared private constructor for the code-authored canvas avatars. */
2
-
3
- import type { PipecatClient } from '@pipecat-ai/client-js';
4
- import { createAvatar as createMixer, STATES } from '../src/avatar.js';
5
- import type { Gain } from '../src/avatar.js';
6
- import { createCanvasRig } from '../src/canvas/create-rig.js';
7
- import { AvatarClient } from './AvatarClient.js';
8
- import type { AvatarInstance, AvatarOptions } from './createAvatar.js';
9
-
10
- export interface CanvasAvatarOptions extends AvatarOptions {
11
- /** Viseme amplitude, 0..2. `1` is as authored. */
12
- readonly mouthGain?: Gain;
13
- /** Gesture-clip amplitude, 0..2. */
14
- readonly gestureGain?: Gain;
15
- /** Idle/liveness amplitude, 0..2. */
16
- readonly motionGain?: Gain;
17
- }
18
-
19
- /** @deprecated Use `CanvasAvatarOptions`; kept for the original entry points. */
20
- export type InterviewerAvatarOptions = CanvasAvatarOptions;
21
-
22
- interface CanvasAvatarConfig {
23
- readonly rigUrl: URL;
24
- readonly images: Readonly<Record<string, URL>>;
25
- readonly face: () => Promise<unknown>;
26
- readonly label: string;
27
- }
28
-
29
- const GAINS = ['mouthGain', 'gestureGain', 'motionGain'] as const;
30
- const PRESENCE_FILTERS: Readonly<Record<string, string>> = {
31
- DEGRADED: String(STATES.DEGRADED.filter ?? ''),
32
- OFFLINE: String(STATES.OFFLINE.filter ?? ''),
33
- };
34
-
35
- export function createCanvasAvatar(
36
- options: CanvasAvatarOptions,
37
- config: CanvasAvatarConfig,
38
- ): AvatarInstance {
39
- const { mount, client, ...gains } = options;
40
- if (!mount) throw new TypeError('createAvatar: `mount` is required');
41
- if (!client) throw new TypeError('createAvatar: `client` is required');
42
- for (const key of GAINS) {
43
- const gain = gains[key];
44
- if (gain === undefined) continue;
45
- if (!Number.isFinite(gain) || gain < 0 || gain > 2) {
46
- throw new RangeError(`createAvatar: \`${key}\` must be 0..2, got ${String(gain)}`);
47
- }
48
- }
49
-
50
- const canvas = createCanvasRig({
51
- url: config.rigUrl,
52
- images: config.images,
53
- face: config.face,
54
- label: config.label,
55
- });
56
- const widget = createMixer({ mount, rig: canvas.factory, ...gains });
57
- const driver = new AvatarClient(widget, {
58
- onPresenceChange: (state) => canvas.setPresenceFilter(PRESENCE_FILTERS[state] ?? ''),
59
- });
60
- const detach = driver.attach(client as PipecatClient);
61
-
62
- let destroyed = false;
63
- return {
64
- destroy() {
65
- if (destroyed) return;
66
- destroyed = true;
67
- detach();
68
- driver.destroy();
69
- widget.destroy();
70
- },
71
- };
72
- }
@@ -1,4 +0,0 @@
1
- /** @deprecated Renamed to `meera`; kept as an alias so existing imports keep working. */
2
-
3
- export { createAvatar } from './meera.js';
4
- export type { CanvasAvatarOptions, CanvasAvatarOptions as InterviewerAvatarOptions } from './createCanvasAvatar.js';
@@ -1,4 +0,0 @@
1
- /** @deprecated Renamed to `arjun`; kept as an alias so existing imports keep working. */
2
-
3
- export { createAvatar } from './arjun.js';
4
- export type { CanvasAvatarOptions, CanvasAvatarOptions as InterviewerAvatarOptions } from './createCanvasAvatar.js';
package/client/ishita.ts DELETED
@@ -1,26 +0,0 @@
1
- /** Polished professional female avatar, authored to read at call-tile size. */
2
-
3
- import { createCanvasAvatar } from './createCanvasAvatar.js';
4
- import type { CanvasAvatarOptions } from './createCanvasAvatar.js';
5
- import type { AvatarInstance } from './createAvatar.js';
6
-
7
- const RIG_URL = new URL('../src/canvas/data/professional-female-a.rig.json', import.meta.url);
8
- const IMAGES = {
9
- 'professional-female-a-top-body.webp': new URL('../src/canvas/data/img/professional-female-a-top-body.webp', import.meta.url),
10
- 'professional-female-a-hair-back.webp': new URL('../src/canvas/data/img/professional-female-a-hair-back.webp', import.meta.url),
11
- 'professional-female-a-hair-front.webp': new URL('../src/canvas/data/img/professional-female-a-hair-front.webp', import.meta.url),
12
- } as const;
13
- const FACE = () => import('../src/canvas/avatars/round/face.mjs');
14
-
15
- export type { CanvasAvatarOptions };
16
- // Same mixer, same clip library, so the same declaration (`supports.ts`).
17
- export { supports } from './supports.js';
18
-
19
- export function createAvatar(options: CanvasAvatarOptions): AvatarInstance {
20
- return createCanvasAvatar(options, {
21
- rigUrl: RIG_URL,
22
- images: IMAGES,
23
- face: FACE,
24
- label: 'Ishita — polished professional female avatar',
25
- });
26
- }
package/client/kabir.ts DELETED
@@ -1,26 +0,0 @@
1
- /** Relaxed professional male avatar, authored to read at call-tile size. */
2
-
3
- import { createCanvasAvatar } from './createCanvasAvatar.js';
4
- import type { CanvasAvatarOptions } from './createCanvasAvatar.js';
5
- import type { AvatarInstance } from './createAvatar.js';
6
-
7
- const RIG_URL = new URL('../src/canvas/data/professional-male-b.rig.json', import.meta.url);
8
- const IMAGES = {
9
- 'professional-male-b-top-body.webp': new URL('../src/canvas/data/img/professional-male-b-top-body.webp', import.meta.url),
10
- 'professional-male-b-hair-back.webp': new URL('../src/canvas/data/img/professional-male-b-hair-back.webp', import.meta.url),
11
- 'professional-male-b-hair-front.webp': new URL('../src/canvas/data/img/professional-male-b-hair-front.webp', import.meta.url),
12
- } as const;
13
- const FACE = () => import('../src/canvas/avatars/round/face.mjs');
14
-
15
- export type { CanvasAvatarOptions };
16
- // Same mixer, same clip library, so the same declaration (`supports.ts`).
17
- export { supports } from './supports.js';
18
-
19
- export function createAvatar(options: CanvasAvatarOptions): AvatarInstance {
20
- return createCanvasAvatar(options, {
21
- rigUrl: RIG_URL,
22
- images: IMAGES,
23
- face: FACE,
24
- label: 'Kabir — relaxed professional male avatar',
25
- });
26
- }
package/client/meera.ts DELETED
@@ -1,26 +0,0 @@
1
- /** Professional Indian female interviewer, authored to read at call-tile size. */
2
-
3
- import { createCanvasAvatar } from './createCanvasAvatar.js';
4
- import type { CanvasAvatarOptions } from './createCanvasAvatar.js';
5
- import type { AvatarInstance } from './createAvatar.js';
6
-
7
- const RIG_URL = new URL('../src/canvas/data/interviewer-female.rig.json', import.meta.url);
8
- const IMAGES = {
9
- 'round-w1-hair-back.webp': new URL('../src/canvas/data/img/round-w1-hair-back.webp', import.meta.url),
10
- 'round-w1-top-body.webp': new URL('../src/canvas/data/img/round-w1-top-body.webp', import.meta.url),
11
- 'round-w1-hair-front.webp': new URL('../src/canvas/data/img/round-w1-hair-front.webp', import.meta.url),
12
- } as const;
13
- const FACE = () => import('../src/canvas/avatars/round/face.mjs');
14
-
15
- export type { CanvasAvatarOptions };
16
- // Same mixer, same clip library, so the same declaration (`supports.ts`).
17
- export { supports } from './supports.js';
18
-
19
- export function createAvatar(options: CanvasAvatarOptions): AvatarInstance {
20
- return createCanvasAvatar(options, {
21
- rigUrl: RIG_URL,
22
- images: IMAGES,
23
- face: FACE,
24
- label: 'Meera — professional female interviewer avatar',
25
- });
26
- }
package/client/naina.ts DELETED
@@ -1,26 +0,0 @@
1
- /** Relaxed professional female avatar, authored to read at call-tile size. */
2
-
3
- import { createCanvasAvatar } from './createCanvasAvatar.js';
4
- import type { CanvasAvatarOptions } from './createCanvasAvatar.js';
5
- import type { AvatarInstance } from './createAvatar.js';
6
-
7
- const RIG_URL = new URL('../src/canvas/data/professional-female-b.rig.json', import.meta.url);
8
- const IMAGES = {
9
- 'professional-female-b-top-body.webp': new URL('../src/canvas/data/img/professional-female-b-top-body.webp', import.meta.url),
10
- 'professional-female-b-hair-back.webp': new URL('../src/canvas/data/img/professional-female-b-hair-back.webp', import.meta.url),
11
- 'professional-female-b-hair-front.webp': new URL('../src/canvas/data/img/professional-female-b-hair-front.webp', import.meta.url),
12
- } as const;
13
- const FACE = () => import('../src/canvas/avatars/round/face.mjs');
14
-
15
- export type { CanvasAvatarOptions };
16
- // Same mixer, same clip library, so the same declaration (`supports.ts`).
17
- export { supports } from './supports.js';
18
-
19
- export function createAvatar(options: CanvasAvatarOptions): AvatarInstance {
20
- return createCanvasAvatar(options, {
21
- rigUrl: RIG_URL,
22
- images: IMAGES,
23
- face: FACE,
24
- label: 'Naina — relaxed professional female avatar',
25
- });
26
- }
@@ -1,4 +0,0 @@
1
- /** @deprecated Renamed to `ishita`; kept as an alias so existing imports keep working. */
2
-
3
- export { createAvatar } from './ishita.js';
4
- export type { CanvasAvatarOptions } from './createCanvasAvatar.js';
@@ -1,4 +0,0 @@
1
- /** @deprecated Renamed to `naina`; kept as an alias so existing imports keep working. */
2
-
3
- export { createAvatar } from './naina.js';
4
- export type { CanvasAvatarOptions } from './createCanvasAvatar.js';
@@ -1,4 +0,0 @@
1
- /** @deprecated Renamed to `vikram`; kept as an alias so existing imports keep working. */
2
-
3
- export { createAvatar } from './vikram.js';
4
- export type { CanvasAvatarOptions } from './createCanvasAvatar.js';
@@ -1,4 +0,0 @@
1
- /** @deprecated Renamed to `kabir`; kept as an alias so existing imports keep working. */
2
-
3
- export { createAvatar } from './kabir.js';
4
- export type { CanvasAvatarOptions } from './createCanvasAvatar.js';
package/client/vikram.ts DELETED
@@ -1,26 +0,0 @@
1
- /** Polished professional male avatar, authored to read at call-tile size. */
2
-
3
- import { createCanvasAvatar } from './createCanvasAvatar.js';
4
- import type { CanvasAvatarOptions } from './createCanvasAvatar.js';
5
- import type { AvatarInstance } from './createAvatar.js';
6
-
7
- const RIG_URL = new URL('../src/canvas/data/professional-male-a.rig.json', import.meta.url);
8
- const IMAGES = {
9
- 'professional-male-a-top-body.webp': new URL('../src/canvas/data/img/professional-male-a-top-body.webp', import.meta.url),
10
- 'professional-male-a-hair-back.webp': new URL('../src/canvas/data/img/professional-male-a-hair-back.webp', import.meta.url),
11
- 'professional-male-a-hair-front.webp': new URL('../src/canvas/data/img/professional-male-a-hair-front.webp', import.meta.url),
12
- } as const;
13
- const FACE = () => import('../src/canvas/avatars/round/face.mjs');
14
-
15
- export type { CanvasAvatarOptions };
16
- // Same mixer, same clip library, so the same declaration (`supports.ts`).
17
- export { supports } from './supports.js';
18
-
19
- export function createAvatar(options: CanvasAvatarOptions): AvatarInstance {
20
- return createCanvasAvatar(options, {
21
- rigUrl: RIG_URL,
22
- images: IMAGES,
23
- face: FACE,
24
- label: 'Vikram — polished professional male avatar',
25
- });
26
- }
package/dist/arjun.d.ts DELETED
@@ -1,7 +0,0 @@
1
- /** Professional Indian male interviewer, authored to read at call-tile size. */
2
- import type { CanvasAvatarOptions } from './createCanvasAvatar.js';
3
- import type { AvatarInstance } from './createAvatar.js';
4
- export type { CanvasAvatarOptions };
5
- export { supports } from './supports.js';
6
- export declare function createAvatar(options: CanvasAvatarOptions): AvatarInstance;
7
- //# sourceMappingURL=arjun.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"arjun.d.ts","sourceRoot":"","sources":["../client/arjun.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAGhF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAUxD,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,cAAc,CAOzE"}
package/dist/arjun.js DELETED
@@ -1,20 +0,0 @@
1
- /** Professional Indian male interviewer, authored to read at call-tile size. */
2
- import { createCanvasAvatar } from './createCanvasAvatar.js';
3
- const RIG_URL = new URL('../src/canvas/data/interviewer-male.rig.json', import.meta.url);
4
- const IMAGES = {
5
- 'round-m3-hair-back.webp': new URL('../src/canvas/data/img/round-m3-hair-back.webp', import.meta.url),
6
- 'round-m3-top-body.webp': new URL('../src/canvas/data/img/round-m3-top-body.webp', import.meta.url),
7
- 'round-m3-hair-front.webp': new URL('../src/canvas/data/img/round-m3-hair-front.webp', import.meta.url),
8
- };
9
- const FACE = () => import('../src/canvas/avatars/round/face.mjs');
10
- // Same mixer, same clip library, so the same declaration (`supports.ts`).
11
- export { supports } from './supports.js';
12
- export function createAvatar(options) {
13
- return createCanvasAvatar(options, {
14
- rigUrl: RIG_URL,
15
- images: IMAGES,
16
- face: FACE,
17
- label: 'Arjun — professional male interviewer avatar',
18
- });
19
- }
20
- //# sourceMappingURL=arjun.js.map
package/dist/arjun.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"arjun.js","sourceRoot":"","sources":["../client/arjun.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAI7D,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,8CAA8C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzF,MAAM,MAAM,GAAG;IACb,yBAAyB,EAAE,IAAI,GAAG,CAAC,gDAAgD,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;IACrG,wBAAwB,EAAE,IAAI,GAAG,CAAC,+CAA+C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;IACnG,0BAA0B,EAAE,IAAI,GAAG,CAAC,iDAAiD,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;CAC/F,CAAC;AACX,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,sCAAsC,CAAC,CAAC;AAGlE,0EAA0E;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,UAAU,YAAY,CAAC,OAA4B;IACvD,OAAO,kBAAkB,CAAC,OAAO,EAAE;QACjC,MAAM,EAAE,OAAO;QACf,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,8CAA8C;KACtD,CAAC,CAAC;AACL,CAAC"}
@@ -1,22 +0,0 @@
1
- /** Shared private constructor for the code-authored canvas avatars. */
2
- import type { Gain } from '../src/avatar.js';
3
- import type { AvatarInstance, AvatarOptions } from './createAvatar.js';
4
- export interface CanvasAvatarOptions extends AvatarOptions {
5
- /** Viseme amplitude, 0..2. `1` is as authored. */
6
- readonly mouthGain?: Gain;
7
- /** Gesture-clip amplitude, 0..2. */
8
- readonly gestureGain?: Gain;
9
- /** Idle/liveness amplitude, 0..2. */
10
- readonly motionGain?: Gain;
11
- }
12
- /** @deprecated Use `CanvasAvatarOptions`; kept for the original entry points. */
13
- export type InterviewerAvatarOptions = CanvasAvatarOptions;
14
- interface CanvasAvatarConfig {
15
- readonly rigUrl: URL;
16
- readonly images: Readonly<Record<string, URL>>;
17
- readonly face: () => Promise<unknown>;
18
- readonly label: string;
19
- }
20
- export declare function createCanvasAvatar(options: CanvasAvatarOptions, config: CanvasAvatarConfig): AvatarInstance;
21
- export {};
22
- //# sourceMappingURL=createCanvasAvatar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createCanvasAvatar.d.ts","sourceRoot":"","sources":["../client/createCanvasAvatar.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAIvE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvE,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,kDAAkD;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC;CAC5B;AAED,iFAAiF;AACjF,MAAM,MAAM,wBAAwB,GAAG,mBAAmB,CAAC;AAE3D,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAQD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,mBAAmB,EAC5B,MAAM,EAAE,kBAAkB,GACzB,cAAc,CAkChB"}
@@ -1,47 +0,0 @@
1
- /** Shared private constructor for the code-authored canvas avatars. */
2
- import { createAvatar as createMixer, STATES } from '../src/avatar.js';
3
- import { createCanvasRig } from '../src/canvas/create-rig.js';
4
- import { AvatarClient } from './AvatarClient.js';
5
- const GAINS = ['mouthGain', 'gestureGain', 'motionGain'];
6
- const PRESENCE_FILTERS = {
7
- DEGRADED: String(STATES.DEGRADED.filter ?? ''),
8
- OFFLINE: String(STATES.OFFLINE.filter ?? ''),
9
- };
10
- export function createCanvasAvatar(options, config) {
11
- const { mount, client, ...gains } = options;
12
- if (!mount)
13
- throw new TypeError('createAvatar: `mount` is required');
14
- if (!client)
15
- throw new TypeError('createAvatar: `client` is required');
16
- for (const key of GAINS) {
17
- const gain = gains[key];
18
- if (gain === undefined)
19
- continue;
20
- if (!Number.isFinite(gain) || gain < 0 || gain > 2) {
21
- throw new RangeError(`createAvatar: \`${key}\` must be 0..2, got ${String(gain)}`);
22
- }
23
- }
24
- const canvas = createCanvasRig({
25
- url: config.rigUrl,
26
- images: config.images,
27
- face: config.face,
28
- label: config.label,
29
- });
30
- const widget = createMixer({ mount, rig: canvas.factory, ...gains });
31
- const driver = new AvatarClient(widget, {
32
- onPresenceChange: (state) => canvas.setPresenceFilter(PRESENCE_FILTERS[state] ?? ''),
33
- });
34
- const detach = driver.attach(client);
35
- let destroyed = false;
36
- return {
37
- destroy() {
38
- if (destroyed)
39
- return;
40
- destroyed = true;
41
- detach();
42
- driver.destroy();
43
- widget.destroy();
44
- },
45
- };
46
- }
47
- //# sourceMappingURL=createCanvasAvatar.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createCanvasAvatar.js","sourceRoot":"","sources":["../client/createCanvasAvatar.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAGvE,OAAO,EAAE,YAAY,IAAI,WAAW,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAsBjD,MAAM,KAAK,GAAG,CAAC,WAAW,EAAE,aAAa,EAAE,YAAY,CAAU,CAAC;AAClE,MAAM,gBAAgB,GAAqC;IACzD,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC;IAC9C,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;CAC7C,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAChC,OAA4B,EAC5B,MAA0B;IAE1B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAC5C,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,SAAS,CAAC,oCAAoC,CAAC,CAAC;IACvE,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,UAAU,CAAC,mBAAmB,GAAG,wBAAwB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,CAAC;QAC7B,GAAG,EAAE,MAAM,CAAC,MAAM;QAClB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IACrE,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE;QACtC,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;KACrF,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAuB,CAAC,CAAC;IAEtD,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,OAAO;QACL,OAAO;YACL,IAAI,SAAS;gBAAE,OAAO;YACtB,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,4 +0,0 @@
1
- /** @deprecated Renamed to `meera`; kept as an alias so existing imports keep working. */
2
- export { createAvatar } from './meera.js';
3
- export type { CanvasAvatarOptions, CanvasAvatarOptions as InterviewerAvatarOptions } from './createCanvasAvatar.js';
4
- //# sourceMappingURL=interviewer-female.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interviewer-female.d.ts","sourceRoot":"","sources":["../client/interviewer-female.ts"],"names":[],"mappings":"AAAA,yFAAyF;AAEzF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,IAAI,wBAAwB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,3 +0,0 @@
1
- /** @deprecated Renamed to `meera`; kept as an alias so existing imports keep working. */
2
- export { createAvatar } from './meera.js';
3
- //# sourceMappingURL=interviewer-female.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interviewer-female.js","sourceRoot":"","sources":["../client/interviewer-female.ts"],"names":[],"mappings":"AAAA,yFAAyF;AAEzF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
@@ -1,4 +0,0 @@
1
- /** @deprecated Renamed to `arjun`; kept as an alias so existing imports keep working. */
2
- export { createAvatar } from './arjun.js';
3
- export type { CanvasAvatarOptions, CanvasAvatarOptions as InterviewerAvatarOptions } from './createCanvasAvatar.js';
4
- //# sourceMappingURL=interviewer-male.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interviewer-male.d.ts","sourceRoot":"","sources":["../client/interviewer-male.ts"],"names":[],"mappings":"AAAA,yFAAyF;AAEzF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,IAAI,wBAAwB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,3 +0,0 @@
1
- /** @deprecated Renamed to `arjun`; kept as an alias so existing imports keep working. */
2
- export { createAvatar } from './arjun.js';
3
- //# sourceMappingURL=interviewer-male.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interviewer-male.js","sourceRoot":"","sources":["../client/interviewer-male.ts"],"names":[],"mappings":"AAAA,yFAAyF;AAEzF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
package/dist/ishita.d.ts DELETED
@@ -1,7 +0,0 @@
1
- /** Polished professional female avatar, authored to read at call-tile size. */
2
- import type { CanvasAvatarOptions } from './createCanvasAvatar.js';
3
- import type { AvatarInstance } from './createAvatar.js';
4
- export type { CanvasAvatarOptions };
5
- export { supports } from './supports.js';
6
- export declare function createAvatar(options: CanvasAvatarOptions): AvatarInstance;
7
- //# sourceMappingURL=ishita.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ishita.d.ts","sourceRoot":"","sources":["../client/ishita.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAG/E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAUxD,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,cAAc,CAOzE"}