vidpipe 1.0.0 → 1.2.0

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 (168) hide show
  1. package/README.md +35 -1
  2. package/dist/agents/BaseAgent.d.ts +17 -17
  3. package/dist/agents/BaseAgent.d.ts.map +1 -1
  4. package/dist/agents/BaseAgent.js +41 -47
  5. package/dist/agents/BaseAgent.js.map +1 -1
  6. package/dist/agents/SilenceRemovalAgent.d.ts.map +1 -1
  7. package/dist/agents/SilenceRemovalAgent.js +3 -2
  8. package/dist/agents/SilenceRemovalAgent.js.map +1 -1
  9. package/dist/commands/doctor.d.ts +4 -0
  10. package/dist/commands/doctor.d.ts.map +1 -0
  11. package/dist/commands/doctor.js +212 -0
  12. package/dist/commands/doctor.js.map +1 -0
  13. package/dist/config/environment.d.ts +3 -0
  14. package/dist/config/environment.d.ts.map +1 -1
  15. package/dist/config/environment.js +5 -2
  16. package/dist/config/environment.js.map +1 -1
  17. package/dist/config/ffmpegResolver.d.ts +3 -0
  18. package/dist/config/ffmpegResolver.d.ts.map +1 -0
  19. package/dist/config/ffmpegResolver.js +37 -0
  20. package/dist/config/ffmpegResolver.js.map +1 -0
  21. package/dist/config/pricing.d.ts +34 -0
  22. package/dist/config/pricing.d.ts.map +1 -0
  23. package/dist/config/pricing.js +71 -0
  24. package/dist/config/pricing.js.map +1 -0
  25. package/dist/index.js +12 -4
  26. package/dist/index.js.map +1 -1
  27. package/dist/pipeline.d.ts.map +1 -1
  28. package/dist/pipeline.js +37 -0
  29. package/dist/pipeline.js.map +1 -1
  30. package/dist/providers/ClaudeProvider.d.ts +14 -0
  31. package/dist/providers/ClaudeProvider.d.ts.map +1 -0
  32. package/dist/providers/ClaudeProvider.js +182 -0
  33. package/dist/providers/ClaudeProvider.js.map +1 -0
  34. package/dist/providers/CopilotProvider.d.ts +17 -0
  35. package/dist/providers/CopilotProvider.d.ts.map +1 -0
  36. package/dist/providers/CopilotProvider.js +149 -0
  37. package/dist/providers/CopilotProvider.js.map +1 -0
  38. package/dist/providers/OpenAIProvider.d.ts +14 -0
  39. package/dist/providers/OpenAIProvider.d.ts.map +1 -0
  40. package/dist/providers/OpenAIProvider.js +175 -0
  41. package/dist/providers/OpenAIProvider.js.map +1 -0
  42. package/dist/providers/index.d.ts +18 -0
  43. package/dist/providers/index.d.ts.map +1 -0
  44. package/dist/providers/index.js +61 -0
  45. package/dist/providers/index.js.map +1 -0
  46. package/dist/providers/types.d.ts +112 -0
  47. package/dist/providers/types.d.ts.map +1 -0
  48. package/dist/providers/types.js +8 -0
  49. package/dist/providers/types.js.map +1 -0
  50. package/dist/services/costTracker.d.ts +63 -0
  51. package/dist/services/costTracker.d.ts.map +1 -0
  52. package/dist/services/costTracker.js +137 -0
  53. package/dist/services/costTracker.js.map +1 -0
  54. package/dist/services/videoIngestion.d.ts.map +1 -1
  55. package/dist/services/videoIngestion.js +4 -3
  56. package/dist/services/videoIngestion.js.map +1 -1
  57. package/dist/tools/ffmpeg/aspectRatio.d.ts.map +1 -1
  58. package/dist/tools/ffmpeg/aspectRatio.js +2 -1
  59. package/dist/tools/ffmpeg/aspectRatio.js.map +1 -1
  60. package/dist/tools/ffmpeg/audioExtraction.d.ts.map +1 -1
  61. package/dist/tools/ffmpeg/audioExtraction.js +3 -2
  62. package/dist/tools/ffmpeg/audioExtraction.js.map +1 -1
  63. package/dist/tools/ffmpeg/captionBurning.d.ts.map +1 -1
  64. package/dist/tools/ffmpeg/captionBurning.js +2 -1
  65. package/dist/tools/ffmpeg/captionBurning.js.map +1 -1
  66. package/dist/tools/ffmpeg/clipExtraction.d.ts +16 -1
  67. package/dist/tools/ffmpeg/clipExtraction.d.ts.map +1 -1
  68. package/dist/tools/ffmpeg/clipExtraction.js +44 -7
  69. package/dist/tools/ffmpeg/clipExtraction.js.map +1 -1
  70. package/dist/tools/ffmpeg/faceDetection.d.ts.map +1 -1
  71. package/dist/tools/ffmpeg/faceDetection.js +3 -2
  72. package/dist/tools/ffmpeg/faceDetection.js.map +1 -1
  73. package/dist/tools/ffmpeg/frameCapture.d.ts.map +1 -1
  74. package/dist/tools/ffmpeg/frameCapture.js +3 -2
  75. package/dist/tools/ffmpeg/frameCapture.js.map +1 -1
  76. package/dist/tools/ffmpeg/silenceDetection.d.ts.map +1 -1
  77. package/dist/tools/ffmpeg/silenceDetection.js +2 -1
  78. package/dist/tools/ffmpeg/silenceDetection.js.map +1 -1
  79. package/dist/tools/ffmpeg/singlePassEdit.d.ts.map +1 -1
  80. package/dist/tools/ffmpeg/singlePassEdit.js +2 -1
  81. package/dist/tools/ffmpeg/singlePassEdit.js.map +1 -1
  82. package/dist/types/index.d.ts +1 -1
  83. package/dist/types/index.js +1 -1
  84. package/package.json +67 -63
  85. package/dist/__tests__/agents.test.d.ts +0 -2
  86. package/dist/__tests__/agents.test.d.ts.map +0 -1
  87. package/dist/__tests__/agents.test.js +0 -434
  88. package/dist/__tests__/agents.test.js.map +0 -1
  89. package/dist/__tests__/aspectRatio.test.d.ts +0 -2
  90. package/dist/__tests__/aspectRatio.test.d.ts.map +0 -1
  91. package/dist/__tests__/aspectRatio.test.js +0 -406
  92. package/dist/__tests__/aspectRatio.test.js.map +0 -1
  93. package/dist/__tests__/captionGenerator.test.d.ts +0 -2
  94. package/dist/__tests__/captionGenerator.test.d.ts.map +0 -1
  95. package/dist/__tests__/captionGenerator.test.js +0 -435
  96. package/dist/__tests__/captionGenerator.test.js.map +0 -1
  97. package/dist/__tests__/config.test.d.ts +0 -2
  98. package/dist/__tests__/config.test.d.ts.map +0 -1
  99. package/dist/__tests__/config.test.js +0 -81
  100. package/dist/__tests__/config.test.js.map +0 -1
  101. package/dist/__tests__/faceDetection.test.d.ts +0 -2
  102. package/dist/__tests__/faceDetection.test.d.ts.map +0 -1
  103. package/dist/__tests__/faceDetection.test.js +0 -372
  104. package/dist/__tests__/faceDetection.test.js.map +0 -1
  105. package/dist/__tests__/ffmpegTools.test.d.ts +0 -2
  106. package/dist/__tests__/ffmpegTools.test.d.ts.map +0 -1
  107. package/dist/__tests__/ffmpegTools.test.js +0 -464
  108. package/dist/__tests__/ffmpegTools.test.js.map +0 -1
  109. package/dist/__tests__/integration/captionBurn.test.d.ts +0 -2
  110. package/dist/__tests__/integration/captionBurn.test.d.ts.map +0 -1
  111. package/dist/__tests__/integration/captionBurn.test.js +0 -103
  112. package/dist/__tests__/integration/captionBurn.test.js.map +0 -1
  113. package/dist/__tests__/integration/clipComposite.test.d.ts +0 -2
  114. package/dist/__tests__/integration/clipComposite.test.d.ts.map +0 -1
  115. package/dist/__tests__/integration/clipComposite.test.js +0 -56
  116. package/dist/__tests__/integration/clipComposite.test.js.map +0 -1
  117. package/dist/__tests__/integration/faceDetection.test.d.ts +0 -2
  118. package/dist/__tests__/integration/faceDetection.test.d.ts.map +0 -1
  119. package/dist/__tests__/integration/faceDetection.test.js +0 -85
  120. package/dist/__tests__/integration/faceDetection.test.js.map +0 -1
  121. package/dist/__tests__/integration/ffmpegPipeline.test.d.ts +0 -2
  122. package/dist/__tests__/integration/ffmpegPipeline.test.d.ts.map +0 -1
  123. package/dist/__tests__/integration/ffmpegPipeline.test.js +0 -88
  124. package/dist/__tests__/integration/ffmpegPipeline.test.js.map +0 -1
  125. package/dist/__tests__/integration/fixture.d.ts +0 -19
  126. package/dist/__tests__/integration/fixture.d.ts.map +0 -1
  127. package/dist/__tests__/integration/fixture.js +0 -112
  128. package/dist/__tests__/integration/fixture.js.map +0 -1
  129. package/dist/__tests__/integration/fixture.test.d.ts +0 -2
  130. package/dist/__tests__/integration/fixture.test.d.ts.map +0 -1
  131. package/dist/__tests__/integration/fixture.test.js +0 -27
  132. package/dist/__tests__/integration/fixture.test.js.map +0 -1
  133. package/dist/__tests__/integration/realCaptions.test.d.ts +0 -2
  134. package/dist/__tests__/integration/realCaptions.test.d.ts.map +0 -1
  135. package/dist/__tests__/integration/realCaptions.test.js +0 -226
  136. package/dist/__tests__/integration/realCaptions.test.js.map +0 -1
  137. package/dist/__tests__/integration/realPipeline.test.d.ts +0 -2
  138. package/dist/__tests__/integration/realPipeline.test.d.ts.map +0 -1
  139. package/dist/__tests__/integration/realPipeline.test.js +0 -210
  140. package/dist/__tests__/integration/realPipeline.test.js.map +0 -1
  141. package/dist/__tests__/integration/silenceRemoval.test.d.ts +0 -2
  142. package/dist/__tests__/integration/silenceRemoval.test.d.ts.map +0 -1
  143. package/dist/__tests__/integration/silenceRemoval.test.js +0 -93
  144. package/dist/__tests__/integration/silenceRemoval.test.js.map +0 -1
  145. package/dist/__tests__/pipeline.test.d.ts +0 -2
  146. package/dist/__tests__/pipeline.test.d.ts.map +0 -1
  147. package/dist/__tests__/pipeline.test.js +0 -434
  148. package/dist/__tests__/pipeline.test.js.map +0 -1
  149. package/dist/__tests__/services.test.d.ts +0 -2
  150. package/dist/__tests__/services.test.d.ts.map +0 -1
  151. package/dist/__tests__/services.test.js +0 -655
  152. package/dist/__tests__/services.test.js.map +0 -1
  153. package/dist/__tests__/silenceRemoval.test.d.ts +0 -2
  154. package/dist/__tests__/silenceRemoval.test.d.ts.map +0 -1
  155. package/dist/__tests__/silenceRemoval.test.js +0 -266
  156. package/dist/__tests__/silenceRemoval.test.js.map +0 -1
  157. package/dist/__tests__/singlePassEdit.test.d.ts +0 -2
  158. package/dist/__tests__/singlePassEdit.test.d.ts.map +0 -1
  159. package/dist/__tests__/singlePassEdit.test.js +0 -321
  160. package/dist/__tests__/singlePassEdit.test.js.map +0 -1
  161. package/dist/__tests__/smoke.test.d.ts +0 -2
  162. package/dist/__tests__/smoke.test.d.ts.map +0 -1
  163. package/dist/__tests__/smoke.test.js +0 -8
  164. package/dist/__tests__/smoke.test.js.map +0 -1
  165. package/dist/__tests__/utilities.test.d.ts +0 -2
  166. package/dist/__tests__/utilities.test.d.ts.map +0 -1
  167. package/dist/__tests__/utilities.test.js +0 -268
  168. package/dist/__tests__/utilities.test.js.map +0 -1
@@ -1,435 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { generateSRT, generateVTT, generateStyledASS, generateStyledASSForSegment, generateStyledASSForComposite, generateHookOverlay, generatePortraitASSWithHook, generatePortraitASSWithHookComposite, } from '../tools/captions/captionGenerator.js';
3
- // ---------------------------------------------------------------------------
4
- // Mock data
5
- // ---------------------------------------------------------------------------
6
- function makeSegment(id, text, start, end, words = []) {
7
- return { id, text, start, end, words };
8
- }
9
- /** Simple transcript with two segments, no word-level data needed for SRT/VTT. */
10
- const basicTranscript = {
11
- text: 'Hello world. This is a test.',
12
- segments: [
13
- makeSegment(0, ' Hello world.', 0.0, 1.5),
14
- makeSegment(1, ' This is a test.', 2.0, 4.0),
15
- ],
16
- words: [],
17
- language: 'en',
18
- duration: 4.0,
19
- };
20
- const emptyTranscript = {
21
- text: '',
22
- segments: [],
23
- words: [],
24
- language: 'en',
25
- duration: 0,
26
- };
27
- /** Words with a silence gap > 0.8s between "world" and "next". */
28
- const wordsWithGap = [
29
- { word: 'Hello', start: 0.0, end: 0.5 },
30
- { word: 'world', start: 0.6, end: 1.0 },
31
- { word: 'this', start: 1.1, end: 1.3 },
32
- { word: 'is', start: 1.4, end: 1.6 },
33
- // gap of 1.4s (1.6 → 3.0)
34
- { word: 'next', start: 3.0, end: 3.3 },
35
- { word: 'sentence', start: 3.4, end: 3.8 },
36
- ];
37
- const transcriptWithWords = {
38
- text: 'Hello world this is next sentence',
39
- segments: [],
40
- words: wordsWithGap,
41
- language: 'en',
42
- duration: 3.8,
43
- };
44
- /** 10 words to verify max-group splitting (MAX_WORDS_PER_GROUP = 8). */
45
- const manyWords = Array.from({ length: 10 }, (_, i) => ({
46
- word: `w${i}`,
47
- start: i * 0.3,
48
- end: i * 0.3 + 0.2,
49
- }));
50
- const manyWordsTranscript = {
51
- text: manyWords.map((w) => w.word).join(' '),
52
- segments: [],
53
- words: manyWords,
54
- language: 'en',
55
- duration: 3.0,
56
- };
57
- // ---------------------------------------------------------------------------
58
- // SRT
59
- // ---------------------------------------------------------------------------
60
- describe('generateSRT', () => {
61
- it('produces valid SRT with sequential numbering', () => {
62
- const srt = generateSRT(basicTranscript);
63
- const blocks = srt.trim().split('\n\n');
64
- expect(blocks).toHaveLength(2);
65
- expect(blocks[0]).toMatch(/^1\n/);
66
- expect(blocks[1]).toMatch(/^2\n/);
67
- });
68
- it('formats timestamps as HH:MM:SS,mmm', () => {
69
- const srt = generateSRT(basicTranscript);
70
- // Expect "00:00:00,000 --> 00:00:01,500"
71
- expect(srt).toContain('00:00:00,000 --> 00:00:01,500');
72
- expect(srt).toContain('00:00:02,000 --> 00:00:04,000');
73
- });
74
- it('returns only a newline for an empty transcript', () => {
75
- const srt = generateSRT(emptyTranscript);
76
- expect(srt).toBe('\n');
77
- });
78
- it('trims segment text', () => {
79
- const srt = generateSRT(basicTranscript);
80
- expect(srt).toContain('Hello world.');
81
- expect(srt).not.toContain(' Hello world.');
82
- });
83
- });
84
- // ---------------------------------------------------------------------------
85
- // VTT
86
- // ---------------------------------------------------------------------------
87
- describe('generateVTT', () => {
88
- it('starts with WEBVTT header', () => {
89
- const vtt = generateVTT(basicTranscript);
90
- expect(vtt.startsWith('WEBVTT')).toBe(true);
91
- });
92
- it('uses dot separator in timestamps (HH:MM:SS.mmm)', () => {
93
- const vtt = generateVTT(basicTranscript);
94
- expect(vtt).toContain('00:00:00.000 --> 00:00:01.500');
95
- });
96
- it('returns header only for empty transcript', () => {
97
- const vtt = generateVTT(emptyTranscript);
98
- expect(vtt).toBe('WEBVTT\n\n\n');
99
- });
100
- });
101
- // ---------------------------------------------------------------------------
102
- // ASS – generateStyledASS
103
- // ---------------------------------------------------------------------------
104
- describe('generateStyledASS', () => {
105
- it('contains [Script Info] header', () => {
106
- const ass = generateStyledASS(transcriptWithWords);
107
- expect(ass).toContain('[Script Info]');
108
- });
109
- it('references Montserrat font', () => {
110
- const ass = generateStyledASS(transcriptWithWords);
111
- expect(ass).toContain('Montserrat');
112
- });
113
- it('returns header only for empty transcript', () => {
114
- const ass = generateStyledASS(emptyTranscript);
115
- expect(ass).toContain('[Script Info]');
116
- expect(ass).not.toContain('Dialogue:');
117
- });
118
- it('highlights only the active word with yellow color', () => {
119
- const ass = generateStyledASS(transcriptWithWords);
120
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
121
- // Each dialogue line should have exactly one active-color tag
122
- for (const line of dialogueLines) {
123
- const activeMatches = line.match(/\\c&H00FFFF&/g) || [];
124
- expect(activeMatches).toHaveLength(1);
125
- }
126
- });
127
- it('inactive words use white color', () => {
128
- const ass = generateStyledASS(transcriptWithWords);
129
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
130
- // Lines with multiple words should have white-colored inactive words
131
- const multiWordLine = dialogueLines.find((l) => (l.match(/\\c&HFFFFFF&/g) || []).length > 0);
132
- expect(multiWordLine).toBeDefined();
133
- });
134
- it('splits words into multi-line groups with \\N', () => {
135
- // manyWords has 10 words; first group of 8 should split into 2 lines
136
- const ass = generateStyledASS(manyWordsTranscript);
137
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
138
- const hasMultiline = dialogueLines.some((l) => l.includes('\\N'));
139
- expect(hasMultiline).toBe(true);
140
- });
141
- it('creates separate groups when silence gap > 0.8s', () => {
142
- const ass = generateStyledASS(transcriptWithWords);
143
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
144
- // Extract ASS timestamps from dialogue lines
145
- const timestamps = dialogueLines.map((l) => {
146
- const match = l.match(/Dialogue: 0,([^,]+),([^,]+),/);
147
- return match ? { start: match[1], end: match[2] } : null;
148
- }).filter(Boolean);
149
- // There should be a discontinuity – no dialogue line bridges the gap (1.6 → 3.0)
150
- // Words before gap end at ~1.6s, words after gap start at ~3.0s
151
- const beforeGap = timestamps.filter((t) => {
152
- const s = parseASSTimestamp(t.start);
153
- return s < 2.0;
154
- });
155
- const afterGap = timestamps.filter((t) => {
156
- const s = parseASSTimestamp(t.start);
157
- return s >= 2.5;
158
- });
159
- expect(beforeGap.length).toBeGreaterThan(0);
160
- expect(afterGap.length).toBeGreaterThan(0);
161
- });
162
- it('shorts style uses larger font sizes', () => {
163
- const ass = generateStyledASS(transcriptWithWords, 'shorts');
164
- expect(ass).toContain('\\fs54'); // active font size
165
- expect(ass).toContain('\\fs42'); // base font size
166
- });
167
- it('medium style uses smaller font sizes', () => {
168
- const ass = generateStyledASS(transcriptWithWords, 'medium');
169
- expect(ass).toContain('\\fs40'); // medium active font size
170
- expect(ass).toContain('\\fs32'); // medium base font size
171
- });
172
- it('medium style uses different header with smaller default font', () => {
173
- const ass = generateStyledASS(transcriptWithWords, 'medium');
174
- // Medium header has Fontsize 32 in style line
175
- const styleLine = ass.split('\n').find((l) => l.startsWith('Style: Default'));
176
- expect(styleLine).toContain('Montserrat,32');
177
- });
178
- });
179
- // ---------------------------------------------------------------------------
180
- // ASS – generateStyledASSForSegment
181
- // ---------------------------------------------------------------------------
182
- describe('generateStyledASSForSegment', () => {
183
- const fullTranscript = {
184
- text: '',
185
- segments: [],
186
- words: [
187
- { word: 'before', start: 0.0, end: 0.5 },
188
- { word: 'Hello', start: 5.0, end: 5.5 },
189
- { word: 'world', start: 5.6, end: 6.0 },
190
- { word: 'after', start: 15.0, end: 15.5 },
191
- ],
192
- language: 'en',
193
- duration: 16.0,
194
- };
195
- it('generates captions only for words within the segment range', () => {
196
- const ass = generateStyledASSForSegment(fullTranscript, 5.0, 6.0, 0.5);
197
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
198
- expect(dialogueLines.length).toBeGreaterThan(0);
199
- // Should include "Hello" and "world" but not "before" or "after"
200
- expect(ass).toContain('Hello');
201
- expect(ass).toContain('world');
202
- expect(ass).not.toContain('before');
203
- expect(ass).not.toContain('after');
204
- });
205
- it('adjusts timestamps relative to the buffered start', () => {
206
- const ass = generateStyledASSForSegment(fullTranscript, 5.0, 6.0, 0.5);
207
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
208
- // bufferedStart = 5.0 - 0.5 = 4.5, so "Hello" at 5.0 maps to 0.5
209
- const firstLine = dialogueLines[0];
210
- const match = firstLine.match(/Dialogue: 0,([^,]+),/);
211
- expect(match).toBeTruthy();
212
- const startSec = parseASSTimestamp(match[1]);
213
- // "Hello" starts at 5.0, bufferedStart=4.5, so adjusted start = 0.5
214
- expect(startSec).toBeCloseTo(0.5, 1);
215
- });
216
- it('returns only header when no words match the range', () => {
217
- const ass = generateStyledASSForSegment(fullTranscript, 20.0, 25.0);
218
- expect(ass).toContain('[Script Info]');
219
- expect(ass).not.toContain('Dialogue:');
220
- });
221
- it('respects the style parameter', () => {
222
- const ass = generateStyledASSForSegment(fullTranscript, 5.0, 6.0, 0.5, 'medium');
223
- expect(ass).toContain('\\fs40');
224
- });
225
- });
226
- // ---------------------------------------------------------------------------
227
- // ASS – generateStyledASSForComposite
228
- // ---------------------------------------------------------------------------
229
- describe('generateStyledASSForComposite', () => {
230
- const compositeTranscript = {
231
- text: '',
232
- segments: [],
233
- words: [
234
- { word: 'intro', start: 1.0, end: 1.5 },
235
- { word: 'middle', start: 10.0, end: 10.5 },
236
- { word: 'end', start: 20.0, end: 20.5 },
237
- ],
238
- language: 'en',
239
- duration: 21.0,
240
- };
241
- it('remaps words from multiple segments onto a continuous timeline', () => {
242
- const segments = [
243
- { start: 1.0, end: 1.5 },
244
- { start: 10.0, end: 10.5 },
245
- ];
246
- const ass = generateStyledASSForComposite(compositeTranscript, segments, 0.5);
247
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
248
- expect(dialogueLines.length).toBeGreaterThan(0);
249
- expect(ass).toContain('intro');
250
- expect(ass).toContain('middle');
251
- expect(ass).not.toContain('end');
252
- });
253
- it('returns header only when no words match any segment', () => {
254
- const segments = [{ start: 50.0, end: 55.0 }];
255
- const ass = generateStyledASSForComposite(compositeTranscript, segments);
256
- expect(ass).toContain('[Script Info]');
257
- expect(ass).not.toContain('Dialogue:');
258
- });
259
- });
260
- // ---------------------------------------------------------------------------
261
- // Word grouping logic (verified via ASS output)
262
- // ---------------------------------------------------------------------------
263
- describe('word grouping logic', () => {
264
- it('groups do not exceed MAX_GROUP_WORDS (8)', () => {
265
- const ass = generateStyledASS(manyWordsTranscript);
266
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
267
- // Count words per dialogue group by checking how many words appear in a single line
268
- for (const line of dialogueLines) {
269
- const wordTokens = line.match(/\\fs\d+\}[^{]+/g) || [];
270
- expect(wordTokens.length).toBeLessThanOrEqual(8);
271
- }
272
- });
273
- it('silence gaps > 0.8s split groups', () => {
274
- // wordsWithGap: 4 words, gap, 2 words → should produce 2 groups
275
- const ass = generateStyledASS(transcriptWithWords);
276
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
277
- // Group1: Hello, world, this, is (4 dialogue lines per word)
278
- // Group2: next, sentence (2 dialogue lines per word)
279
- expect(dialogueLines).toHaveLength(6);
280
- });
281
- it('lines within a group do not exceed WORDS_PER_LINE (4) per display line', () => {
282
- const ass = generateStyledASS(manyWordsTranscript);
283
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
284
- for (const line of dialogueLines) {
285
- // Split on \N to get individual display lines
286
- const textPart = line.split(',').slice(9).join(',');
287
- const displayLines = textPart.split('\\N');
288
- for (const dLine of displayLines) {
289
- const wordCount = (dLine.match(/\\fs\d+\}/g) || []).length;
290
- expect(wordCount).toBeLessThanOrEqual(4);
291
- }
292
- }
293
- });
294
- });
295
- // ---------------------------------------------------------------------------
296
- // Portrait style
297
- // ---------------------------------------------------------------------------
298
- describe('generateStyledASS – portrait style', () => {
299
- it('portrait ASS header has PlayResX 1080 and PlayResY 1920', () => {
300
- const ass = generateStyledASS(transcriptWithWords, 'portrait');
301
- expect(ass).toContain('PlayResX: 1080');
302
- expect(ass).toContain('PlayResY: 1920');
303
- });
304
- it('portrait Default style uses Alignment 2 (bottom-center)', () => {
305
- const ass = generateStyledASS(transcriptWithWords, 'portrait');
306
- const styleLine = ass.split('\n').find((l) => l.startsWith('Style: Default'));
307
- expect(styleLine).toBeDefined();
308
- // Alignment is the 18th field in the Style line (0-indexed: 17)
309
- const fields = styleLine.split(',');
310
- // Alignment field: "Style: Name(0),Fontname(1),...,Shadow(17),Alignment(18)"
311
- expect(fields[18].trim()).toBe('2');
312
- });
313
- it('portrait header contains Hook style definition', () => {
314
- const ass = generateStyledASS(transcriptWithWords, 'portrait');
315
- expect(ass).toContain('Style: Hook,');
316
- });
317
- it('portrait active word uses green color (not yellow)', () => {
318
- const ass = generateStyledASS(transcriptWithWords, 'portrait');
319
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
320
- expect(dialogueLines.length).toBeGreaterThan(0);
321
- // Should contain green active color
322
- expect(ass).toContain('\\c&H00FF00&');
323
- // Should NOT contain yellow (shorts) active color
324
- const dialogueText = dialogueLines.join('\n');
325
- expect(dialogueText).not.toContain('\\c&H00FFFF&');
326
- });
327
- it('portrait active word has scale animation', () => {
328
- const ass = generateStyledASS(transcriptWithWords, 'portrait');
329
- expect(ass).toContain('\\fscx130\\fscy130');
330
- expect(ass).toContain('\\t(0,150,\\fscx100\\fscy100)');
331
- });
332
- it('portrait active word font size is 78', () => {
333
- const ass = generateStyledASS(transcriptWithWords, 'portrait');
334
- expect(ass).toContain('\\fs78');
335
- });
336
- it('portrait inactive words use white color at size 66', () => {
337
- const ass = generateStyledASS(transcriptWithWords, 'portrait');
338
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
339
- const hasWhite66 = dialogueLines.some((l) => l.includes('\\c&HFFFFFF&') && l.includes('\\fs66'));
340
- expect(hasWhite66).toBe(true);
341
- });
342
- });
343
- // ---------------------------------------------------------------------------
344
- // Hook overlay
345
- // ---------------------------------------------------------------------------
346
- describe('generateHookOverlay', () => {
347
- it('returns a Dialogue line with Style=Hook on Layer 1', () => {
348
- const line = generateHookOverlay('Test hook text');
349
- expect(line).toMatch(/^Dialogue: 1,/);
350
- expect(line).toContain(',Hook,');
351
- });
352
- it('contains fade animation \\fad(300,500)', () => {
353
- const line = generateHookOverlay('Test hook text');
354
- expect(line).toContain('\\fad(300,500)');
355
- expect(line).not.toContain('\\blur3');
356
- });
357
- it('starts at 0:00:00.00 and ends at ~0:00:04.00 by default', () => {
358
- const line = generateHookOverlay('Test hook text');
359
- expect(line).toContain(',0:00:00.00,');
360
- expect(line).toContain(',0:00:04.00,');
361
- });
362
- it('truncates long text to ~60 chars with "..."', () => {
363
- const longText = 'a'.repeat(100);
364
- const line = generateHookOverlay(longText);
365
- // Text after last "}" should be 60 chars (57 + "...")
366
- const textPart = line.split('}').pop();
367
- expect(textPart.length).toBeLessThanOrEqual(60);
368
- expect(textPart).toContain('...');
369
- });
370
- it('does not truncate short text', () => {
371
- const line = generateHookOverlay('Short hook');
372
- expect(line).toContain('Short hook');
373
- expect(line).not.toContain('...');
374
- });
375
- });
376
- // ---------------------------------------------------------------------------
377
- // Portrait ASS with hook
378
- // ---------------------------------------------------------------------------
379
- describe('generatePortraitASSWithHook', () => {
380
- it('contains both Default and Hook style Dialogue lines', () => {
381
- const ass = generatePortraitASSWithHook(transcriptWithWords, 'Hook!', 0, 3.8);
382
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
383
- const defaultLines = dialogueLines.filter((l) => l.includes(',Default,'));
384
- const hookLines = dialogueLines.filter((l) => l.includes(',Hook,'));
385
- expect(defaultLines.length).toBeGreaterThan(0);
386
- expect(hookLines.length).toBeGreaterThan(0);
387
- });
388
- it('uses portrait header with PlayResX 1080', () => {
389
- const ass = generatePortraitASSWithHook(transcriptWithWords, 'Hook!', 0, 3.8);
390
- expect(ass).toContain('PlayResX: 1080');
391
- });
392
- });
393
- // ---------------------------------------------------------------------------
394
- // Composite with hook
395
- // ---------------------------------------------------------------------------
396
- describe('generatePortraitASSWithHookComposite', () => {
397
- const compositeTranscript = {
398
- text: '',
399
- segments: [],
400
- words: [
401
- { word: 'intro', start: 1.0, end: 1.5 },
402
- { word: 'middle', start: 10.0, end: 10.5 },
403
- ],
404
- language: 'en',
405
- duration: 11.0,
406
- };
407
- it('contains caption and hook Dialogue lines', () => {
408
- const segments = [
409
- { start: 1.0, end: 1.5 },
410
- { start: 10.0, end: 10.5 },
411
- ];
412
- const ass = generatePortraitASSWithHookComposite(compositeTranscript, segments, 'Hook!');
413
- const dialogueLines = ass.split('\n').filter((l) => l.startsWith('Dialogue:'));
414
- const defaultLines = dialogueLines.filter((l) => l.includes(',Default,'));
415
- const hookLines = dialogueLines.filter((l) => l.includes(',Hook,'));
416
- expect(defaultLines.length).toBeGreaterThan(0);
417
- expect(hookLines.length).toBeGreaterThan(0);
418
- });
419
- it('uses portrait header', () => {
420
- const segments = [{ start: 1.0, end: 1.5 }];
421
- const ass = generatePortraitASSWithHookComposite(compositeTranscript, segments, 'Test');
422
- expect(ass).toContain('PlayResY: 1920');
423
- expect(ass).toContain('Style: Hook,');
424
- });
425
- });
426
- // ---------------------------------------------------------------------------
427
- // Helpers
428
- // ---------------------------------------------------------------------------
429
- /** Parse an ASS timestamp "H:MM:SS.cc" to seconds. */
430
- function parseASSTimestamp(ts) {
431
- const [h, m, rest] = ts.split(':');
432
- const [s, cs] = rest.split('.');
433
- return parseInt(h) * 3600 + parseInt(m) * 60 + parseInt(s) + parseInt(cs) / 100;
434
- }
435
- //# sourceMappingURL=captionGenerator.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"captionGenerator.test.js","sourceRoot":"","sources":["../../src/__tests__/captionGenerator.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=config.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":""}
@@ -1,81 +0,0 @@
1
- import { describe, it, expect, afterEach, vi } from 'vitest';
2
- import { initConfig, getConfig, validateRequiredKeys } from '../config/environment.js';
3
- afterEach(() => {
4
- vi.unstubAllEnvs();
5
- });
6
- describe('initConfig', () => {
7
- it('CLI params override env vars', () => {
8
- vi.stubEnv('OPENAI_API_KEY', 'env-key');
9
- vi.stubEnv('OUTPUT_DIR', '/env/output');
10
- const cfg = initConfig({
11
- openaiKey: 'cli-key',
12
- outputDir: '/cli/output',
13
- });
14
- expect(cfg.OPENAI_API_KEY).toBe('cli-key');
15
- expect(cfg.OUTPUT_DIR).toBe('/cli/output');
16
- });
17
- it('defaults used when nothing provided', () => {
18
- vi.stubEnv('OPENAI_API_KEY', '');
19
- vi.stubEnv('OUTPUT_DIR', '');
20
- vi.stubEnv('WATCH_FOLDER', '');
21
- vi.stubEnv('FFMPEG_PATH', '');
22
- vi.stubEnv('FFPROBE_PATH', '');
23
- const cfg = initConfig({});
24
- expect(cfg.FFMPEG_PATH).toBe('ffmpeg');
25
- expect(cfg.FFPROBE_PATH).toBe('ffprobe');
26
- expect(cfg.VERBOSE).toBe(false);
27
- expect(cfg.SKIP_GIT).toBe(false);
28
- expect(cfg.SKIP_SILENCE_REMOVAL).toBe(false);
29
- expect(cfg.SKIP_SHORTS).toBe(false);
30
- });
31
- it('OPENAI_API_KEY from env used when no CLI param', () => {
32
- vi.stubEnv('OPENAI_API_KEY', 'from-env');
33
- const cfg = initConfig({});
34
- expect(cfg.OPENAI_API_KEY).toBe('from-env');
35
- });
36
- it('OUTPUT_DIR defaults to recordings under repo root', () => {
37
- vi.stubEnv('OUTPUT_DIR', '');
38
- const cfg = initConfig({});
39
- expect(cfg.OUTPUT_DIR).toContain('recordings');
40
- });
41
- it('SKIP_* flags honor CLI --no-* params', () => {
42
- const cfg = initConfig({
43
- silenceRemoval: false,
44
- shorts: false,
45
- social: false,
46
- captions: false,
47
- git: false,
48
- mediumClips: false,
49
- });
50
- expect(cfg.SKIP_SILENCE_REMOVAL).toBe(true);
51
- expect(cfg.SKIP_SHORTS).toBe(true);
52
- expect(cfg.SKIP_SOCIAL).toBe(true);
53
- expect(cfg.SKIP_CAPTIONS).toBe(true);
54
- expect(cfg.SKIP_GIT).toBe(true);
55
- expect(cfg.SKIP_MEDIUM_CLIPS).toBe(true);
56
- });
57
- it('VERBOSE flag from -v param', () => {
58
- const cfg = initConfig({ verbose: true });
59
- expect(cfg.VERBOSE).toBe(true);
60
- });
61
- });
62
- describe('Environment validation', () => {
63
- it('throws when OPENAI_API_KEY is missing', () => {
64
- vi.stubEnv('OPENAI_API_KEY', '');
65
- initConfig({ openaiKey: '' });
66
- expect(() => validateRequiredKeys()).toThrow('Missing required: OPENAI_API_KEY');
67
- });
68
- it('FFMPEG_PATH has a default value', () => {
69
- const cfg = initConfig({});
70
- expect(cfg.FFMPEG_PATH).toBeTruthy();
71
- });
72
- });
73
- describe('getConfig', () => {
74
- it('returns previously initialized config', () => {
75
- const cfg = initConfig({ openaiKey: 'test-key-123' });
76
- const retrieved = getConfig();
77
- expect(retrieved.OPENAI_API_KEY).toBe('test-key-123');
78
- expect(retrieved).toEqual(cfg);
79
- });
80
- });
81
- //# sourceMappingURL=config.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=faceDetection.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"faceDetection.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/faceDetection.test.ts"],"names":[],"mappings":""}