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,406 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- // Use vi.hoisted to ensure mock fns are available before vi.mock factories
3
- const { mockExecFile, mockMkdir, mockCopyFile, mockDetectWebcam, mockGetVideoResolution } = vi.hoisted(() => ({
4
- mockExecFile: vi.fn(),
5
- mockMkdir: vi.fn(),
6
- mockCopyFile: vi.fn(),
7
- mockDetectWebcam: vi.fn(),
8
- mockGetVideoResolution: vi.fn(),
9
- }));
10
- vi.mock('child_process', () => ({
11
- execFile: mockExecFile,
12
- }));
13
- vi.mock('fs', async (importOriginal) => {
14
- const original = await importOriginal();
15
- return {
16
- ...original,
17
- promises: {
18
- ...original.promises,
19
- mkdir: mockMkdir,
20
- copyFile: mockCopyFile,
21
- },
22
- };
23
- });
24
- // Mock logger
25
- vi.mock('../config/logger.js', () => ({
26
- default: {
27
- info: vi.fn(),
28
- warn: vi.fn(),
29
- error: vi.fn(),
30
- debug: vi.fn(),
31
- },
32
- }));
33
- // Mock face detection — return null (no webcam) so smart portrait falls back to center-crop
34
- vi.mock('../tools/ffmpeg/faceDetection', () => ({
35
- detectWebcamRegion: mockDetectWebcam,
36
- getVideoResolution: mockGetVideoResolution,
37
- }));
38
- import { convertAspectRatio, convertToPortraitSmart, convertToSquareSmart, convertToFeedSmart, generatePlatformVariants, PLATFORM_RATIOS, DIMENSIONS, } from '../tools/ffmpeg/aspectRatio.js';
39
- // ── Helpers ─────────────────────────────────────────────────────────────────
40
- /** Make execFile succeed by default */
41
- function execFileSucceeds() {
42
- mockExecFile.mockImplementation((...args) => {
43
- const cb = args[args.length - 1];
44
- if (typeof cb === 'function')
45
- cb(null, '', '');
46
- });
47
- }
48
- /** Make execFile fail */
49
- function execFileFails(message = 'ffmpeg error') {
50
- mockExecFile.mockImplementation((...args) => {
51
- const cb = args[args.length - 1];
52
- if (typeof cb === 'function')
53
- cb(new Error(message), '', message);
54
- });
55
- }
56
- /** Extract the -vf filter argument from execFile calls */
57
- function getCapturedFilter() {
58
- const call = mockExecFile.mock.calls[0];
59
- if (!call)
60
- return undefined;
61
- const args = call[1];
62
- const vfIdx = args.indexOf('-vf');
63
- return vfIdx >= 0 ? args[vfIdx + 1] : undefined;
64
- }
65
- beforeEach(() => {
66
- mockExecFile.mockReset();
67
- mockMkdir.mockReset().mockResolvedValue(undefined);
68
- mockCopyFile.mockReset().mockResolvedValue(undefined);
69
- mockDetectWebcam.mockReset().mockResolvedValue(null);
70
- mockGetVideoResolution.mockReset().mockResolvedValue({ width: 1920, height: 1080 });
71
- execFileSucceeds();
72
- });
73
- // ── Filter string generation ────────────────────────────────────────────────
74
- describe('Crop filter generation (via convertAspectRatio)', () => {
75
- it('9:16 portrait center-crop produces correct crop filter', async () => {
76
- await convertAspectRatio('/in.mp4', '/out.mp4', '9:16');
77
- const filter = getCapturedFilter();
78
- expect(filter).toContain('crop=ih*9/16:ih');
79
- expect(filter).toContain('scale=1080:1920');
80
- });
81
- it('1:1 square crop produces correct filter', async () => {
82
- await convertAspectRatio('/in.mp4', '/out.mp4', '1:1');
83
- const filter = getCapturedFilter();
84
- expect(filter).toContain('crop=ih:ih');
85
- expect(filter).toContain('scale=1080:1080');
86
- });
87
- it('4:5 Instagram feed produces correct filter', async () => {
88
- await convertAspectRatio('/in.mp4', '/out.mp4', '4:5');
89
- const filter = getCapturedFilter();
90
- expect(filter).toContain('crop=ih*4/5:ih');
91
- expect(filter).toContain('scale=1080:1350');
92
- });
93
- it('letterbox mode produces pad filter instead of crop', async () => {
94
- await convertAspectRatio('/in.mp4', '/out.mp4', '9:16', { letterbox: true });
95
- const filter = getCapturedFilter();
96
- expect(filter).toContain('pad=1080:1920');
97
- expect(filter).toContain('force_original_aspect_ratio=decrease');
98
- expect(filter).not.toContain('crop=');
99
- });
100
- it('16:9 same-ratio copies file instead of re-encoding', async () => {
101
- await convertAspectRatio('/in.mp4', '/out.mp4', '16:9');
102
- expect(mockCopyFile).toHaveBeenCalledWith('/in.mp4', '/out.mp4');
103
- expect(mockExecFile).not.toHaveBeenCalled();
104
- });
105
- it('16:9 with letterbox still encodes (not a copy)', async () => {
106
- await convertAspectRatio('/in.mp4', '/out.mp4', '16:9', { letterbox: true });
107
- expect(mockExecFile).toHaveBeenCalled();
108
- const filter = getCapturedFilter();
109
- expect(filter).toContain('scale=1920:1080');
110
- });
111
- });
112
- // ── Platform variant generation ─────────────────────────────────────────────
113
- describe('generatePlatformVariants', () => {
114
- it('returns expected variants for default platforms', async () => {
115
- const platforms = ['tiktok', 'youtube-shorts', 'instagram-reels', 'instagram-feed', 'linkedin'];
116
- const variants = await generatePlatformVariants('/in.mp4', '/out', 'my-short', platforms);
117
- // 9:16 platforms: tiktok, youtube-shorts, instagram-reels (one encode, 3 entries)
118
- // 4:5: instagram-feed (1 entry)
119
- // 1:1: linkedin (1 entry)
120
- expect(variants).toHaveLength(5);
121
- const portrait = variants.filter((v) => v.aspectRatio === '9:16');
122
- expect(portrait).toHaveLength(3);
123
- expect(portrait.map((v) => v.platform)).toEqual(expect.arrayContaining(['tiktok', 'youtube-shorts', 'instagram-reels']));
124
- const feed = variants.filter((v) => v.aspectRatio === '4:5');
125
- expect(feed).toHaveLength(1);
126
- expect(feed[0].platform).toBe('instagram-feed');
127
- const square = variants.filter((v) => v.aspectRatio === '1:1');
128
- expect(square).toHaveLength(1);
129
- expect(square[0].platform).toBe('linkedin');
130
- });
131
- it('each variant has correct dimensions for its aspect ratio', async () => {
132
- const platforms = ['tiktok', 'instagram-feed', 'linkedin'];
133
- const variants = await generatePlatformVariants('/in.mp4', '/out', 'clip', platforms);
134
- for (const v of variants) {
135
- const expectedDims = DIMENSIONS[v.aspectRatio];
136
- expect(v.width).toBe(expectedDims.width);
137
- expect(v.height).toBe(expectedDims.height);
138
- }
139
- });
140
- it('skips 16:9 platforms (original ratio)', async () => {
141
- const platforms = ['youtube', 'tiktok'];
142
- const variants = await generatePlatformVariants('/in.mp4', '/out', 'clip', platforms);
143
- // youtube is 16:9 → skipped; only tiktok (9:16) remains
144
- expect(variants).toHaveLength(1);
145
- expect(variants[0].platform).toBe('tiktok');
146
- });
147
- it('deduplicates encodes for same aspect ratio', async () => {
148
- const platforms = ['tiktok', 'youtube-shorts'];
149
- await generatePlatformVariants('/in.mp4', '/out', 'clip', platforms);
150
- // Both are 9:16 → only one ffmpeg encode (via convertToPortraitSmart fallback)
151
- // convertToPortraitSmart calls convertAspectRatio once when no webcam detected
152
- const ffmpegCalls = mockExecFile.mock.calls.filter((c) => c[0] !== 'ffprobe');
153
- expect(ffmpegCalls).toHaveLength(1);
154
- });
155
- });
156
- // ── Constants ───────────────────────────────────────────────────────────────
157
- describe('PLATFORM_RATIOS constant', () => {
158
- it('maps all platforms to valid aspect ratios', () => {
159
- const validRatios = ['16:9', '9:16', '1:1', '4:5'];
160
- for (const [platform, ratio] of Object.entries(PLATFORM_RATIOS)) {
161
- expect(validRatios).toContain(ratio);
162
- }
163
- });
164
- it('tiktok and youtube-shorts are 9:16', () => {
165
- expect(PLATFORM_RATIOS['tiktok']).toBe('9:16');
166
- expect(PLATFORM_RATIOS['youtube-shorts']).toBe('9:16');
167
- });
168
- it('instagram-feed is 4:5', () => {
169
- expect(PLATFORM_RATIOS['instagram-feed']).toBe('4:5');
170
- });
171
- });
172
- describe('DIMENSIONS constant', () => {
173
- it('has dimensions for all aspect ratios', () => {
174
- expect(DIMENSIONS['16:9']).toEqual({ width: 1920, height: 1080 });
175
- expect(DIMENSIONS['9:16']).toEqual({ width: 1080, height: 1920 });
176
- expect(DIMENSIONS['1:1']).toEqual({ width: 1080, height: 1080 });
177
- expect(DIMENSIONS['4:5']).toEqual({ width: 1080, height: 1350 });
178
- });
179
- });
180
- // ── Error handling ──────────────────────────────────────────────────────────
181
- describe('Error handling', () => {
182
- it('convertAspectRatio rejects when ffmpeg fails', async () => {
183
- execFileFails('Conversion error');
184
- await expect(convertAspectRatio('/in.mp4', '/out.mp4', '9:16')).rejects.toThrow('Aspect ratio conversion failed');
185
- });
186
- it('generatePlatformVariants skips failed ratios gracefully', async () => {
187
- execFileFails('encode failed');
188
- const variants = await generatePlatformVariants('/in.mp4', '/out', 'clip', ['tiktok', 'linkedin']);
189
- // All fail → empty array, no throw
190
- expect(variants).toEqual([]);
191
- });
192
- });
193
- // ── Smart portrait: screen crop & face padding ─────────────────────────────
194
- describe('convertToPortraitSmart – screen crop & face padding', () => {
195
- /** Extract the -filter_complex argument from execFile calls */
196
- function getCapturedFilterComplex() {
197
- const call = mockExecFile.mock.calls[0];
198
- if (!call)
199
- return undefined;
200
- const args = call[1];
201
- const idx = args.indexOf('-filter_complex');
202
- return idx >= 0 ? args[idx + 1] : undefined;
203
- }
204
- it('screen crop excludes webcam region (bottom-right)', async () => {
205
- mockDetectWebcam.mockResolvedValue({
206
- x: 1440, y: 810, width: 480, height: 270,
207
- position: 'bottom-right', confidence: 0.8,
208
- });
209
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
210
- await convertToPortraitSmart('/in.mp4', '/out.mp4');
211
- const fc = getCapturedFilterComplex();
212
- expect(fc).toBeDefined();
213
- // Screen crop uses webcam.x directly as width (no hardcoded margin)
214
- expect(fc).toContain('crop=1440:ih:0:0');
215
- });
216
- it('screen crop excludes webcam region (bottom-left)', async () => {
217
- mockDetectWebcam.mockResolvedValue({
218
- x: 0, y: 810, width: 480, height: 270,
219
- position: 'bottom-left', confidence: 0.8,
220
- });
221
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
222
- await convertToPortraitSmart('/in.mp4', '/out.mp4');
223
- const fc = getCapturedFilterComplex();
224
- expect(fc).toBeDefined();
225
- // Screen crop starts after webcam (x + width) with remaining width
226
- expect(fc).toContain('crop=1440:ih:480:0');
227
- });
228
- it('face crop matches target aspect ratio and fills bottom section', async () => {
229
- const webcamW = 480;
230
- const webcamH = 270;
231
- mockDetectWebcam.mockResolvedValue({
232
- x: 1440, y: 810, width: webcamW, height: webcamH,
233
- position: 'bottom-right', confidence: 0.8,
234
- });
235
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
236
- await convertToPortraitSmart('/in.mp4', '/out.mp4');
237
- const fc = getCapturedFilterComplex();
238
- expect(fc).toBeDefined();
239
- // Target AR = 1080/672 = 1.607; webcam AR = 480/270 = 1.778 (wider)
240
- // So crop height = 270, width = round(270 * 1.607) = 434
241
- const targetAR = 1080 / 672;
242
- const expectedW = Math.round(webcamH * targetAR); // 434
243
- expect(fc).toContain(`crop=${expectedW}:${webcamH}`);
244
- // Should scale directly to 1080:672 with no padding
245
- expect(fc).toContain('scale=1080:672[cam]');
246
- expect(fc).not.toContain('force_original_aspect_ratio=increase');
247
- });
248
- it('screen crop uses detected webcam.x directly with no hardcoded margin', async () => {
249
- mockDetectWebcam.mockResolvedValue({
250
- x: 1728, y: 810, width: 192, height: 270,
251
- position: 'bottom-right', confidence: 0.9,
252
- });
253
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
254
- await convertToPortraitSmart('/in.mp4', '/out.mp4');
255
- const fc = getCapturedFilterComplex();
256
- expect(fc).toBeDefined();
257
- // With precise bbox detection, crop width = webcam.x = 1728
258
- expect(fc).toContain('crop=1728:ih:0:0');
259
- });
260
- it('screen crop handles webcam at far edge gracefully', async () => {
261
- mockDetectWebcam.mockResolvedValue({
262
- x: 20, y: 810, width: 480, height: 270,
263
- position: 'bottom-right', confidence: 0.8,
264
- });
265
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
266
- await convertToPortraitSmart('/in.mp4', '/out.mp4');
267
- const fc = getCapturedFilterComplex();
268
- expect(fc).toBeDefined();
269
- // webcam.x = 20, so screen crop is only 20px wide
270
- expect(fc).toContain('crop=20:ih:0:0');
271
- });
272
- });
273
- // ── Smart square: screen crop & face padding ────────────────────────────────
274
- describe('convertToSquareSmart – screen crop & face padding', () => {
275
- function getCapturedFilterComplex() {
276
- const call = mockExecFile.mock.calls[0];
277
- if (!call)
278
- return undefined;
279
- const args = call[1];
280
- const idx = args.indexOf('-filter_complex');
281
- return idx >= 0 ? args[idx + 1] : undefined;
282
- }
283
- it('falls back to center-crop when no webcam detected', async () => {
284
- mockDetectWebcam.mockResolvedValue(null);
285
- await convertToSquareSmart('/in.mp4', '/out.mp4');
286
- const filter = getCapturedFilter();
287
- expect(filter).toContain('crop=ih:ih');
288
- expect(filter).toContain('scale=1080:1080');
289
- });
290
- it('screen crop excludes webcam region (bottom-right)', async () => {
291
- mockDetectWebcam.mockResolvedValue({
292
- x: 1440, y: 810, width: 480, height: 270,
293
- position: 'bottom-right', confidence: 0.8,
294
- });
295
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
296
- await convertToSquareSmart('/in.mp4', '/out.mp4');
297
- const fc = getCapturedFilterComplex();
298
- expect(fc).toBeDefined();
299
- expect(fc).toContain('crop=1440:ih:0:0');
300
- });
301
- it('face crop matches target aspect ratio and fills bottom section', async () => {
302
- const webcamW = 480;
303
- const webcamH = 270;
304
- mockDetectWebcam.mockResolvedValue({
305
- x: 1440, y: 810, width: webcamW, height: webcamH,
306
- position: 'bottom-right', confidence: 0.8,
307
- });
308
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
309
- await convertToSquareSmart('/in.mp4', '/out.mp4');
310
- const fc = getCapturedFilterComplex();
311
- expect(fc).toBeDefined();
312
- // Target AR = 1080/380 = 2.842; webcam AR = 480/270 = 1.778 (narrower)
313
- // Keep full width, center-crop height: faceH = round(480 / (1080/380)) = 169
314
- const targetAR = 1080 / 380;
315
- const expectedH = Math.round(webcamW / targetAR);
316
- expect(fc).toContain(`crop=${webcamW}:${expectedH}`);
317
- // Should scale directly to 1080:380 with no padding
318
- expect(fc).toContain('scale=1080:380[cam]');
319
- });
320
- it('uses split-screen layout 700+380=1080', async () => {
321
- mockDetectWebcam.mockResolvedValue({
322
- x: 1440, y: 810, width: 480, height: 270,
323
- position: 'bottom-right', confidence: 0.8,
324
- });
325
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
326
- await convertToSquareSmart('/in.mp4', '/out.mp4');
327
- const fc = getCapturedFilterComplex();
328
- expect(fc).toBeDefined();
329
- expect(fc).toContain('scale=1080:700');
330
- expect(fc).toContain('scale=1080:380[cam]');
331
- expect(fc).toContain('vstack');
332
- });
333
- });
334
- // ── Smart feed: screen crop & face padding ──────────────────────────────────
335
- describe('convertToFeedSmart – screen crop & face padding', () => {
336
- function getCapturedFilterComplex() {
337
- const call = mockExecFile.mock.calls[0];
338
- if (!call)
339
- return undefined;
340
- const args = call[1];
341
- const idx = args.indexOf('-filter_complex');
342
- return idx >= 0 ? args[idx + 1] : undefined;
343
- }
344
- it('falls back to center-crop when no webcam detected', async () => {
345
- mockDetectWebcam.mockResolvedValue(null);
346
- await convertToFeedSmart('/in.mp4', '/out.mp4');
347
- const filter = getCapturedFilter();
348
- expect(filter).toContain('crop=ih*4/5:ih');
349
- expect(filter).toContain('scale=1080:1350');
350
- });
351
- it('screen crop excludes webcam region (bottom-right)', async () => {
352
- mockDetectWebcam.mockResolvedValue({
353
- x: 1440, y: 810, width: 480, height: 270,
354
- position: 'bottom-right', confidence: 0.8,
355
- });
356
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
357
- await convertToFeedSmart('/in.mp4', '/out.mp4');
358
- const fc = getCapturedFilterComplex();
359
- expect(fc).toBeDefined();
360
- expect(fc).toContain('crop=1440:ih:0:0');
361
- });
362
- it('face crop matches target aspect ratio and fills bottom section', async () => {
363
- const webcamW = 480;
364
- const webcamH = 270;
365
- mockDetectWebcam.mockResolvedValue({
366
- x: 1440, y: 810, width: webcamW, height: webcamH,
367
- position: 'bottom-right', confidence: 0.8,
368
- });
369
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
370
- await convertToFeedSmart('/in.mp4', '/out.mp4');
371
- const fc = getCapturedFilterComplex();
372
- expect(fc).toBeDefined();
373
- // Target AR = 1080/472 = 2.288; webcam AR = 480/270 = 1.778 (narrower)
374
- // Keep full width, center-crop height: faceH = round(480 / (1080/472)) = 210
375
- const targetAR = 1080 / 472;
376
- const expectedH = Math.round(webcamW / targetAR);
377
- expect(fc).toContain(`crop=${webcamW}:${expectedH}`);
378
- // Should scale directly to 1080:472 with no padding
379
- expect(fc).toContain('scale=1080:472[cam]');
380
- });
381
- it('uses split-screen layout 878+472=1350', async () => {
382
- mockDetectWebcam.mockResolvedValue({
383
- x: 1440, y: 810, width: 480, height: 270,
384
- position: 'bottom-right', confidence: 0.8,
385
- });
386
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
387
- await convertToFeedSmart('/in.mp4', '/out.mp4');
388
- const fc = getCapturedFilterComplex();
389
- expect(fc).toBeDefined();
390
- expect(fc).toContain('scale=1080:878');
391
- expect(fc).toContain('scale=1080:472[cam]');
392
- expect(fc).toContain('vstack');
393
- });
394
- it('screen crop excludes webcam region (bottom-left)', async () => {
395
- mockDetectWebcam.mockResolvedValue({
396
- x: 0, y: 810, width: 480, height: 270,
397
- position: 'bottom-left', confidence: 0.8,
398
- });
399
- mockGetVideoResolution.mockResolvedValue({ width: 1920, height: 1080 });
400
- await convertToFeedSmart('/in.mp4', '/out.mp4');
401
- const fc = getCapturedFilterComplex();
402
- expect(fc).toBeDefined();
403
- expect(fc).toContain('crop=1440:ih:480:0');
404
- });
405
- });
406
- //# sourceMappingURL=aspectRatio.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aspectRatio.test.js","sourceRoot":"","sources":["../../src/__tests__/aspectRatio.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=captionGenerator.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"captionGenerator.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/captionGenerator.test.ts"],"names":[],"mappings":""}