electron fluent-ffmpeg mergeToFile()命令承诺不会触发

electron fluent-ffmpeg mergeToFile() command promise not triggering

我正在尝试将 fluent-ffmpeg 与我的 electron 应用程序一起使用,以将多个音频文件与视频中的图像连接在一起。所以如果我有三个文件:

song1.mp3 1:00 song2.mp3 0:30 song3.mp3 2:00 front.jpg

我可以创建 output.mp4,长度为 3:30 秒,并按顺序一个接一个地播放每个文件。 front.jpg 设置为背景图片。

我想先为这个视频创建连接的音频文件,然后我可以只渲染一个有两个输入的视频;图像和 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, outputFilepath, 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 显示承诺已输入,命令已创建,但函数只是结束而没有等待 resolve(); 等待几分钟不会有任何改变。

如果我再次按下按钮:

创建了一个新命令,到达了承诺的结尾,但这次实际上开始了,并触发了前一个命令开始。然后两个作业 运行 及其文件都以正确的长度 (12:08) 和正确的质量 (320k)

呈现

我的 promise 中有什么我需要修复的,涉及电子应用程序中的异步函数和 promise 吗?我尝试编辑我的 ffmpeg 命令以包含

command.run()

在我保证它被触发的承诺结束时;但这会导致控制台出错,说 Uncaught (in promise) Error: No output specified 因为显然在 fluent-ffmpeg command.mergeToFile(outputFilepath); 中不够好,我还需要包括 .output(outputFilepath)。如果我将 command.run() 更改为 command.output(outputFilepath).run(),当我单击我的按钮时,ffmpeg 作业将被触发并完美呈现。 除了文件总是 128kbps

所以我想弄清楚为什么我包含的代码块,我的 ffmpeg 命令在第一次创建时没有 运行。

我试过这个,我发现你的原始代码有同样的问题,文件正在以 128k 比特率输出。

此代码似乎有效,但我得到的最大比特率为 320k(我认为这是编解码器的限制)。

再次测试后,我认为我得到了与您相同的行为,因为文件需要一些时间才能生成。如果我 return 来自 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;
}