11import fs , { createWriteStream , createReadStream } from "fs" ;
22import path from "path" ;
3- import { path as ffmpegBin } from "@ ffmpeg-installer/ffmpeg " ;
4- import { path as ffprobeBin } from "@ ffprobe-installer/ffprobe " ;
3+ import ffmpegBin from "ffmpeg-static " ;
4+ import { path as ffprobeBin } from "ffprobe-static " ;
55import { file as tmpFile } from "tempy" ;
66import { waitFile } from "wait-file" ;
7- import { FFmpeggy } from "../FFmpeggy" ;
7+ import { FFmpeggy , FFmpeggyProgressEvent } from "../FFmpeggy" ;
88
9- // NOTE: "fs/promises" is not available in node 12
10- const { unlink, stat } = fs . promises ;
9+ // NOTE: "fs/promises" is not available in node 12 =(
10+ const { mkdir , rmdir , unlink, stat } = fs . promises ;
1111
1212FFmpeggy . DefaultConfig = {
1313 ...FFmpeggy . DefaultConfig ,
@@ -17,9 +17,9 @@ FFmpeggy.DefaultConfig = {
1717} ;
1818
1919describe ( "FFmpeggy" , ( ) => {
20- const sampleMp4 = path . join ( __dirname , "samples/sample1.mp4 " ) ;
21- const sampleMkv = path . join ( __dirname , "samples/sample1.mkv " ) ;
22- const sampleMp3 = path . join ( __dirname , "samples/sample1 .mp3" ) ;
20+ const sampleMkv = path . join ( __dirname , "samples/bunny1.mkv " ) ;
21+ const sampleMp4 = path . join ( __dirname , "samples/bunny2.mp4 " ) ;
22+ const sampleMp3 = path . join ( __dirname , "samples/audio .mp3" ) ;
2323 const tempFiles : string [ ] = [ ] ;
2424
2525 // bump jest timeout since file ops can take some time
@@ -31,18 +31,33 @@ describe("FFmpeggy", () => {
3131 return file ;
3232 }
3333
34+ beforeAll ( async ( ) => {
35+ try {
36+ await mkdir ( path . join ( __dirname , "samples/.temp/" ) ) ;
37+ } catch {
38+ // Ignore
39+ }
40+ } ) ;
41+
3442 afterAll ( async ( ) => {
3543 // Clean up temp files
36- await waitFile ( { resources : tempFiles } ) ;
37- await Promise . allSettled ( tempFiles . map ( unlink ) ) ;
44+ if ( tempFiles . length > 0 ) {
45+ await waitFile ( { resources : tempFiles } ) ;
46+ await Promise . allSettled ( tempFiles . map ( unlink ) ) ;
47+ }
48+ try {
49+ await rmdir ( path . join ( __dirname , "samples/.temp/" ) , { recursive : true } ) ;
50+ } catch {
51+ // Ignore
52+ }
3853 } ) ;
3954
4055 it ( "should initialize" , ( ) => {
4156 const ffmpeggy = new FFmpeggy ( ) ;
4257 expect ( ffmpeggy ) . toBeInstanceOf ( FFmpeggy ) ;
4358 } ) ;
4459
45- it ( "should copy sample .mp4 to temp file" , ( done ) => {
60+ it ( "should copy bunny2 .mp4 to temp file" , ( done ) => {
4661 const ffmpeggy = new FFmpeggy ( ) ;
4762 const tempFile = getTempFile ( "mp4" ) ;
4863 ffmpeggy
@@ -64,7 +79,7 @@ describe("FFmpeggy", () => {
6479 } ) ;
6580 } ) ;
6681
67- it ( "should stream sample1 .mkv to temp file" , async ( ) => {
82+ it ( "should stream bunny1 .mkv to temp file" , async ( ) => {
6883 const tempFile = getTempFile ( "mkv" ) ;
6984 const ffmpeggy = new FFmpeggy ( {
7085 autorun : true ,
@@ -79,7 +94,7 @@ describe("FFmpeggy", () => {
7994 expect ( pipedStats . size ) . toBeGreaterThan ( 0 ) ;
8095 } ) ;
8196
82- it ( "should stream sample1 .mp3 to temp file" , async ( ) => {
97+ it ( "should stream audio .mp3 to temp file" , async ( ) => {
8398 const tempFile = getTempFile ( "mp3" ) ;
8499 const ffmpeggy = new FFmpeggy ( {
85100 autorun : true ,
@@ -94,7 +109,7 @@ describe("FFmpeggy", () => {
94109 expect ( pipedStats . size ) . toBeGreaterThan ( 0 ) ;
95110 } ) ;
96111
97- it ( "should receive progress event" , ( done ) => {
112+ it . only ( "should receive progress event" , ( done ) => {
98113 expect . assertions ( 9 ) ;
99114 const tempFile = getTempFile ( "mp4" ) ;
100115 const ffmpeggy = new FFmpeggy ( ) ;
@@ -104,21 +119,84 @@ describe("FFmpeggy", () => {
104119 . setOutput ( tempFile )
105120 . run ( ) ;
106121
107- ffmpeggy . on ( "progress" , async ( e ) => {
108- expect ( e . frame ) . toBeGreaterThan ( 0 ) ;
109- expect ( e . fps ) . toBeDefined ( ) ;
110- expect ( e . q ) . toBeDefined ( ) ;
111- expect ( e . size ) . toBe ( 1055744 ) ;
112- expect ( e . time ) . toBeGreaterThan ( 0 ) ;
113- expect ( e . bitrate ) . toBeGreaterThan ( 0 ) ;
114- expect ( e . speed ) . toBeGreaterThan ( 0 ) ;
115- expect ( e . duration ) . toBeDefined ( ) ;
116- expect ( e . percent ) . toBeGreaterThan ( 0 ) ;
122+ let progress : FFmpeggyProgressEvent ;
123+ ffmpeggy . on ( "progress" , async ( p ) => {
124+ progress = p ;
117125 } ) ;
118126
119- ffmpeggy . on ( "exit" , async ( ) => {
120- done ( ) ;
127+ ffmpeggy . on ( "exit" , async ( code , error ) => {
128+ expect ( progress . frame ) . toBeGreaterThan ( 0 ) ;
129+ expect ( progress . fps ) . toBeDefined ( ) ;
130+ expect ( progress . q ) . toBeDefined ( ) ;
131+ expect ( progress . size ) . toBe ( 1055744 ) ;
132+ expect ( progress . time ) . toBeGreaterThan ( 0 ) ;
133+ expect ( progress . bitrate ) . toBeGreaterThan ( 0 ) ;
134+ expect ( progress . speed ) . toBeGreaterThan ( 0 ) ;
135+ expect ( progress . duration ) . toBeDefined ( ) ;
136+ expect ( progress . percent ) . toBeGreaterThan ( 0 ) ;
137+
138+ if ( code === 1 || error ) {
139+ done . fail ( error ) ;
140+ } else {
141+ done ( ) ;
142+ }
143+ } ) ;
144+ } ) ;
145+
146+ it ( "should emit writing and done events for segments" , ( done ) => {
147+ expect . assertions ( 10 ) ;
148+ const ffmpeggy = new FFmpeggy ( {
149+ input : sampleMkv ,
150+ output : path . join ( __dirname , "samples/.temp/temp-%d.mpegts" ) ,
151+ outputOptions : [
152+ "-t 5" ,
153+ "-map 0" ,
154+ "-c:v libx264" ,
155+ "-c:a aac" ,
156+ "-r 25" ,
157+ "-force_key_frames expr:gte(t,n_forced*1)" ,
158+ "-f ssegment" ,
159+ "-forced-idr 1" ,
160+ "-flags +cgop" ,
161+ "-copyts" ,
162+ "-vsync -1" ,
163+ "-avoid_negative_ts disabled" ,
164+ "-individual_header_trailer 0" ,
165+ "-start_at_zero" ,
166+ "-segment_list_type m3u8" ,
167+ `-segment_list ${ path . join ( __dirname , "samples/.temp/playlist.m3u8" ) } ` ,
168+ "-segment_time 1" ,
169+ "-segment_format mpegts" ,
170+ ] ,
121171 } ) ;
172+
173+ let fileIdx = 0 ;
174+ ffmpeggy . on ( "writing" , ( file ) => {
175+ if ( file . includes ( "temp-" ) ) {
176+ expect ( file ) . toBe (
177+ path . join ( __dirname , "samples/.temp/" , `temp-${ fileIdx } .mpegts` )
178+ ) ;
179+ }
180+ } ) ;
181+
182+ ffmpeggy . on ( "done" , ( file ) => {
183+ if ( file ?. includes ( "temp-" ) ) {
184+ expect ( file ) . toBe (
185+ path . join ( __dirname , "samples/.temp/" , `temp-${ fileIdx } .mpegts` )
186+ ) ;
187+ fileIdx ++ ;
188+ }
189+ } ) ;
190+
191+ ffmpeggy . on ( "exit" , ( code , error ) => {
192+ if ( code === 1 || error ) {
193+ done . fail ( error ) ;
194+ } else {
195+ done ( ) ;
196+ }
197+ } ) ;
198+
199+ ffmpeggy . run ( ) ;
122200 } ) ;
123201
124202 describe ( "toStream()" , ( ) => {
@@ -141,7 +219,7 @@ describe("FFmpeggy", () => {
141219 } ) ;
142220
143221 describe ( "probe" , ( ) => {
144- it ( "should probe sample .mp4" , async ( ) => {
222+ it ( "should probe bunny2 .mp4" , async ( ) => {
145223 expect . assertions ( 5 ) ;
146224 const result = await FFmpeggy . probe ( sampleMp4 ) ;
147225 expect ( result . format ) . toBeDefined ( ) ;
0 commit comments