如何修复C ++中的ffmpeg“断言错误”错误

时间:2019-05-08 22:38:10

标签: c++ ffmpeg

我正在编写一个程序来加速视频的安静部分,并且我希望支持长达2个小时的视频。

这是基于命令行的程序。我正在XCode中构建它,然后将已编译的程序复制到带有输入视频的文件夹中,然后从终端运行它。

我基本上是根据ffmpeg的silence_detect功能的时间生成一个命令来运行一个非常大的复杂过滤器,以加快视频的其他“部分”的速度,然后将所有这些部分连接在一起。

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include "CoreFoundation/CoreFoundation.h"

using namespace std;

int main(int argc, const char * argv[]) {
    CFBundleRef mainBundle = CFBundleGetMainBundle();
    CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
    char path[PATH_MAX];
    if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
    {
        // error!
    }
    CFRelease(resourcesURL);

    /************************************/
    /***********Getting Input************/
    /************************************/

    chdir(path);
    std::cout << "Current Path: " << path << std::endl;

    for (int i = 0; i < argc; i++){
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    string inpath = "input.mp4";
    string outpath = "output.mp4";
    if(argc >= 1){
        inpath = argv[1];
    }
    if(argc >= 2){
        outpath = argv[2];
    }
    string volcall = "ffmpeg -i \"" + inpath + "\" -af silencedetect=noise=-30dB:d=0.5 -f null - 2> " + inpath + "vol.txt";
    system(volcall.c_str());

    /************************************/
    /***********File Analysis************/
    /************************************/
    cout<<"Starting File Analysis"<<endl;

    string s;
    string sTotal;
    string sNew;

    ifstream in;
    in.open(inpath + "vol.txt");

    //loads entire document into sTotal
    while(!in.eof()) {
        getline(in, s);
        sTotal += s + "\n";
    }

    size_t pos = sTotal.find("silence_start"); //find location of first time
    sNew = sTotal.erase(0,pos); //delete everything prior to location found

    //START TIME EXTRACTION
    vector<double> startArr;
    vector<double> endArr;

    string term = "silence_start";
    int bpos = 0;

    while ((bpos = sNew.find(term,bpos)) != -1)
    {
        int posStart = 15 + bpos;
        string timeStart = sNew.substr (posStart,7);

        float timeSrt = stof (timeStart);
        startArr.push_back(timeSrt);
        cout<< (timeSrt / 2) <<endl;
        bpos += term.length();
    }

    //END TIME EXTRACTION
    string term2 = "silence_end";
    int bpos2 = 0;

    while ((bpos2 = sNew.find(term2,bpos2)) != -1)
    {
        int posStart = 13 + bpos2;
        string timeEnd = sNew.substr (posStart,7);

        float timeNd = stof (timeEnd);
        endArr.push_back(timeNd);
        cout<< (timeNd / 2) <<endl;
        bpos2 += term.length();
    }

    vector<double> totalArr(startArr);

    totalArr.insert( totalArr.end(), endArr.begin(), endArr.end() );
    sort(totalArr.begin(), totalArr.end());

    in.close();

    /************************************/
    /***********Video Editing************/
    /************************************/

    cout<<"Starting Video Editing"<<endl;

    string cmd = "";
    string acmd = "";

    cmd+= "ffmpeg -i " + inpath + " -filter_complex \"";

    double first_speed = 1.0;
    double second_speed = 2.0;
    vector<double> times(totalArr); //starts with next timecode after 0, ends with last timecode 
    int numTimes = times.size();

    cmd= cmd + "[0:v]trim=0:" + to_string(times[0]) + ",setpts=" + to_string(first_speed) + "*(PTS-STARTPTS)[v0]; ";
    acmd= acmd + "[0:a]atrim=0:" + to_string(times[0]) + ",asetpts=PTS-STARTPTS,atempo=" + to_string(first_speed) + "[a0]; ";

    double mySpeed;
    int i;
    for(i = 0; i < numTimes - 1; i++){
        mySpeed = i%2==1? first_speed : second_speed;
        cmd= cmd + "[0:v]trim=" + to_string(times[0 + i]) + ":" + to_string(times[1 + i]) + ",setpts=" + to_string(1 / mySpeed) + "*(PTS-STARTPTS)[v" + to_string(i+1) + "]; ";
        acmd= acmd + "[0:a]atrim=" + to_string(times[0 + i]) + ":" + to_string(times[1 + i]) + ",asetpts=PTS-STARTPTS,atempo=" + to_string(mySpeed) + "[a" + to_string(i+1) + "]; ";
    }
    cmd = cmd + "[0:v]trim=" + to_string(times[i]) + ",setpts=" + to_string(1/(i%2==1? first_speed : second_speed)) + "*(PTS-STARTPTS)[v" + to_string(i + 1) + "]; ";
    acmd= acmd + "[0:a]atrim=" + to_string(times[i]) + ",asetpts=PTS-STARTPTS,atempo=" + to_string(i%2==1? first_speed : second_speed) + "[a" + to_string(i + 1) + "]; ";

    string cnc = "";
    for(int j = 0; j < i + 2; j++){
        cnc = cnc + "[v" + to_string(j) + "][a" + to_string(j) + "]";
    }
    cnc = cnc + "concat=n=" + to_string(i + 2) + ":v=1:a=1";

    cmd = cmd + acmd + cnc + "\" -preset superfast -profile:v baseline " + outpath;

    system(cmd.c_str());
    return 0;
}

我希望输出的视频长度比输入的短。 (如果输入的视频没有安静的部分,则长度相等)。

这有时效果很好:

这是在shortening Jacksfilms' 'woooooww' video from 17.200 seconds to 13.434 seconds.中工作的实际命令

ffmpeg -loglevel verbose -i WOOOW.mp4 -filter_complex "[0:v]trim=0:0.978250,setpts=1.000000*(PTS-STARTPTS)[v0]; [0:v]trim=0.978250:2.452020,setpts=0.500000*(PTS-STARTPTS)[v1]; [0:v]trim=2.452020:3.706520,setpts=1.000000*(PTS-STARTPTS)[v2]; [0:v]trim=3.706520:5.565560,setpts=0.500000*(PTS-STARTPTS)[v3]; [0:v]trim=5.565560:7.122250,setpts=1.000000*(PTS-STARTPTS)[v4]; [0:v]trim=7.122250:8.272020,setpts=0.500000*(PTS-STARTPTS)[v5]; [0:v]trim=8.272020:8.892350,setpts=1.000000*(PTS-STARTPTS)[v6]; [0:v]trim=8.892350:10.034100,setpts=0.500000*(PTS-STARTPTS)[v7]; [0:v]trim=10.034100:11.695400,setpts=1.000000*(PTS-STARTPTS)[v8]; [0:v]trim=11.695400:13.783300,setpts=0.500000*(PTS-STARTPTS)[v9]; [0:v]trim=13.783300,setpts=1.000000*(PTS-STARTPTS)[v10]; [0:a]atrim=0:0.978250,asetpts=PTS-STARTPTS,atempo=1.000000[a0]; [0:a]atrim=0.978250:2.452020,asetpts=PTS-STARTPTS,atempo=2.000000[a1]; [0:a]atrim=2.452020:3.706520,asetpts=PTS-STARTPTS,atempo=1.000000[a2]; [0:a]atrim=3.706520:5.565560,asetpts=PTS-STARTPTS,atempo=2.000000[a3]; [0:a]atrim=5.565560:7.122250,asetpts=PTS-STARTPTS,atempo=1.000000[a4]; [0:a]atrim=7.122250:8.272020,asetpts=PTS-STARTPTS,atempo=2.000000[a5]; [0:a]atrim=8.272020:8.892350,asetpts=PTS-STARTPTS,atempo=1.000000[a6]; [0:a]atrim=8.892350:10.034100,asetpts=PTS-STARTPTS,atempo=2.000000[a7]; [0:a]atrim=10.034100:11.695400,asetpts=PTS-STARTPTS,atempo=1.000000[a8]; [0:a]atrim=11.695400:13.783300,asetpts=PTS-STARTPTS,atempo=2.000000[a9]; [0:a]atrim=13.783300,asetpts=PTS-STARTPTS,atempo=1.000000[a10]; [v0][a0][v1][a1][v2][a2][v3][a3][v4][a4][v5][a5][v6][a6][v7][a7][v8][a8][v9][a9][v10][a10]concat=n=11:v=1:a=1" -preset superfast -profile:v baseline shortWOWOUT.mp4 2> shortWOWOUT.mp4_log.txt

但是有时代码会停止并返回错误:

Assertion start_sample < end_sample || (start_sample == end_sample && !frame->nb_samples) failed at libavfilter/trim.c:303

这似乎仅在ffmpeg渲染3分钟左右的某个位置时发生。似乎与文件大小,分辨率,比特率,帧率或生成的命令的长度没有关联。似乎与输入视频的长度有关,但是我不确定这是什么。一个3分56秒的视频效果不错,但一个5分57英寸的视频却出错了。

是否可以解决此问题?还是当输入视频经过一些未知的截止时间时该程序注定要失败?

0 个答案:

没有答案