我通过fluent-ffmpeg使用FFmpeg通过Node.js将多个小音频文件合并为一个。我合并的每个音频文件都有一个延迟的开始时间(所以它既不是在同一个开始时合并,也不是在连接中合并)。我可以使用aevalsrc
=0
和concat
ing我的音频文件成功完成此操作,然后将amix
ing一切都关闭。但是,虽然我在文档中找不到对最大输入数的引用,但在尝试[amix @ 0x3fcd920] Value 78.000000 for parameter 'inputs' out of range [1 - 32]
78个文件时,我得到了amix
。显然,有32个输入文件的限制。
鉴于这种限制,我不确定最好的方法。我知道amerge
存在,但它在最短的文件长度后停止,所以我需要apad
所有内容我只是测试它并确定amerge
有64个输入文件的限制,这并不总是适合我的需要(我有任意数量的输入)。
我可以 amix
32个文件,存储在某个地方,amix
32个等等,以及amix
结果。我宁愿不处理将临时文件写入磁盘然后必须稍后清理。我考虑将“临时”输出写入双工节点流并在最后的混音中从中读取,但我担心这可能效率很低。
以下是我目前正在做的事情。如果这是一个XY problem,这是一种愚蠢的方式来实现我想要的,请告诉我。
ffmpeg()
//INPUTS
.input('/drummachine/www/audio/bd/bd5025.wav')
.input('/drummachine/www/audio/bd/bd5025.wav')
.input('/drummachine/www/audio/bd/bd5025.wav')
.input('/drummachine/www/audio/sd/sd5025.wav')
.input('/drummachine/www/audio/sd/sd5025.wav')
.input('/drummachine/www/audio/rs/rs.wav')
.input('/drummachine/www/audio/rs/rs.wav')
.input('/drummachine/www/audio/rs/rs.wav')
.input('/drummachine/www/audio/cp/cp.wav')
.input('/drummachine/www/audio/cp/cp.wav')
.input('/drummachine/www/audio/cp/cp.wav')
.input('/drummachine/www/audio/oh/oh25.wav')
.input('/drummachine/www/audio/oh/oh25.wav')
.input('/drummachine/www/audio/oh/oh25.wav')
.input('/drummachine/www/audio/ch/ch.wav')
.input('/drummachine/www/audio/ch/ch.wav')
.input('/drummachine/www/audio/ch/ch.wav')
// ...
// you get the picture
// ...
.audioCodec('libmp3lame').format('mp3')
.complexFilter([
//GENERATE SILENCE TO PREPEND TO INPUTS
'aevalsrc=0:d=6.857142857142857[s78]',
'aevalsrc=0:d=0[s0]',
'aevalsrc=0:d=0.857[s1]',
'aevalsrc=0:d=1.714[s2]',
'aevalsrc=0:d=2.571[s3]',
'aevalsrc=0:d=3.429[s4]',
'aevalsrc=0:d=4.286[s5]',
'aevalsrc=0:d=5.143[s6]',
'aevalsrc=0:d=6[s7]',
'aevalsrc=0:d=0.429[s8]',
'aevalsrc=0:d=1.286[s9]',
'aevalsrc=0:d=2.143[s10]',
'aevalsrc=0:d=3[s11]',
'aevalsrc=0:d=3.857[s12]',
'aevalsrc=0:d=4.714[s13]',
'aevalsrc=0:d=5.571[s14]',
'aevalsrc=0:d=6.429[s15]',
'aevalsrc=0:d=0.536[s16]',
// ...
//CONCAT SILENCE AND AUDIO
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s0', '0:a'], outputs: 'ac0'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s1', '1:a'], outputs: 'ac1'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s2', '2:a'], outputs: 'ac2'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s3', '3:a'], outputs: 'ac3'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s4', '4:a'], outputs: 'ac4'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s5', '5:a'], outputs: 'ac5'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s6', '6:a'], outputs: 'ac6'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s7', '7:a'], outputs: 'ac7'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s8', '8:a'], outputs: 'ac8'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s9', '9:a'], outputs: 'ac9'},
{filter: 'concat', options: {v: 0, a: 1}, inputs: ['s10', '10:a'], outputs: 'ac10'},
// ...
// again, this goes on for a while
// ...
//MIX IT ALL
{filter: 'amix', options: {inputs: 78, duration: 'longest'},
inputs: ['s78', 'ac0', 'ac1', 'ac2', 'ac3', 'ac4', 'ac5',
'ac6', 'ac7', 'ac8', 'ac9', 'ac10', 'ac11', 'ac12', 'ac13',
'ac14', 'ac15', 'ac16', 'ac17', 'ac18', 'ac19', 'ac20',
// ...
'ac74', 'ac75', 'ac76'], outputs: 'out'}], 'out')
//ERROR
.on('error', function (err, stdout, stderr) {
console.log('an error happened: ' + err.message);
console.log('ffmpeg stdout: ' + stdout);
console.log('ffmpeg stderr: ' + stderr);
//SUCCESS
}).on('end', function () {
console.log('Processing finished !');
res.end();
}).pipe(res);