1- // import { createFFmpeg, fetchFile, type ProgressCallback } from '@ffmpeg.wasm/main';
1+ import { createWriteStream , existsSync } from 'fs' ;
2+ import { readFile } from 'fs/promises' ;
3+ import { Readable } from 'stream' ;
4+ import { finished } from 'stream/promises' ;
25import { FFmpeg } from '@ffmpeg.wasm/main' ;
36import type { Show } from '@prisma/client' ;
4- import { readFile , readdir } from 'fs/promises' ;
5- import { logProgress } from './logProgress' ;
67import core from '@ffmpeg.wasm/core-mt' ;
7- const flagPaths = [ './audio/wes-flagger.mp3' , './audio/scott-flagger.mp3' ] ;
8- import wasmPathAb from '@ffmpeg.wasm/core-mt/dist/core.wasm?url' ;
98import { env } from '$env/dynamic/private' ;
9+ import { logProgress } from './logProgress' ;
10+
11+ const flag_paths = [ './audio/wes-flagger.mp3' , './audio/scott-flagger.mp3' ] ;
12+
1013export type ProgressEvent = {
1114 duration ?: number ;
1215 ratio ?: number ;
1316 time : number ;
1417 percentage : number ;
1518} ;
1619
20+ async function downloadFile ( url : string , path : string ) {
21+ if ( existsSync ( path ) ) return ;
22+
23+ const stream = createWriteStream ( path ) ;
24+ const response = await fetch ( url ) ;
25+ if ( response . body ) {
26+ // @ts -expect-error body is readable
27+ await finished ( Readable . fromWeb ( response . body ) . pipe ( stream ) ) ;
28+ }
29+ }
30+
1731/**
1832 * Concatenates a show with flagger audio to help with diatirization
1933 * @returns {Promise<Buffer> } - The concatenated show
@@ -23,71 +37,73 @@ export async function addFlaggerAudio(show: Show): Promise<Buffer> {
2337 console . log ( 'ADDING FLAGGER AUDIO' ) ;
2438 const url = new URL ( show . url ) ;
2539 // Get the filename
26- const fileName = `${ show . number } .mp3` ;
40+ const file_name = `${ show . number } .mp3` ;
2741 // Get the base name
28- const [ baseName , extension ] = fileName . split ( '.' ) ;
42+ const [ base_name , extension ] = file_name . split ( '.' ) ;
2943 // create the output filename
30- const outputFilename = `${ show . number } -flagged.${ extension } ` ;
44+ const output_filename = `${ show . number } -flagged.${ extension } ` ;
3145 console . log ( `Downloading #${ show . number } - ${ show . title } ` ) ;
3246 console . log ( 'Creating ffmpeg instance' ) ;
47+ await downloadFile (
48+ 'https://cdn.jsdelivr.net/npm/@ffmpeg.wasm/core-mt@0.13.2/dist/core.wasm' ,
49+ './core.wasm'
50+ ) ;
51+ await downloadFile (
52+ 'https://cdn.jsdelivr.net/npm/@ffmpeg.wasm/core-mt@0.13.2/dist/core.worker.js' ,
53+ './core.worker.cjs'
54+ ) ;
3355 const ffmpeg = await FFmpeg . create ( {
3456 log : true ,
3557 core : core ,
36- // Specify WASM paths for Vercel. These are copied into the function via a post-build script https://github.com/syntaxfm/website/issues/1175
37- ...( env . VERCEL && {
38- coreOptions : {
39- wasmPath : './core.wasm' ,
40- workerPath : './core.worker.cjs'
41- }
42- } ) ,
58+ coreOptions : {
59+ wasmPath : './core.wasm' ,
60+ workerPath : './core.worker.cjs'
61+ } ,
4362 logger : ( type , ...message ) => {
4463 logProgress ( message . join ( ' ' ) ) ;
4564 }
4665 } ) ;
4766 console . log ( 'Loading ffmpeg' ) ;
48- // await ffmpeg.load();
67+
4968 // 1. download the show
5069 // 1.1 See if the file exists first
51- const { ok } = await fetch ( url , { method : 'HEAD' } ) ;
70+ await fetch ( url , { method : 'HEAD' } ) ;
5271 console . log ( `Fetching ${ url } ` ) ;
53- const fetchBuffer = await fetch ( url )
72+ const fetch_buffer = await fetch ( url )
5473 . then ( ( res ) => res . arrayBuffer ( ) )
5574 . then ( ( buf ) => Buffer . from ( new Uint8Array ( buf ) ) ) ;
75+
5676 // Load it into ffmpeg memory
57- // ffmpeg.FS('writeFile', fileName, await fetchFile(fetchBuffer));
58- ffmpeg . fs . writeFile ( fileName , fetchBuffer ) ;
77+ ffmpeg . fs . writeFile ( file_name , fetch_buffer ) ;
5978
60- console . log ( `wrote ${ fileName } to ffmpeg memory` ) ;
79+ console . log ( `wrote ${ file_name } to ffmpeg memory` ) ;
6180 // Write Flaggers to ffmpeg memory
62- for ( const [ i , flagPath ] of flagPaths . entries ( ) ) {
81+ for ( const [ i , flag_path ] of flag_paths . entries ( ) ) {
82+ // eslint-disable-next-line @typescript-eslint/naming-convention
6383 const __dirname = new URL ( '.' , import . meta. url ) . pathname ;
64- const flagBuffer = await readFile ( env . VERCEL ? flagPath : `${ __dirname } /${ flagPath } ` ) ;
65- ffmpeg . fs . writeFile ( `flagger-${ baseName } -${ i } .mp3` , flagBuffer ) ;
66- console . log ( `wrote flagger-${ baseName } -${ i } .mp3 to ffmpeg memory` ) ;
84+ const flag_buffer = await readFile ( env . VERCEL ? flag_path : `${ __dirname } /${ flag_path } ` ) ;
85+ ffmpeg . fs . writeFile ( `flagger-${ base_name } -${ i } .mp3` , flag_buffer ) ;
86+ console . log ( `wrote flagger-${ base_name } -${ i } .mp3 to ffmpeg memory` ) ;
6787 }
6888
6989 // Create the Command
7090 const command = [
7191 '-i' ,
72- fileName ,
73- ...flagPaths . map ( ( flagPath , i ) => [ '-i' , `flagger-${ baseName } -${ i } .mp3` ] ) . flat ( ) ,
92+ file_name ,
93+ ...flag_paths . map ( ( flagPath , i ) => [ '-i' , `flagger-${ base_name } -${ i } .mp3` ] ) . flat ( ) ,
7494 '-filter_complex' ,
7595 '[0:a:0][1:a:0][2:a:0]concat=n=3:v=0:a=1[outa]' ,
7696 '-map' ,
7797 '[outa]' ,
78- outputFilename
98+ output_filename
7999 ] ;
80100
81101 console . log ( `Running ffmpeg with command: ${ command . join ( ' ' ) } ` ) ;
82102 // Run ffmpeg
83103 await ffmpeg . run ( ...command ) ;
84104 // Get the Uint8Array
85- const data = ffmpeg . fs . readFile ( outputFilename ) ;
105+ const data = ffmpeg . fs . readFile ( output_filename ) ;
86106 // Convert to buffer
87107 const buffer = Buffer . from ( data . buffer ) ;
88- // progressBar.stop();
89- console . log ( `FFMpeg Merging ` ) ;
90- // Write to disk from buffer for DEbugging
91- // await writeFile(`./audio-out/${outputFilename}`, buffer);
92108 return buffer ;
93109}
0 commit comments