@@ -44,6 +44,28 @@ function missing(command: string): Error {
4444}
4545
4646describe ( "prepareVideo capability reporting" , ( ) => {
47+ it ( "extracts frames at exact times" , async ( ) => {
48+ const directory = await temporaryDirectory ( ) ;
49+ const inputPath = join ( directory , "clip.mp4" ) ;
50+ await writeFile ( inputPath , "video bytes" ) ;
51+
52+ const result = await prepareVideo (
53+ {
54+ command : "prepare" ,
55+ inputPath,
56+ artifactsDirectory : join ( directory , "artifacts" ) ,
57+ only : "frames" ,
58+ timestampsSeconds : [ 3 , 1 ] ,
59+ } ,
60+ { cwd : directory , hostExec : workingExec ( ) } ,
61+ ) ;
62+
63+ if ( result . frames ?. outcome !== "ok" ) throw new Error ( "expected prepared frames" ) ;
64+ expect ( result . frames . sampling . timestampsSeconds ) . toEqual ( [ 1 , 3 ] ) ;
65+ expect ( result . audio ) . toBeNull ( ) ;
66+ expect ( isComplete ( result ) ) . toBe ( true ) ;
67+ } ) ;
68+
4769 it ( "creates and reports a temporary artifacts directory when the caller omits one" , async ( ) => {
4870 const directory = await temporaryDirectory ( ) ;
4971 const inputPath = join ( directory , "clip.mp4" ) ;
@@ -217,7 +239,12 @@ describe("prepareVideo audio coverage", () => {
217239 } ) ;
218240
219241 const result = await prepareVideo (
220- { command : "prepare" , inputPath, artifactsDirectory : join ( directory , "artifacts" ) } ,
242+ {
243+ command : "prepare" ,
244+ inputPath,
245+ artifactsDirectory : join ( directory , "artifacts" ) ,
246+ only : "audio" ,
247+ } ,
221248 {
222249 cwd : directory ,
223250 hostExec : async ( request ) => {
@@ -233,12 +260,54 @@ describe("prepareVideo audio coverage", () => {
233260 ) ;
234261
235262 if ( result . audio ?. outcome !== "ok" ) throw new Error ( "expected an extracted audio lane" ) ;
263+ expect ( result . frames ) . toBeNull ( ) ;
236264 expect ( result . audio . selection . omittedStreamIndexes ) . toEqual ( [ ] ) ;
237265 expect ( isComplete ( result ) ) . toBe ( true ) ;
238266 } ) ;
239267} ) ;
240268
241269describe ( "prepareVideo source identity" , ( ) => {
270+ it ( "stops before tooling when the source changes between passes" , async ( ) => {
271+ const directory = await temporaryDirectory ( ) ;
272+ const inputPath = join ( directory , "clip.mp4" ) ;
273+ const artifactsDirectory = join ( directory , "artifacts" ) ;
274+ await writeFile ( inputPath , "first video bytes" ) ;
275+ const first = await prepareVideo (
276+ { command : "prepare" , inputPath, artifactsDirectory, only : "audio" } ,
277+ { cwd : directory , hostExec : workingExec ( ) } ,
278+ ) ;
279+ await writeFile ( inputPath , "different video bytes" ) ;
280+ let called = false ;
281+
282+ const second = await prepareVideo (
283+ {
284+ command : "prepare" ,
285+ inputPath,
286+ artifactsDirectory,
287+ expectedSha256 : first . file . sha256 ,
288+ only : "frames" ,
289+ timestampsSeconds : [ 1 ] ,
290+ } ,
291+ {
292+ cwd : directory ,
293+ hostExec : async ( ) => {
294+ called = true ;
295+ return { exitCode : 0 , stdout : "" , stderr : "" } ;
296+ } ,
297+ } ,
298+ ) ;
299+
300+ expect ( second . inputChanged ) . toMatchObject ( {
301+ outcome : "input-changed" ,
302+ initialSha256 : first . file . sha256 ,
303+ finalSha256 : second . file . sha256 ,
304+ } ) ;
305+ expect ( second . frames ) . toBeNull ( ) ;
306+ expect ( second . audio ) . toBeNull ( ) ;
307+ expect ( called ) . toBe ( false ) ;
308+ expect ( isComplete ( second ) ) . toBe ( false ) ;
309+ } ) ;
310+
242311 it ( "discards every derivative and reports input-changed when the original moved underneath it" , async ( ) => {
243312 const directory = await temporaryDirectory ( ) ;
244313 const inputPath = join ( directory , "clip.mp4" ) ;
0 commit comments