问题描述
我正尝试在我的 electron 应用程序中使用fluent-ffmpeg来连接多个音频文件以及视频中的图像。因此,如果我有三个文件:
歌曲1.mp3 1:00 song2.mp3 0:30 song3.mp3 2:00 front.jpg
我可以创建长度为3:30秒的output.mp4
,然后依次播放每个文件。将front.jpg设置为背景图像。
我试图首先为该视频创建级联的音频文件,然后我可以使用两个输入渲染一个vid。图片和3:30秒长的串联音频文件。但是我很难让我的电子应用程序等待ffmpeg作业运行并完成。
我知道如何在命令行上完成所有这些ffmpeg作业,但是我一直遵循this指南如何将ffmpeg打包到可以在mac / win10 / linux环境下运行的电子应用程序中。我现在正在win10上开发它。 gur.com/LtykP.png
我有一个按钮:
<button onClick='fullAlbum("upload-${uploadNumber}")'>FULLALBUM</button>
当我单击时运行fullAlbum()
函数,该函数调用combineMp3FilesOrig
运行实际的ffmpeg作业:
async function fullAlbum(uploadName) {
//document.getElementById("buttonId").disabled = true;
//get table
var table = $(`#upload_${uploadNumber}_table`).DataTable()
//get all selected rows
var selectedRows = table.rows( '.selected' ).data()
//get outputFile location
var path = require('path');
var outputDir = path.dirname(selectedRows[0].audioFilepath)
//create outputfile
var timestamp = new Date().getUTCMilliseconds();
let outputFilepath = `${outputDir}/output-${timestamp}.mp3`
console.log('fullAlbum() button pressed: ',timestamp)
await combineMp3FilesOrig(selectedRows,outputFilepath,'320k',timestamp);
//document.getElementById("buttonId").disabled = false;
console.log(`fullAlbum() /output-${timestamp}.mp3 should be created Now`)
}
function combineMp3FilesOrig(selectedRows,bitrate,timestamp) {
console.log(`combineMp3FilesOrig(): ${outputFilepath}`)
//begin get ffmpeg info
const ffmpeg = require('fluent-ffmpeg');
//Get the paths to the packaged versions of the binaries we want to use
const ffmpegPath = require('ffmpeg-static').replace('app.asar','app.asar.unpacked');
const ffprobePath = require('ffprobe-static').path.replace('app.asar','app.asar.unpacked');
//tell the ffmpeg package where it can find the needed binaries.
ffmpeg.setFfmpegPath(ffmpegPath);
ffmpeg.setFfprobePath(ffprobePath);
//end set ffmpeg info
//create ffmpeg command
console.log(`combineMp3FilesOrig(): create command`)
const command = ffmpeg();
//set command inputs
command.input('C:\\Users\\marti\\Documents\\martinradio\\uploads\\CharlyBoyUTurn\\5. Akula (Club Mix).flac')
command.input('C:\\Users\\marti\\Documents\\martinradio\\uploads\\CharlyBoyUTurn\\4. Civilian Barracks.flac')
return new Promise((resolve,reject) => {
console.log(`combineMp3FilesOrig(): command status logging`)
command.on('progress',function(progress) {
console.info(`Processing : ${progress.percent} % done`);
})
.on('codecData',function(data) {
console.log('codecData=',data);
})
.on('end',function() {
console.log('file has been converted succesfully; resolve() promise');
resolve();
})
.on('error',function(err) {
console.log('an error happened: ' + err.message,',reject()');
reject(err);
})
console.log(`combineMp3FilesOrig(): add audio bitrate to command`)
command.audioBitrate(bitrate)
console.log(`combineMp3FilesOrig(): tell command to merge inputs to single file`)
command.mergetoFile(outputFilepath);
console.log(`combineMp3FilesOrig(): end of promise`)
});
console.log(`combineMp3FilesOrig(): end of function`)
}
单击一次按钮后,console.logs显示输入了promise,创建了命令,但是该函数只是结束而无需等待resolve();。 等待几分钟不会改变任何东西。
如果我再次按下按钮:
创建了一个新命令,到达了诺言的尽头,但是这次实际上开始了,并触发了前一个命令的开始。然后运行这两个作业,并以正确的长度(12:08)和正确的质量(320k)呈现其文件
在电子应用程序中,我是否需要解决涉及异步功能和诺言的诺言?我尝试编辑ffmpeg命令以包含
command.run()
在我保证将其触发的承诺的结尾;但这会导致控制台出现错误,说Uncaught (in promise) Error: No output specified
,因为显然在流畅的ffmpeg command.mergetoFile(outputFilepath);
中还不够好,我还需要包含.output(outputFilepath)
。如果将command.run()
更改为command.output(outputFilepath).run()
,则当我单击按钮时,ffmpeg作业将被触发并呈现完美状态。 除了文件始终为128kbps
所以我试图弄清楚为什么我包含的代码块,我的ffmpeg命令在创建时不第一次运行。
解决方法
我已经玩过这个游戏,并且看到原始代码也有同样的问题,文件以128k比特率输出。
尽管我获得的最大比特率是320k(我认为这是编解码器的限制),但是这段代码似乎可以正常工作。
再次测试后,我认为我得到的行为与您相同,因为生成该文件需要一些时间。如果我从CombineMp3FilesOrig函数返回一个Promise,则在单击处理程序中等待。在通话结束之前,我将禁用按钮,显然您的按钮ID会有所不同。
function combineMp3FilesOrig(selectedRows,outputFile,bitrate) {
const command = ffmpeg();
var count = selectedRows.length;
for(var i = 0; i < count; i++){
command.input(selectedRows[i].audioFilepath)
}
return new Promise((resolve,reject) => {
command.on('progress',function(progress) {
console.info(`Processing : ${progress.percent} % done`);
})
.on('codecData',function(data) {
console.log('codecData=',data);
})
.on('end',function() {
console.log('file has been converted succesfully');
resolve();
})
.on('error',function(err) {
console.log('an error happened: ' + err.message);
reject(err);
}).audioBitrate(bitrate).mergeToFile(outputFile);
});
}
async function convertFiles() {
document.getElementById("buttonId").disabled = true;
await combineMp3FilesOrig(selectedRows,'output.mp3','320k');
document.getElementById("buttonId").disabled = false;
}