提问者:小点点

在循环中更改视频分辨率


我正在尝试降低视频的分辨率到500x500以下。 我不想把它改成500x500,因为那会把视频质量搞砸。 所以我想做的是在一个循环中降低75%的分辨率,这个循环只会在视频低于500x500时停止。 理论上这并不难,但我似乎搞不清楚。

var vidwidth = 501; //Create variable and put it to 501
var vidheight = 501; //so that it won't go through the If Statement
fs.copyFile(filepath2, './media/media.mp4', (err: any) => { //Copy given file to directory
    console.log('filepath2 was copied to media.mp4'); //Log confirmation (Not appearing for some reason, but file is copied)
})
while (true) {
    getDimensions('./media/media.mp4').then(function (dimensions: any) { //Get dimensions of copied video
        var vidwidth = parseInt(dimensions.width)   //Parse to Int
        var vidheight = parseInt(dimensions.height) //and put in variables
    })
    ffmpeg('./media/media.mp4')                 //Call ffmpeg function with copied video path
        .output('./media/media.mp4')            //Set output to the same file so we can loop it
        .size('75%')                            //Reduce resolution by 75%
        .on('end', function() {                 //Log confirmation on end
            console.log('Finished processing'); //(Not appearing)
        })                                      //
        .run();                                 //Run function
    if (vidwidth < 500 && vidheight < 500) {    //Check if both the width and height is under 500px
        break;                                  //If true, break the loop and continue
    }
}

这是我现在使用的注释代码。 基本上,它会被困在while循环中,因为视频的尺寸不会改变。 使用console.log()行进行了测试。 我认为,如果我能以某种方式修复ffmpeg问题,它就会全部修复。 如有任何帮助,我将不胜感激:)

PS:这都是在打字脚本中制作的,然后使用npx tsc构建到js中


共1个答案

匿名用户

问题是循环阻止了回调的调用,因为javascript运行在一个线程上(请参阅另一个SO问题:从不调用异步函数的回调)。 不被调用的回调之一是then的回调,其中变量vidwidthvidheight被更改,因此检查它们是否小于500并最终中断循环的条件永远不是true,循环将永远运行。 无论如何,这都不是处理异步函数的正确方法(请参阅另一个SO问题:如何从异步调用返回响应?)。

顺便说一下,copyfilewhile循环对于这种工作根本不是必需的,您只需使用getdimensions获取视频的维度,根据它们计算所需的维度并启动ffmpeg任务(ffmpeg将处理结果文件的创建,而不改变输入文件,因此不需要copyfile)。 像这样:

getDimensions(filepath2).then((dimensions: any) => {                            // get the dimension of the input file
  let sizeStr = dimensions.width < dimensions.height ? "?x500" : "500x?";       // if width is smaller than height, reduce the height to 500 and calculate width based on that, same goes for the other way around
  
  ffmpeg(filepath2)                                                             // the input is the original video, don't worry 'ffmpeg' won't alter the input file
    .output('./media/media.mp4')                                                // the output file path
    .size(sizeStr)                                                              // use the 'sizeStr' string calculated previously (read more about it here: https://github.com/fluent-ffmpeg/node-fluent-ffmpeg#video-frame-size-options) 
    .on('end', () => console.log('Finished processing'))
    .run();       
});

就这么简单!