@phont-ai/subtitles-core 0.1.10 → 0.2.1
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.
- package/README.md +51 -0
- package/dist/browser.d.mts +140 -0
- package/dist/browser.d.ts +140 -0
- package/dist/browser.js +1 -0
- package/dist/browser.mjs +1 -0
- package/dist/index.d.mts +501 -407
- package/dist/index.d.ts +1437 -7
- package/dist/index.js +3 -5414
- package/dist/index.mjs +3 -5347
- package/dist/phont-subtitles.global.js +2 -0
- package/package.json +37 -14
- package/dist/client/PhontClient.d.ts +0 -16
- package/dist/types/registration.d.ts +0 -46
- package/dist/utils/video-handling.d.ts +0 -33
- package/dist/validation/registration.d.ts +0 -64
package/dist/index.d.mts
CHANGED
|
@@ -45,6 +45,125 @@ interface PhontClientOptions {
|
|
|
45
45
|
apiBaseUrl?: string;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Animation Types
|
|
50
|
+
*
|
|
51
|
+
* Type definitions for animation parameter states, curves, and animation state
|
|
52
|
+
*/
|
|
53
|
+
interface CurvePoint {
|
|
54
|
+
time: number;
|
|
55
|
+
value: number | string;
|
|
56
|
+
}
|
|
57
|
+
interface ParameterState {
|
|
58
|
+
points: CurvePoint[];
|
|
59
|
+
currentValue?: number | string;
|
|
60
|
+
}
|
|
61
|
+
interface ParameterStates {
|
|
62
|
+
[key: string]: ParameterState;
|
|
63
|
+
}
|
|
64
|
+
interface AnimationParameterStates {
|
|
65
|
+
parameterStates: ParameterStates;
|
|
66
|
+
duration?: number;
|
|
67
|
+
format?: 'normalized' | 'absolute';
|
|
68
|
+
fontData?: {
|
|
69
|
+
style?: {
|
|
70
|
+
fontFamily?: string;
|
|
71
|
+
[key: string]: unknown;
|
|
72
|
+
};
|
|
73
|
+
config?: unknown;
|
|
74
|
+
fontId?: string | null;
|
|
75
|
+
fontName?: string | null;
|
|
76
|
+
};
|
|
77
|
+
text?: string;
|
|
78
|
+
name?: string;
|
|
79
|
+
}
|
|
80
|
+
interface AnimationState {
|
|
81
|
+
fontSize: number;
|
|
82
|
+
scale: number;
|
|
83
|
+
opacity: number;
|
|
84
|
+
slant: number;
|
|
85
|
+
weight: number;
|
|
86
|
+
width: number;
|
|
87
|
+
textColor: string;
|
|
88
|
+
translateX: number;
|
|
89
|
+
translateY: number;
|
|
90
|
+
stretchY: number;
|
|
91
|
+
rotation?: number;
|
|
92
|
+
skewX?: number;
|
|
93
|
+
fontVariationAxes?: Record<string, number>;
|
|
94
|
+
letterShake?: number;
|
|
95
|
+
shadowColor?: string;
|
|
96
|
+
}
|
|
97
|
+
interface SentenceAnimationState extends AnimationState {
|
|
98
|
+
text: string;
|
|
99
|
+
emotion: string;
|
|
100
|
+
emotionIntensity: number;
|
|
101
|
+
fontFamily: string;
|
|
102
|
+
startTime: number;
|
|
103
|
+
endTime: number;
|
|
104
|
+
duration: number;
|
|
105
|
+
isActive: boolean;
|
|
106
|
+
}
|
|
107
|
+
interface WordAnimationState {
|
|
108
|
+
text: string;
|
|
109
|
+
words: Array<{
|
|
110
|
+
word: string;
|
|
111
|
+
start: number;
|
|
112
|
+
end: number;
|
|
113
|
+
animationEnd: number;
|
|
114
|
+
isActive: boolean;
|
|
115
|
+
emotion: string;
|
|
116
|
+
emotionIntensity: number;
|
|
117
|
+
originalEmotionIntensity?: number;
|
|
118
|
+
fontFamily: string;
|
|
119
|
+
emphasis: number;
|
|
120
|
+
emphasisEffect?: any;
|
|
121
|
+
strongEmphasis?: any;
|
|
122
|
+
animationParameters: AnimationState;
|
|
123
|
+
joyAnimationMode?: 'letter' | 'letter-bulge' | 'word' | null;
|
|
124
|
+
joyProgress?: number | null;
|
|
125
|
+
}>;
|
|
126
|
+
currentWordIndex: number;
|
|
127
|
+
emotion: string;
|
|
128
|
+
emotionIntensity: number;
|
|
129
|
+
fontFamily: string;
|
|
130
|
+
startTime: number;
|
|
131
|
+
endTime: number;
|
|
132
|
+
isActive: boolean;
|
|
133
|
+
}
|
|
134
|
+
interface SubtitleSegment {
|
|
135
|
+
start_time: number;
|
|
136
|
+
end_time: number;
|
|
137
|
+
text?: string;
|
|
138
|
+
subtitle?: string;
|
|
139
|
+
emotion?: string;
|
|
140
|
+
emotion_intensity?: number;
|
|
141
|
+
animation_url?: string;
|
|
142
|
+
words?: Array<{
|
|
143
|
+
word: string;
|
|
144
|
+
start: number;
|
|
145
|
+
end: number;
|
|
146
|
+
emphasis?: number;
|
|
147
|
+
emotion?: string;
|
|
148
|
+
emotion_intensity?: number;
|
|
149
|
+
animation_url?: string;
|
|
150
|
+
animations?: Record<string, number>;
|
|
151
|
+
}>;
|
|
152
|
+
animations?: Record<string, number>;
|
|
153
|
+
volume?: number;
|
|
154
|
+
speech_rate?: number;
|
|
155
|
+
merged_subtitles?: SubtitleSegment[];
|
|
156
|
+
}
|
|
157
|
+
interface AnimationOptions {
|
|
158
|
+
maxExpression?: number;
|
|
159
|
+
threshold?: number;
|
|
160
|
+
isRTL?: boolean;
|
|
161
|
+
volume?: number;
|
|
162
|
+
speechRate?: number;
|
|
163
|
+
nextSegmentStartTime?: number;
|
|
164
|
+
extendedEndTime?: number;
|
|
165
|
+
}
|
|
166
|
+
|
|
48
167
|
/**
|
|
49
168
|
* ============================================
|
|
50
169
|
* SUBTITLE STATE MANAGER
|
|
@@ -164,12 +283,12 @@ declare class SubtitleStateManager {
|
|
|
164
283
|
*
|
|
165
284
|
* STATUS: Phase 2 Complete - All 8 classes extracted, clean architecture, no duplication
|
|
166
285
|
*/
|
|
167
|
-
type AnimationMode = "Sentence" | "Word" | string;
|
|
286
|
+
type AnimationMode$1 = "Sentence" | "Word" | string;
|
|
168
287
|
interface SubtitleState {
|
|
169
288
|
isVisible: boolean;
|
|
170
289
|
isKaraokeMode: boolean;
|
|
171
290
|
isSpeaker: boolean;
|
|
172
|
-
animationMode: AnimationMode;
|
|
291
|
+
animationMode: AnimationMode$1;
|
|
173
292
|
currentSubtitle: string;
|
|
174
293
|
currentSequence: number | null;
|
|
175
294
|
subtitles: any[];
|
|
@@ -242,7 +361,7 @@ declare class SubtitleManager {
|
|
|
242
361
|
toggleSoundbiteAnimations(isVisible: boolean): void;
|
|
243
362
|
mapEventLabelToAnimation(eventLabel: string): string | null;
|
|
244
363
|
processSoundbiteAnimations(soundbites: any[]): any[];
|
|
245
|
-
setAnimationMode(mode: AnimationMode): void;
|
|
364
|
+
setAnimationMode(mode: AnimationMode$1): void;
|
|
246
365
|
toggleTransition(enabled: boolean): void;
|
|
247
366
|
updateSubtitle(text: string): void;
|
|
248
367
|
updateLiveTime(videoTime?: number | null): number;
|
|
@@ -262,7 +381,7 @@ declare class SubtitleManager {
|
|
|
262
381
|
getInitialLiveSequenceNumber(): Promise<number>;
|
|
263
382
|
fetchSubtitles(sequenceNumber: number): Promise<any | null>;
|
|
264
383
|
loadVodSubtitles(urlOrVodId: string, languageCode?: string | null): Promise<void>;
|
|
265
|
-
_processVodData(data: any, url: string, languageCode: string | null): void;
|
|
384
|
+
_processVodData(data: any, url: string, languageCode: string | null, originalSubtitles?: any[]): void;
|
|
266
385
|
getSubtitleForTime(time: number): any;
|
|
267
386
|
getLiveSubtitleForTime(): any;
|
|
268
387
|
getCurrentSubtitleData(): any | null;
|
|
@@ -293,106 +412,186 @@ declare class SubtitleManager {
|
|
|
293
412
|
declare const subtitleManager: SubtitleManager;
|
|
294
413
|
|
|
295
414
|
/**
|
|
296
|
-
* Animation
|
|
415
|
+
* URL Decoder for Animation Parameters
|
|
297
416
|
*
|
|
298
|
-
*
|
|
417
|
+
* Extracted from app/playground/utils/urlEncoding.js
|
|
418
|
+
* Decodes animation URLs into parameter states
|
|
419
|
+
*
|
|
420
|
+
* Supports both full URLs and query strings:
|
|
421
|
+
* - Full URL: https://stage-dev.phont.ai/playground/shared?name=...&scale=0,1|1,1.2
|
|
422
|
+
* - Query string: ?name=...&scale=0,1|1,1.2
|
|
299
423
|
*/
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Decode animation data from URL or query string
|
|
427
|
+
* @param urlOrQuery - Full URL (https://...) or query string (?name=... or name=...)
|
|
428
|
+
* @returns Decoded animation data object with parameterStates
|
|
429
|
+
*/
|
|
430
|
+
declare function decodeAnimationUrl(urlOrQuery: string): AnimationParameterStates;
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Animation parameter calculation -- the unified rendering pipeline.
|
|
434
|
+
* TypeScript port of app/utils/animation/animationParameters.js.
|
|
435
|
+
*
|
|
436
|
+
* Samples authored URL curves with linear interpolation, then scales deviations
|
|
437
|
+
* proportionally from a reference point (REFERENCE_INTENSITY × REFERENCE_GTS).
|
|
438
|
+
* At the reference point the authored curve is rendered 1:1.
|
|
439
|
+
*/
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Exponential variance curve (hockey stick)
|
|
443
|
+
*
|
|
444
|
+
* Creates an exponential curve that accelerates dramatically after 0.7 intensity.
|
|
445
|
+
* Low intensities (0.0-0.7): Subtle effects (gradual rise)
|
|
446
|
+
* High intensities (0.7-1.0): Dramatic effects (exponential acceleration)
|
|
447
|
+
*
|
|
448
|
+
* @param i - Input intensity (0-1)
|
|
449
|
+
* @returns Transformed intensity (0-1) with exponential variance
|
|
450
|
+
*/
|
|
451
|
+
declare function hockeyStickIntensity(i: number): number;
|
|
452
|
+
/**
|
|
453
|
+
* Sample a parameter curve at a given time
|
|
454
|
+
*
|
|
455
|
+
* Interpolates between keyframe points to get the value at a specific time.
|
|
456
|
+
* Supports both normalized (0-1) and absolute time formats.
|
|
457
|
+
* For color parameters, uses RGB interpolation for smooth color transitions.
|
|
458
|
+
*
|
|
459
|
+
* @param points - Array of {time, value} points or [time, value] arrays
|
|
460
|
+
* @param t - Normalized time (0-1)
|
|
461
|
+
* @param duration - Animation duration in seconds
|
|
462
|
+
* @param isNormalized - Whether points are in normalized (0-1) or absolute time
|
|
463
|
+
* @param parameterName - Name of the parameter (e.g., 'color', 'shadowColor', 'outlineColor') for color interpolation
|
|
464
|
+
* @returns Sampled value or null if no points
|
|
465
|
+
*/
|
|
466
|
+
declare function sampleParameterCurve(points: Array<{
|
|
467
|
+
time?: number;
|
|
468
|
+
value?: number | string;
|
|
469
|
+
} | [number, number | string]> | undefined | null, t: number, duration: number, isNormalized?: boolean, parameterName?: string | null): number | string | null;
|
|
470
|
+
interface AnimationParameterState {
|
|
471
|
+
rawIntensity: number;
|
|
472
|
+
scaleFactor: number;
|
|
318
473
|
scale: number;
|
|
319
|
-
opacity: number;
|
|
320
474
|
slant: number;
|
|
475
|
+
stretchY: number;
|
|
476
|
+
translateX: number;
|
|
477
|
+
translateY: number;
|
|
321
478
|
weight: number;
|
|
322
479
|
width: number;
|
|
480
|
+
fontFamily: string;
|
|
323
481
|
textColor: string;
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
482
|
+
opacity: number;
|
|
483
|
+
textShadow: string;
|
|
484
|
+
blur: number;
|
|
485
|
+
outlineWidth: number;
|
|
486
|
+
outlineColor: string;
|
|
487
|
+
outline2Width?: number;
|
|
488
|
+
outline2Color?: string;
|
|
489
|
+
outline3Width?: number;
|
|
490
|
+
outline3Color?: string;
|
|
491
|
+
outlineShadowWidth?: number;
|
|
492
|
+
outlineShadowColor?: string;
|
|
493
|
+
outlineShadowBlur?: number;
|
|
494
|
+
glowIntensity?: number;
|
|
495
|
+
glowColor?: string;
|
|
496
|
+
snakeWave?: number;
|
|
497
|
+
karaoke?: number;
|
|
498
|
+
stretchX?: number;
|
|
499
|
+
letterSpacing: string;
|
|
500
|
+
fontVariationAxes: Record<string, number>;
|
|
335
501
|
text: string;
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
duration: number;
|
|
342
|
-
isActive: boolean;
|
|
502
|
+
joy: number;
|
|
503
|
+
fear: number;
|
|
504
|
+
standardEmphasis: number;
|
|
505
|
+
strongEmphasis: number;
|
|
506
|
+
joyWaveProgress: number;
|
|
343
507
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
508
|
+
declare const REFERENCE_INTENSITY = 0.7;
|
|
509
|
+
declare const REFERENCE_GTS = 0.7;
|
|
510
|
+
/**
|
|
511
|
+
* Sample all animation parameters at time `t` with proportional intensity scaling.
|
|
512
|
+
*
|
|
513
|
+
* The authored curve represents the animation at REFERENCE_INTENSITY × REFERENCE_GTS.
|
|
514
|
+
* At those values you see exactly what was authored. Other intensity × GTS values
|
|
515
|
+
* scale linearly from there.
|
|
516
|
+
*/
|
|
517
|
+
declare function calculateAnimationParameters(animationData: AnimationParameterStates | null, rawIntensity: number, t: number, gts: number, subtitleDuration?: number | null, { rawMode }?: {
|
|
518
|
+
rawMode?: boolean;
|
|
519
|
+
}): AnimationParameterState | null;
|
|
520
|
+
|
|
521
|
+
type AnimationMode = 'sentence' | 'word';
|
|
522
|
+
type AnimationStateOptions = AnimationOptions & {
|
|
523
|
+
transparentUntilSpoken?: boolean;
|
|
524
|
+
};
|
|
525
|
+
declare function calculateAnimationState(segment: SubtitleSegment | null, currentTime: number, modeOrOptions?: AnimationMode | AnimationStateOptions, maybeOptions?: AnimationStateOptions): SentenceAnimationState | WordAnimationState;
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Emotion Animation URLs
|
|
529
|
+
*
|
|
530
|
+
* Config mapping emotion → animation URL
|
|
531
|
+
* Uses full playground URLs from app/gallery/config/animations.js
|
|
532
|
+
*
|
|
533
|
+
* SYNCED FROM: app/gallery/config/emotionMapping.js
|
|
534
|
+
*
|
|
535
|
+
* To update these URLs:
|
|
536
|
+
* 1. Update app/gallery/config/animations.js with new URLs
|
|
537
|
+
* 2. Update app/gallery/config/emotionMapping.js to map emotions to indices
|
|
538
|
+
* 3. Run: node scripts/sync-animation-urls.js
|
|
539
|
+
* OR manually copy the URLs based on the mapping
|
|
540
|
+
*
|
|
541
|
+
* The decodeAnimationUrl() function now supports both full URLs and query strings.
|
|
542
|
+
*/
|
|
543
|
+
declare const ANIMATION_URLS: string[];
|
|
544
|
+
/**
|
|
545
|
+
* Emotion to Animation URL mapping
|
|
546
|
+
* Based on app/gallery/config/emotionMapping.js
|
|
547
|
+
*
|
|
548
|
+
* Maps each emotion to an index in ANIMATION_URLS array
|
|
549
|
+
*/
|
|
550
|
+
declare const EMOTION_ANIMATION_URLS: Record<string, string>;
|
|
551
|
+
/**
|
|
552
|
+
* Get animation URL for an emotion
|
|
553
|
+
* @param emotion - Emotion name (case-insensitive)
|
|
554
|
+
* @returns Full animation URL or query string fallback
|
|
555
|
+
*/
|
|
556
|
+
declare function getAnimationUrlForEmotion(emotion: string): string;
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Published Animation Resolver (framework-agnostic)
|
|
560
|
+
*
|
|
561
|
+
* Fetches the active published animation URL for each emotion from the backend,
|
|
562
|
+
* caches the results, and provides sync/async accessors.
|
|
563
|
+
*
|
|
564
|
+
* Any consumer (app, SDK, extension) creates an instance by supplying a fetcher
|
|
565
|
+
* that returns an array of animation objects for a given stylesheet.
|
|
566
|
+
*
|
|
567
|
+
* USAGE:
|
|
568
|
+
* import { createPublishedAnimationResolver } from '@phont-ai/subtitles-core';
|
|
569
|
+
*
|
|
570
|
+
* const resolver = createPublishedAnimationResolver(
|
|
571
|
+
* async (stylesheet) => fetch(`/animations?stylesheet_name=${stylesheet}&is_active=true`).then(r => r.json())
|
|
572
|
+
* );
|
|
573
|
+
*
|
|
574
|
+
* await resolver.prefetch('default'); // warm the cache
|
|
575
|
+
* const url = resolver.getSync('lust'); // sync (returns null if not cached)
|
|
576
|
+
* const url = await resolver.get('lust'); // async (fetches if needed)
|
|
577
|
+
* resolver.invalidate(); // bust after publishing
|
|
578
|
+
*/
|
|
579
|
+
interface AnimationRecord {
|
|
364
580
|
emotion: string;
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
endTime: number;
|
|
369
|
-
isActive: boolean;
|
|
370
|
-
}
|
|
371
|
-
interface SubtitleSegment {
|
|
372
|
-
start_time: number;
|
|
373
|
-
end_time: number;
|
|
374
|
-
text?: string;
|
|
375
|
-
subtitle?: string;
|
|
376
|
-
words?: Array<{
|
|
377
|
-
word: string;
|
|
378
|
-
start: number;
|
|
379
|
-
end: number;
|
|
380
|
-
emphasis?: number;
|
|
381
|
-
}>;
|
|
382
|
-
animations?: Record<string, number>;
|
|
383
|
-
volume?: number;
|
|
384
|
-
speech_rate?: number;
|
|
385
|
-
merged_subtitles?: SubtitleSegment[];
|
|
581
|
+
url: string;
|
|
582
|
+
is_active: boolean;
|
|
583
|
+
[key: string]: unknown;
|
|
386
584
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
nextSegmentStartTime?: number;
|
|
394
|
-
extendedEndTime?: number;
|
|
585
|
+
type AnimationFetcher = (stylesheetName: string) => Promise<AnimationRecord[]>;
|
|
586
|
+
interface PublishedAnimationResolver {
|
|
587
|
+
prefetch: (stylesheetName?: string) => Promise<Map<string, string>>;
|
|
588
|
+
get: (emotion: string, stylesheetName?: string) => Promise<string | null>;
|
|
589
|
+
getSync: (emotion: string, stylesheetName?: string) => string | null;
|
|
590
|
+
invalidate: () => void;
|
|
395
591
|
}
|
|
592
|
+
declare function createPublishedAnimationResolver(fetcher: AnimationFetcher, { ttlMs }?: {
|
|
593
|
+
ttlMs?: number;
|
|
594
|
+
}): PublishedAnimationResolver;
|
|
396
595
|
|
|
397
596
|
/**
|
|
398
597
|
* Emotion Selector
|
|
@@ -421,86 +620,24 @@ interface EmotionSelectionResult {
|
|
|
421
620
|
declare function selectEmotion(animationsObject: Record<string, number> | null | undefined, threshold?: number): EmotionSelectionResult;
|
|
422
621
|
|
|
423
622
|
/**
|
|
424
|
-
*
|
|
623
|
+
* Timing Utilities
|
|
425
624
|
*
|
|
426
|
-
* Pure functions
|
|
427
|
-
* Uses function-based EMOTION_ANIMATIONS (identical to monorepo)
|
|
625
|
+
* Pure functions for calculating subtitle timing
|
|
428
626
|
*/
|
|
429
627
|
|
|
430
628
|
/**
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
* Pure function version of useSentenceAnimation - uses function-based EMOTION_ANIMATIONS (identical to monorepo)
|
|
629
|
+
* Get subtitle timing information
|
|
434
630
|
*/
|
|
435
|
-
declare function
|
|
631
|
+
declare function getSubtitleTiming(subtitle: SubtitleSegment | null): {
|
|
632
|
+
startTime: number;
|
|
633
|
+
endTime: number;
|
|
634
|
+
duration: number;
|
|
635
|
+
};
|
|
436
636
|
/**
|
|
437
|
-
* Calculate
|
|
438
|
-
*
|
|
439
|
-
* Pure function version of useWordAnimation - uses function-based EMOTION_ANIMATIONS (identical to monorepo)
|
|
637
|
+
* Calculate normalized time (t: 0→1) through subtitle duration
|
|
440
638
|
*/
|
|
441
|
-
declare function
|
|
442
|
-
|
|
443
|
-
* Main function: Calculate animation state from segment and emotion
|
|
444
|
-
*
|
|
445
|
-
* This is the main entry point that uses function-based EMOTION_ANIMATIONS (identical to monorepo)
|
|
446
|
-
*/
|
|
447
|
-
declare function calculateAnimationState(segment: SubtitleSegment | null, currentTime: number, mode: 'sentence' | 'word', options?: AnimationOptions): SentenceAnimationState | WordAnimationState;
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Timing Utilities
|
|
451
|
-
*
|
|
452
|
-
* Pure functions for calculating subtitle timing
|
|
453
|
-
*/
|
|
454
|
-
|
|
455
|
-
/**
|
|
456
|
-
* Get subtitle timing information
|
|
457
|
-
*/
|
|
458
|
-
declare function getSubtitleTiming(subtitle: SubtitleSegment | null): {
|
|
459
|
-
startTime: number;
|
|
460
|
-
endTime: number;
|
|
461
|
-
duration: number;
|
|
462
|
-
};
|
|
463
|
-
/**
|
|
464
|
-
* Get subtitle text content
|
|
465
|
-
*/
|
|
466
|
-
declare function getSubtitleText(subtitle: SubtitleSegment | null): string;
|
|
467
|
-
/**
|
|
468
|
-
* Calculate normalized time (t: 0→1) through subtitle duration
|
|
469
|
-
*/
|
|
470
|
-
declare function calculateNormalizedTime(currentTime: number, startTime: number, duration: number): number;
|
|
471
|
-
|
|
472
|
-
/**
|
|
473
|
-
* **EMOTION_CURVES_DEFINITION** - Animation DNA
|
|
474
|
-
*
|
|
475
|
-
* Emotion Curves - Animation Parameter Definitions
|
|
476
|
-
*
|
|
477
|
-
* These curves define how subtitle text animates over time based on emotion.
|
|
478
|
-
* Each emotion has time-based functions that return values for visual parameters.
|
|
479
|
-
*
|
|
480
|
-
* PARAMETERS:
|
|
481
|
-
* - fontSize: Always constant (ANIMATION_STYLING.fontSize) for layout stability
|
|
482
|
-
* - scale: Size multiplier applied via CSS transform (prevents text wrapping)
|
|
483
|
-
* - slant: Italic/skew effect in degrees (applied as CSS skewX)
|
|
484
|
-
* - weight: Font weight (100-900) - overridden by VariableFontContext in practice
|
|
485
|
-
* - translateX/Y: Movement in pixels (direct CSS values)
|
|
486
|
-
* - textColor: Text color (rgba)
|
|
487
|
-
* - stretchY: Vertical stretch multiplier (CSS scaleY)
|
|
488
|
-
* - letterShakeIntensity: Per-letter shake amount in pixels (fear)
|
|
489
|
-
*
|
|
490
|
-
* WHY SCALE INSTEAD OF FONTSIZE:
|
|
491
|
-
* Using transform: scale() instead of fontSize changes allows the layout engine
|
|
492
|
-
* to calculate word positions ONCE at the base fontSize, preventing words from
|
|
493
|
-
* wrapping to new lines mid-animation. Scale is GPU-accelerated and doesn't trigger reflow.
|
|
494
|
-
*
|
|
495
|
-
* ⚠️ Parameters NOT included (handled elsewhere):
|
|
496
|
-
* - opacity: Always 1.0 (fade in/out handled by controllers)
|
|
497
|
-
* - shadows: Handled by styling.js ANIMATION_STYLING.shadow (emotion-specific for disgust/angry)
|
|
498
|
-
* - font family: Handled by fontSelection.js based on emotion + intensity
|
|
499
|
-
* - transitions: Handled by styling.js ANIMATION_STYLING.transition
|
|
500
|
-
* - marginRight: Handled by calculateDynamicWordSpacing() based on current scale
|
|
501
|
-
*/
|
|
502
|
-
declare const EMOTION_ANIMATIONS: Record<string, any>;
|
|
503
|
-
|
|
639
|
+
declare function calculateNormalizedTime(currentTime: number, startTime: number, duration: number): number;
|
|
640
|
+
|
|
504
641
|
/**
|
|
505
642
|
* Animation Defaults - Visual Styling Layer
|
|
506
643
|
*
|
|
@@ -572,6 +709,11 @@ declare const ANIMATION_STYLING: {
|
|
|
572
709
|
wordSpacingMultiplier: number;
|
|
573
710
|
fontSizeOffset: number;
|
|
574
711
|
};
|
|
712
|
+
'Bricolage Grotesque': {
|
|
713
|
+
letterSpacing: string;
|
|
714
|
+
wordSpacingMultiplier: number;
|
|
715
|
+
fontSizeOffset: number;
|
|
716
|
+
};
|
|
575
717
|
Rakkas: {
|
|
576
718
|
letterSpacing: string;
|
|
577
719
|
wordSpacingMultiplier: number;
|
|
@@ -703,81 +845,22 @@ declare const RENDERING_CONTROL: {
|
|
|
703
845
|
};
|
|
704
846
|
};
|
|
705
847
|
|
|
706
|
-
/**
|
|
707
|
-
* Shared Animation Parameter Calculation Utility
|
|
708
|
-
*
|
|
709
|
-
* Calculates animation parameters from emotion curves.
|
|
710
|
-
* Shared by calculateWordAnimation and calculateSentenceAnimation to eliminate duplication.
|
|
711
|
-
*
|
|
712
|
-
* This utility extracts all animation parameters defined in EMOTION_ANIMATIONS
|
|
713
|
-
* including variation axes (YOPQ, YTAS) that are separate from voice axes (wght, wdth).
|
|
714
|
-
*
|
|
715
|
-
* TERMINOLOGY:
|
|
716
|
-
* - **Voice Axes**: Font axes driven by audio analysis (volume→wght, speech_rate→wdth)
|
|
717
|
-
* - **Variation Axes**: Font axes driven by emotion animations (YOPQ, YTAS from emotion curves)
|
|
718
|
-
*/
|
|
719
|
-
interface VariableFontStyle {
|
|
720
|
-
fontWeight?: number;
|
|
721
|
-
fontStretch?: string;
|
|
722
|
-
}
|
|
723
|
-
interface AnimationParameters {
|
|
724
|
-
fontSize: number;
|
|
725
|
-
scale: number;
|
|
726
|
-
opacity: number;
|
|
727
|
-
slant: number;
|
|
728
|
-
weight: number;
|
|
729
|
-
width: number;
|
|
730
|
-
textColor: string;
|
|
731
|
-
translateX: number;
|
|
732
|
-
translateY: number;
|
|
733
|
-
stretchY: number;
|
|
734
|
-
letterShake?: number;
|
|
735
|
-
fontVariationAxes?: Record<string, number>;
|
|
736
|
-
shadowColor?: string | ((t: number, intensity: number) => string);
|
|
737
|
-
}
|
|
738
|
-
interface EmotionCurve {
|
|
739
|
-
fontSize?: number | ((t: number, intensity: number) => number);
|
|
740
|
-
scale?: number | ((t: number, intensity: number) => number);
|
|
741
|
-
opacity?: number | ((t: number, intensity: number) => number);
|
|
742
|
-
slant?: number | ((t: number, intensity?: number) => number);
|
|
743
|
-
weight?: number | ((t: number, intensity?: number) => number);
|
|
744
|
-
translateX?: number | ((t: number, intensity: number) => number);
|
|
745
|
-
translateY?: number | ((t: number, intensity: number) => number);
|
|
746
|
-
stretchY?: number | ((t: number, intensity: number) => number);
|
|
747
|
-
textColor?: string | ((t: number, intensity: number) => string);
|
|
748
|
-
shadowColor?: string | ((t: number, intensity: number) => string);
|
|
749
|
-
thinStroke?: (t: number, intensity: number, gtsValue: number) => number;
|
|
750
|
-
ascenderHeight?: (t: number, intensity: number, gtsValue: number) => number;
|
|
751
|
-
letterShake?: (t: number, intensity: number, gtsValue: number) => number;
|
|
752
|
-
}
|
|
753
|
-
/**
|
|
754
|
-
* Calculate animation parameters from emotion curve
|
|
755
|
-
*
|
|
756
|
-
* @param emotionCurve - Emotion curve from EMOTION_ANIMATIONS
|
|
757
|
-
* @param t - Normalized time (0-1) through animation
|
|
758
|
-
* @param intensity - Emotion intensity (0-1), capped by GTS (maxExpression)
|
|
759
|
-
* @param variableFontStyle - Font style from variable font calculations
|
|
760
|
-
* @param gtsValue - GTS maxExpression value (0.2-1.0) for scaling ranges
|
|
761
|
-
* @param selectedFontFamily - The selected font family (e.g., 'Cormorant', 'Roboto Flex')
|
|
762
|
-
* @returns Complete animation parameters including fontVariationAxes (variation axes, not voice axes)
|
|
763
|
-
*/
|
|
764
|
-
declare function calculateAnimationParameters(emotionCurve: EmotionCurve, t: number, intensity: number, variableFontStyle?: VariableFontStyle | null, gtsValue?: number, selectedFontFamily?: string): AnimationParameters;
|
|
765
|
-
|
|
766
848
|
/**
|
|
767
849
|
* Shadow Generator
|
|
768
850
|
*
|
|
769
|
-
* Generates CSS text-shadow strings from shadow colors
|
|
851
|
+
* Generates CSS text-shadow strings from shadow colors
|
|
852
|
+
* All emotion-specific shadows are now controlled by URL animations
|
|
770
853
|
*/
|
|
771
854
|
/**
|
|
772
855
|
* Generate CSS text-shadow string from shadow color
|
|
773
856
|
*
|
|
774
857
|
* @param shadowColor - Shadow color in hex format (e.g., '#ff3232')
|
|
775
|
-
* @param
|
|
776
|
-
* @param
|
|
777
|
-
* @param
|
|
778
|
-
* @returns CSS text-shadow value
|
|
858
|
+
* @param _fontFamily - Unused (kept for API compatibility)
|
|
859
|
+
* @param _emotion - Unused (kept for API compatibility)
|
|
860
|
+
* @param _intensity - Unused (kept for API compatibility)
|
|
861
|
+
* @returns CSS text-shadow value or empty string if no shadow
|
|
779
862
|
*/
|
|
780
|
-
declare function generateTextShadow(shadowColor: string | undefined,
|
|
863
|
+
declare function generateTextShadow(shadowColor: string | undefined, _fontFamily?: string, _emotion?: string, _intensity?: number): string;
|
|
781
864
|
|
|
782
865
|
/**
|
|
783
866
|
* Dynamic Word Spacing Calculator
|
|
@@ -796,6 +879,27 @@ declare function generateTextShadow(shadowColor: string | undefined, fontFamily?
|
|
|
796
879
|
*/
|
|
797
880
|
declare function calculateDynamicWordSpacing(currentScale?: number, fontFamily?: string, gtsIntensity?: number, emotion?: string): string;
|
|
798
881
|
|
|
882
|
+
/**
|
|
883
|
+
* Prosody Weight — Natural Voice Intonation for Animations
|
|
884
|
+
*
|
|
885
|
+
* Only ~20% of words get motion animation, mimicking how natural speech
|
|
886
|
+
* stresses only a few key words per phrase. Font styling (color, weight,
|
|
887
|
+
* slant) is unaffected — this only gates movement.
|
|
888
|
+
*
|
|
889
|
+
* Selection criteria:
|
|
890
|
+
* 1. Function words (the, a, is, and…) → always quiet
|
|
891
|
+
* 2. Content words are scored by length + deterministic hash
|
|
892
|
+
* 3. Only the top ~35% of content words animate
|
|
893
|
+
* (since function/short words are ~55% of text,
|
|
894
|
+
* 35% of remaining 45% ≈ 16-20% of all words)
|
|
895
|
+
*/
|
|
896
|
+
/**
|
|
897
|
+
* Compute a prosody importance weight for a single word.
|
|
898
|
+
*
|
|
899
|
+
* @returns 0 (no motion) or 1 (full motion).
|
|
900
|
+
*/
|
|
901
|
+
declare function computeProsodyWeight(word: any, _emotionIntensity: number, _gts: number): number;
|
|
902
|
+
|
|
799
903
|
/**
|
|
800
904
|
* Joy Animation Effects
|
|
801
905
|
*
|
|
@@ -841,6 +945,131 @@ declare function getJoyTransform(joyEffect: JoyEffect | null): string;
|
|
|
841
945
|
*/
|
|
842
946
|
declare function getJoyFilter(joyEffect: JoyEffect | null): string;
|
|
843
947
|
|
|
948
|
+
/**
|
|
949
|
+
* Word Emphasis Effects
|
|
950
|
+
*
|
|
951
|
+
* Calculates emphasis effects (standard and strong) for words based on confidence levels.
|
|
952
|
+
*
|
|
953
|
+
* USED BY:
|
|
954
|
+
* - calculateWordAnimation: Main word animation orchestrator
|
|
955
|
+
*
|
|
956
|
+
* HOW IT WORKS:
|
|
957
|
+
* 1. Standard Emphasis (50-70%): Quick "pop" effect at word start
|
|
958
|
+
* 2. Strong Emphasis (70%+): Per-letter dramatic effects throughout word
|
|
959
|
+
* 3. Both scale with GTS (expressiveness level) and word confidence
|
|
960
|
+
*
|
|
961
|
+
* KEY FEATURES:
|
|
962
|
+
* - Confidence-based thresholds (50-70% vs 70%+)
|
|
963
|
+
* - GTS-scaled intensity
|
|
964
|
+
* - Emotion slant inheritance
|
|
965
|
+
* - Smooth transitions
|
|
966
|
+
*/
|
|
967
|
+
interface Word {
|
|
968
|
+
emphasis?: number;
|
|
969
|
+
start: number;
|
|
970
|
+
end: number;
|
|
971
|
+
animationEnd?: number;
|
|
972
|
+
}
|
|
973
|
+
interface EmphasisEffect {
|
|
974
|
+
scaleMultiplier: number;
|
|
975
|
+
slantAdditive: number;
|
|
976
|
+
weightBoost: number;
|
|
977
|
+
scaleProgress: number;
|
|
978
|
+
gtsMultiplier: number;
|
|
979
|
+
emphasis: number;
|
|
980
|
+
emphasisMultiplier: number;
|
|
981
|
+
elapsed: number;
|
|
982
|
+
scaleActive: boolean;
|
|
983
|
+
}
|
|
984
|
+
interface StrongEmphasisData {
|
|
985
|
+
emphasis: number;
|
|
986
|
+
rawEmphasis: number;
|
|
987
|
+
scale: number;
|
|
988
|
+
rotation: number;
|
|
989
|
+
translateX: number;
|
|
990
|
+
translateY: number;
|
|
991
|
+
skewX: number;
|
|
992
|
+
stretchY: number;
|
|
993
|
+
brightness: number;
|
|
994
|
+
contrast: number;
|
|
995
|
+
shadowBlur: number;
|
|
996
|
+
shadowOpacity: number;
|
|
997
|
+
zIndex: number;
|
|
998
|
+
weightBoost: number;
|
|
999
|
+
shadowOffsetX: number;
|
|
1000
|
+
shadowOffsetY: number;
|
|
1001
|
+
gtsMultiplier: number;
|
|
1002
|
+
emphasisMultiplier: number;
|
|
1003
|
+
fadeFactor: number;
|
|
1004
|
+
isInTail: boolean;
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Calculate emphasis effects for a word
|
|
1008
|
+
*
|
|
1009
|
+
* @param params - Emphasis calculation parameters
|
|
1010
|
+
* @returns Emphasis effects { emphasisEffect, strongEmphasisData }
|
|
1011
|
+
*/
|
|
1012
|
+
declare function calculateWordEmphasisEffects({ word, currentTime, maxExpression, emotionAnimationDuration, wordBaseSlant, isActive, wordEmotion, }: {
|
|
1013
|
+
word: Word;
|
|
1014
|
+
currentTime: number;
|
|
1015
|
+
maxExpression: number;
|
|
1016
|
+
emotionAnimationDuration: number;
|
|
1017
|
+
wordBaseSlant: number;
|
|
1018
|
+
isActive: boolean;
|
|
1019
|
+
wordEmotion?: string;
|
|
1020
|
+
}): {
|
|
1021
|
+
emphasisEffect: EmphasisEffect | null;
|
|
1022
|
+
strongEmphasisData: StrongEmphasisData | null;
|
|
1023
|
+
};
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* ============================================
|
|
1027
|
+
* WORD LETTER SPACING
|
|
1028
|
+
* ============================================
|
|
1029
|
+
*
|
|
1030
|
+
* PURPOSE:
|
|
1031
|
+
* Calculates per-letter translateX offsets for GPU-accelerated spacing (no layout reflow).
|
|
1032
|
+
* Extracted from animationEngine for better maintainability.
|
|
1033
|
+
*
|
|
1034
|
+
* USED BY:
|
|
1035
|
+
* - animationEngine: Main word animation orchestrator
|
|
1036
|
+
*
|
|
1037
|
+
* HOW IT WORKS:
|
|
1038
|
+
* 1. Detects active effects (fear shake only - emphasis spacing is disabled)
|
|
1039
|
+
* 2. Calculates per-letter translateX offsets to create spacing between letters
|
|
1040
|
+
* 3. Returns array of translateX values in pixels (one per letter)
|
|
1041
|
+
*
|
|
1042
|
+
* KEY FEATURES:
|
|
1043
|
+
* - Transform-based spacing (GPU-accelerated, no layout reflow)
|
|
1044
|
+
* - Letter spacing disabled for emphasis effects (standard and strong)
|
|
1045
|
+
* - Only fear shake effects get letter spacing (if needed)
|
|
1046
|
+
* - Zero baseline for clean transitions
|
|
1047
|
+
*
|
|
1048
|
+
* PERFORMANCE BENEFITS:
|
|
1049
|
+
* - Uses translateX (compositor property) instead of letter-spacing (layout property)
|
|
1050
|
+
* - Smooth CSS transitions without triggering layout reflow
|
|
1051
|
+
* - All spacing animations run on GPU compositor layer
|
|
1052
|
+
*/
|
|
1053
|
+
interface WordLetterSpacingParams {
|
|
1054
|
+
strongEmphasisData?: any;
|
|
1055
|
+
emphasisEffect?: any;
|
|
1056
|
+
wordLetterShakeIntensity: number | null;
|
|
1057
|
+
wordFontFamily: string;
|
|
1058
|
+
currentTime: number;
|
|
1059
|
+
word: any;
|
|
1060
|
+
emotionAnimationDuration: number;
|
|
1061
|
+
wordEmotion?: string;
|
|
1062
|
+
totalLetters: number;
|
|
1063
|
+
fontSize: number;
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Calculate per-letter translateX offsets for GPU-accelerated spacing
|
|
1067
|
+
*
|
|
1068
|
+
* @param params - Spacing calculation parameters
|
|
1069
|
+
* @returns Array of translateX offsets in pixels (one per letter)
|
|
1070
|
+
*/
|
|
1071
|
+
declare function calculateWordLetterSpacing({ strongEmphasisData, emphasisEffect, wordLetterShakeIntensity, wordFontFamily, currentTime, word, emotionAnimationDuration, wordEmotion, totalLetters, fontSize, }: WordLetterSpacingParams): number[];
|
|
1072
|
+
|
|
844
1073
|
/**
|
|
845
1074
|
* GTS (Global Text Style) Calculations
|
|
846
1075
|
*
|
|
@@ -871,11 +1100,16 @@ declare function calculateGTSValues(gts: number): {
|
|
|
871
1100
|
*/
|
|
872
1101
|
declare function meetsEmotionThreshold(intensity: number, threshold: number): boolean;
|
|
873
1102
|
/**
|
|
874
|
-
* Calculate
|
|
1103
|
+
* Calculate scaled emotion intensity based on GTS maxExpression
|
|
1104
|
+
*
|
|
1105
|
+
* GTS acts as a scaling multiplier (final layer) to preserve variance in emotion values
|
|
1106
|
+
* while controlling overall expressiveness.
|
|
1107
|
+
*
|
|
1108
|
+
* When GTS=0.0 (maxExpression=0.2), animations are completely disabled.
|
|
875
1109
|
*
|
|
876
1110
|
* @param rawIntensity - Raw emotion intensity from backend (0-1)
|
|
877
|
-
* @param maxExpression - GTS-derived max expression
|
|
878
|
-
* @returns
|
|
1111
|
+
* @param maxExpression - GTS-derived max expression multiplier (0.2-1.0)
|
|
1112
|
+
* @returns Scaled emotion intensity (0-1), or 0 if GTS=0.0
|
|
879
1113
|
*/
|
|
880
1114
|
declare function capEmotionIntensity(rawIntensity: number, maxExpression: number): number;
|
|
881
1115
|
/**
|
|
@@ -903,14 +1137,6 @@ declare function isInEmphasisRange(emphasis: number): boolean;
|
|
|
903
1137
|
*/
|
|
904
1138
|
declare function isInStrongEmphasisRange(emphasis: number): boolean;
|
|
905
1139
|
|
|
906
|
-
/**
|
|
907
|
-
* Emotion Animation URLs
|
|
908
|
-
*
|
|
909
|
-
* Config mapping emotion → animation URL
|
|
910
|
-
* Replaces hardcoded EMOTION_ANIMATIONS config with URL-based parameters
|
|
911
|
-
*/
|
|
912
|
-
declare const EMOTION_ANIMATION_URLS: Record<string, string>;
|
|
913
|
-
|
|
914
1140
|
/**
|
|
915
1141
|
* Font Selection Utilities
|
|
916
1142
|
*
|
|
@@ -985,129 +1211,22 @@ interface Letter {
|
|
|
985
1211
|
declare function splitTextIntoLetters(text: string): Letter[];
|
|
986
1212
|
|
|
987
1213
|
/**
|
|
988
|
-
*
|
|
989
|
-
*
|
|
990
|
-
* Calculates emphasis effects (standard and strong) for words based on confidence levels.
|
|
991
|
-
*
|
|
992
|
-
* USED BY:
|
|
993
|
-
* - calculateWordAnimation: Main word animation orchestrator
|
|
994
|
-
*
|
|
995
|
-
* HOW IT WORKS:
|
|
996
|
-
* 1. Standard Emphasis (50-70%): Quick "pop" effect at word start
|
|
997
|
-
* 2. Strong Emphasis (70%+): Per-letter dramatic effects throughout word
|
|
998
|
-
* 3. Both scale with GTS (expressiveness level) and word confidence
|
|
999
|
-
*
|
|
1000
|
-
* KEY FEATURES:
|
|
1001
|
-
* - Confidence-based thresholds (50-70% vs 70%+)
|
|
1002
|
-
* - GTS-scaled intensity
|
|
1003
|
-
* - Emotion slant inheritance
|
|
1004
|
-
* - Smooth transitions
|
|
1005
|
-
*/
|
|
1006
|
-
interface Word {
|
|
1007
|
-
emphasis?: number;
|
|
1008
|
-
start: number;
|
|
1009
|
-
end: number;
|
|
1010
|
-
animationEnd?: number;
|
|
1011
|
-
}
|
|
1012
|
-
interface EmphasisEffect {
|
|
1013
|
-
scaleMultiplier: number;
|
|
1014
|
-
slantAdditive: number;
|
|
1015
|
-
weightBoost: number;
|
|
1016
|
-
scaleProgress: number;
|
|
1017
|
-
gtsMultiplier: number;
|
|
1018
|
-
emphasis: number;
|
|
1019
|
-
emphasisMultiplier: number;
|
|
1020
|
-
elapsed: number;
|
|
1021
|
-
scaleActive: boolean;
|
|
1022
|
-
}
|
|
1023
|
-
interface StrongEmphasisData {
|
|
1024
|
-
emphasis: number;
|
|
1025
|
-
rawEmphasis: number;
|
|
1026
|
-
scale: number;
|
|
1027
|
-
rotation: number;
|
|
1028
|
-
translateX: number;
|
|
1029
|
-
translateY: number;
|
|
1030
|
-
skewX: number;
|
|
1031
|
-
stretchY: number;
|
|
1032
|
-
brightness: number;
|
|
1033
|
-
contrast: number;
|
|
1034
|
-
shadowBlur: number;
|
|
1035
|
-
shadowOpacity: number;
|
|
1036
|
-
zIndex: number;
|
|
1037
|
-
weightBoost: number;
|
|
1038
|
-
shadowOffsetX: number;
|
|
1039
|
-
shadowOffsetY: number;
|
|
1040
|
-
gtsMultiplier: number;
|
|
1041
|
-
emphasisMultiplier: number;
|
|
1042
|
-
fadeFactor: number;
|
|
1043
|
-
isInTail: boolean;
|
|
1044
|
-
}
|
|
1045
|
-
/**
|
|
1046
|
-
* Calculate emphasis effects for a word
|
|
1214
|
+
* Emotion Importance Processing
|
|
1047
1215
|
*
|
|
1048
|
-
*
|
|
1049
|
-
*
|
|
1216
|
+
* Core emotions (anger, fear, sadness, joy) are prioritized over secondary emotions
|
|
1217
|
+
* by multiplying their intensity by 1.5 before selection.
|
|
1218
|
+
* Identical to monorepo app/utils/data/emotionImportance.js
|
|
1050
1219
|
*/
|
|
1051
|
-
declare function calculateWordEmphasisEffects({ word, currentTime, maxExpression, emotionAnimationDuration, wordBaseSlant, isActive, wordEmotion, }: {
|
|
1052
|
-
word: Word;
|
|
1053
|
-
currentTime: number;
|
|
1054
|
-
maxExpression: number;
|
|
1055
|
-
emotionAnimationDuration: number;
|
|
1056
|
-
wordBaseSlant: number;
|
|
1057
|
-
isActive: boolean;
|
|
1058
|
-
wordEmotion?: string;
|
|
1059
|
-
}): {
|
|
1060
|
-
emphasisEffect: EmphasisEffect | null;
|
|
1061
|
-
strongEmphasisData: StrongEmphasisData | null;
|
|
1062
|
-
};
|
|
1063
|
-
|
|
1064
1220
|
/**
|
|
1065
|
-
*
|
|
1066
|
-
* WORD LETTER SPACING
|
|
1067
|
-
* ============================================
|
|
1068
|
-
*
|
|
1069
|
-
* PURPOSE:
|
|
1070
|
-
* Calculates per-letter translateX offsets for GPU-accelerated spacing (no layout reflow).
|
|
1071
|
-
* Extracted from animationEngine for better maintainability.
|
|
1072
|
-
*
|
|
1073
|
-
* USED BY:
|
|
1074
|
-
* - animationEngine: Main word animation orchestrator
|
|
1075
|
-
*
|
|
1076
|
-
* HOW IT WORKS:
|
|
1077
|
-
* 1. Detects active effects (fear shake only - emphasis spacing is disabled)
|
|
1078
|
-
* 2. Calculates per-letter translateX offsets to create spacing between letters
|
|
1079
|
-
* 3. Returns array of translateX values in pixels (one per letter)
|
|
1080
|
-
*
|
|
1081
|
-
* KEY FEATURES:
|
|
1082
|
-
* - Transform-based spacing (GPU-accelerated, no layout reflow)
|
|
1083
|
-
* - Letter spacing disabled for emphasis effects (standard and strong)
|
|
1084
|
-
* - Only fear shake effects get letter spacing (if needed)
|
|
1085
|
-
* - Zero baseline for clean transitions
|
|
1221
|
+
* Process emotions with importance factors
|
|
1086
1222
|
*
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1089
|
-
* - Smooth CSS transitions without triggering layout reflow
|
|
1090
|
-
* - All spacing animations run on GPU compositor layer
|
|
1091
|
-
*/
|
|
1092
|
-
interface WordLetterSpacingParams {
|
|
1093
|
-
strongEmphasisData?: any;
|
|
1094
|
-
emphasisEffect?: any;
|
|
1095
|
-
wordLetterShakeIntensity: number | null;
|
|
1096
|
-
wordFontFamily: string;
|
|
1097
|
-
currentTime: number;
|
|
1098
|
-
word: any;
|
|
1099
|
-
emotionAnimationDuration: number;
|
|
1100
|
-
wordEmotion?: string;
|
|
1101
|
-
totalLetters: number;
|
|
1102
|
-
fontSize: number;
|
|
1103
|
-
}
|
|
1104
|
-
/**
|
|
1105
|
-
* Calculate per-letter translateX offsets for GPU-accelerated spacing
|
|
1223
|
+
* Core emotions (anger, fear, sadness, joy) get ×1.5 multiplier
|
|
1224
|
+
* Secondary emotions get ×1.0 multiplier
|
|
1106
1225
|
*
|
|
1107
|
-
* @param
|
|
1108
|
-
* @returns Array of
|
|
1226
|
+
* @param emotions - Array of [emotion, intensity] tuples
|
|
1227
|
+
* @returns Array of [emotion, originalIntensity, adjustedIntensity, importanceFactor, isCore] tuples
|
|
1109
1228
|
*/
|
|
1110
|
-
declare function
|
|
1229
|
+
declare function processEmotionsWithImportance(emotions: Array<[string, number]>): Array<[string, number, number, number, boolean]>;
|
|
1111
1230
|
|
|
1112
1231
|
/**
|
|
1113
1232
|
* Backend Data Accessors
|
|
@@ -1117,6 +1236,21 @@ declare function calculateWordLetterSpacing({ strongEmphasisData, emphasisEffect
|
|
|
1117
1236
|
* Identical to monorepo app/utils/data/backendDataAccessors.js
|
|
1118
1237
|
*/
|
|
1119
1238
|
|
|
1239
|
+
/**
|
|
1240
|
+
* Get word emphasis data
|
|
1241
|
+
*/
|
|
1242
|
+
declare function getWordEmphasis(word: any): {
|
|
1243
|
+
confidence: any;
|
|
1244
|
+
emphasis: any;
|
|
1245
|
+
hasEmphasis: boolean;
|
|
1246
|
+
hasStrongEmphasis: boolean;
|
|
1247
|
+
};
|
|
1248
|
+
/**
|
|
1249
|
+
* Get subtitle text content
|
|
1250
|
+
*
|
|
1251
|
+
* Handles both 'subtitle' and 'text' properties
|
|
1252
|
+
*/
|
|
1253
|
+
declare function getSubtitleText(subtitle: SubtitleSegment | null): string;
|
|
1120
1254
|
/**
|
|
1121
1255
|
* Get subtitle words array
|
|
1122
1256
|
*/
|
|
@@ -1140,24 +1274,6 @@ declare function getMergedSubtitles(subtitle: SubtitleSegment | null): SubtitleS
|
|
|
1140
1274
|
*/
|
|
1141
1275
|
declare function findSubtitleForWord(subtitles: SubtitleSegment[], word: any): SubtitleSegment | null;
|
|
1142
1276
|
|
|
1143
|
-
/**
|
|
1144
|
-
* Emotion Importance Processing
|
|
1145
|
-
*
|
|
1146
|
-
* Core emotions (anger, fear, sadness, joy) are prioritized over secondary emotions
|
|
1147
|
-
* by multiplying their intensity by 1.5 before selection.
|
|
1148
|
-
* Identical to monorepo app/utils/data/emotionImportance.js
|
|
1149
|
-
*/
|
|
1150
|
-
/**
|
|
1151
|
-
* Process emotions with importance factors
|
|
1152
|
-
*
|
|
1153
|
-
* Core emotions (anger, fear, sadness, joy) get ×1.5 multiplier
|
|
1154
|
-
* Secondary emotions get ×1.0 multiplier
|
|
1155
|
-
*
|
|
1156
|
-
* @param emotions - Array of [emotion, intensity] tuples
|
|
1157
|
-
* @returns Array of [emotion, originalIntensity, adjustedIntensity, importanceFactor, isCore] tuples
|
|
1158
|
-
*/
|
|
1159
|
-
declare function processEmotionsWithImportance(emotions: Array<[string, number]>): Array<[string, number, number, number, boolean]>;
|
|
1160
|
-
|
|
1161
1277
|
/**
|
|
1162
1278
|
* Variable Font Calculations
|
|
1163
1279
|
*
|
|
@@ -1204,34 +1320,8 @@ declare function calculateWeightFromVolume(volume: number | undefined, weightAxi
|
|
|
1204
1320
|
*/
|
|
1205
1321
|
declare function calculateWidthFromSpeechRate(speechRate: number | undefined, widthAxis: FontAxisConfig | undefined, baseWidth?: number): number;
|
|
1206
1322
|
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
*
|
|
1210
|
-
* TODO: Extract from app/hooks/subtitle/useSentenceAnimation.js and useWordAnimation.js
|
|
1211
|
-
*
|
|
1212
|
-
* This module should provide:
|
|
1213
|
-
* - createSubtitleEngine(track) - creates engine instance
|
|
1214
|
-
* - engine.at(time) - returns SubtitleEngineState for given time
|
|
1215
|
-
* - Handle karaoke mode (word-by-word) and sentence mode
|
|
1216
|
-
* - Handle edge cases: gaps, overlaps, end-of-video
|
|
1217
|
-
*/
|
|
1218
|
-
|
|
1219
|
-
declare function createSubtitleEngine(track: SubtitleTrack): {
|
|
1220
|
-
at(time: number): SubtitleEngineState;
|
|
1221
|
-
};
|
|
1222
|
-
|
|
1223
|
-
/**
|
|
1224
|
-
* Emotion → Style Mapper
|
|
1225
|
-
*
|
|
1226
|
-
* TODO: Extract from app/config/animation/ directory
|
|
1227
|
-
*
|
|
1228
|
-
* This module should provide:
|
|
1229
|
-
* - getEmotionStyle(emotion, intensity) - maps emotion to CSS styles
|
|
1230
|
-
* - Handle all 6 emotions: joy, anger, sadness, fear, disgust, surprise
|
|
1231
|
-
* - Support intensity scaling (0-1)
|
|
1232
|
-
*/
|
|
1233
|
-
|
|
1234
|
-
declare function getEmotionStyle(emotion: Emotion, intensity: number): EmotionStyle;
|
|
1323
|
+
declare function ensureFont(fontFamily: string | undefined | null): void;
|
|
1324
|
+
declare function preloadAnimationFonts(): void;
|
|
1235
1325
|
|
|
1236
1326
|
/**
|
|
1237
1327
|
* PHONT API Client
|
|
@@ -1287,7 +1377,11 @@ declare class PhontClient {
|
|
|
1287
1377
|
/**
|
|
1288
1378
|
* Register a new user
|
|
1289
1379
|
*/
|
|
1290
|
-
register(username: string, email: string, password: string
|
|
1380
|
+
register(username: string, email: string, password: string, profile: {
|
|
1381
|
+
company: string;
|
|
1382
|
+
first_name: string;
|
|
1383
|
+
last_name: string;
|
|
1384
|
+
}): Promise<RegisterResponse>;
|
|
1291
1385
|
/**
|
|
1292
1386
|
* Get subtitle track for a VOD
|
|
1293
1387
|
* Requires: Session token authentication
|
|
@@ -1343,4 +1437,4 @@ declare class PhontClient {
|
|
|
1343
1437
|
clearCredentials(): void;
|
|
1344
1438
|
}
|
|
1345
1439
|
|
|
1346
|
-
export { ANIMATION_STYLING, type AnimationOptions, type AnimationParameterStates, type
|
|
1440
|
+
export { ANIMATION_STYLING, ANIMATION_URLS, type AnimationFetcher, type AnimationOptions, type AnimationParameterState, type AnimationParameterStates, type AnimationRecord, type AnimationState, type CurvePoint, EMOTION_ANIMATION_URLS, type Emotion, type EmotionSelectionResult, type EmotionStyle, type EmphasisEffect, type FontAxisConfig, type FontConfig, type JoyEffect, type Letter, type LoginResponse, type ParameterState, type ParameterStates, PhontClient, type PhontClientOptions, type PublishedAnimationResolver, REFERENCE_GTS, REFERENCE_INTENSITY, RENDERING_CONTROL, type RegisterResponse, type SentenceAnimationState, type StateCallback, type StrongEmphasisData, type Stylesheet, type SubtitleEngineState, type SubtitleLine, SubtitleManager, type SubtitleSegment, type SubtitleState$1 as SubtitleState, SubtitleStateManager, type SubtitleTrack, type SubtitleWord, type VodMetadata, type VodState$1 as VodState, type Word, type WordAnimationState, type WordLetterSpacingParams, calculateAnimationParameters, calculateAnimationState, calculateDynamicWordSpacing, calculateEmphasisMultiplier, calculateGTSValues, calculateJoy, calculateJoyBulge, calculateNormalizedTime, calculateWeightFromVolume, calculateWidthFromSpeechRate, calculateWordEmphasisEffects, calculateWordLetterSpacing, capEmotionIntensity, computeProsodyWeight, createPublishedAnimationResolver, decodeAnimationUrl, ensureFont, findSubtitleForWord, generateTextShadow, getAnimationUrlForEmotion, getFontFamilyCSS, getJoyAnimationMode, getJoyFilter, getJoyTransform, getMergedSubtitles, getSubtitleAnimations, getSubtitleText, getSubtitleTiming, getSubtitleWords, getWordEmphasis, hasMergedSubtitles, hockeyStickIntensity, isInEmphasisRange, isInStrongEmphasisRange, meetsEmotionThreshold, preloadAnimationFonts, processEmotionsWithImportance, sampleParameterCurve, selectEmotion, selectFontFamily, shouldUseAngryFont, shouldUseJoyFont, shouldUseSadnessFont, splitTextIntoLetters, subtitleManager };
|