My goal is to take two audio inputs and merge them. The below works for this, however, I want a continuous output stream even when only one of the two inputs are being streamed into FFmpeg. The below only produces an output when the stdin pipe input is receiving audio.
Here I have an FFmpeg child process where one input is a stream from the device’s microphone, the other comes from wav audio buffers sent to the server in clips by a client.
@Injectable()
export class AppService {
ffmpegProcess: ChildProcessWithoutNullStreams;
constructor() {
this.start();
}
start() {
this.ffmpegProcess = spawn(ffmpegPath, [
'-f', 'avfoundation', // mac os media devices
'-i', ':1', // mac os microphone input
'-f', 'wav',
'-i', 'pipe:', // stdin input source
'-codec:a', 'aac',
'-b:a', '128k',
// '-ab', '32k',
'-f', 'hls',
'-hls_time', '4', // Segment duration (in seconds)
'-hls_list_size', '3', // Number of HLS segments to keep in playlist
'-hls_flags', 'delete_segments', // Automatically delete old segments
'-filter_complex', 'amerge=inputs=2',
'public/output.m3u8' // HLS playlist file name
]);
}
}
Here I’m piping wav audio buffers posted to the server and streamed as the stdin source to the FFMepg process, to be merged into the output.
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
) { }
@Post('broadcast')
@UseInterceptors(FileInterceptor('audio_data'))
uploadFile(@UploadedFile() file: Express.Multer.File) {
console.log(file);
Readable.from(file.buffer).pipe(this.appService.ffmpegProcess.stdin);
}
}
I’ve considered trying to pass in a null stream for the stdin when no submitted wav audio is present though I’m spinning my wheels. How can I produce a continuous output while only one of the two inputs are streaming, and while both are streaming?