1.问题引发背景
原先在项目中,使用QProcess来调用启动ffmpeg进程来进行长时间的转码,但是发现有时候会出现程序经常异常退出的情况。
原先的启动方式(简化后的代码):
QProcess *ffmpeg_proc = new QProcess(this);
ffmpeg_proc->setProcessChannelMode(QProcess::SeparateChannels);
ffmpeg_proc->start("ffmpeg -i \"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000\" -f segment -segment_time 01:00:00 D:/shoulu/shoulu_%02d.mxf");
更改后的启动方式:
QString ffmpeg_file_path = qApp->applicationDirPath()+"/ffmpeg.exe";
QStringList list;
list<<"-y"<<"-i"<<"\"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000\""
<<"-f"<<"segment"
<<"-segment_time"<<"01:00:00"
<<"D:/shoulu/shoulu_%02d.mxf";
QProcess *ffmpeg_proc = new QProcess(this);
ffmpeg_proc->setProcessChannelMode(QProcess::SeparateChannels);
ffmpeg_proc->start(ffmpeg_file_path,list);
但是这样执行后发现,ffmpeg进程在后台一闪而逝,说明遇到问题了
于是,增加代码,获取输出
connect(proc,&QProcess::readyReadStandardError,this,[this](){
qDebug().noquote()<<proc->readAllStandardError()<<endl;
});
获得了ffmpeg输出以下的错误信息
"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000": Invalid argument
2.问题分析(猜想)
针对这个奇怪错误,先猜想了下问题发生的更深层次的原因
1.QStringList获取到我给的这个参数"\"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000\""时,是不是这个转义字符出问题了
上网查(摸)了半天资料(鱼),依旧没找到相关能论证这个猜想的资料,于是决定相信QT本身的设计不会出这种离谱问题,然后继续思(摸)考(鱼),提出了第二个猜想
2.会不会QStringList对"\"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000\""这个参数最后传递给ffmpeg时,多加了个双引号。
于是更改代码
list<<"-y"<<"-i"<<"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000"
<<"-f"<<"segment"
<<"-segment_time"<<"01:00:00"
<<"D:/shoulu/shoulu_%02d.mxf";
然后一运行发现,ffmpeg能正常在后台执行了
突然有点好奇,于是在cmd里运行了这个命令
"ffmpeg.exe" "-y" "-i" "udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000" "-f" "segment" "-segment_time" "01:00:00" "D:/shoulu/shoulu_%02d.mxf"
没想到所有的参数加个双引号后竟然能成功运行,长见识了
3.总结
使用QStringList将参数传递给QProcess时,一定要注意,QStringList会对每个参数额外使用双引号括起来(如果有大佬有不同的见解,欢迎在评论区留下你的痕迹)
4.2022-01-13 新增
最近在开发时遇到了一个奇怪的错误,QProcess+QStringList的方式调用ffmpeg时,ffmpeg会立即退出,并接收到报错信息
Output file #0 does not contain any stream
在查了半天资料后,发现了其中一个大神提出了不要在参数列表中参数里加空格,然后回去检查后发现,果然,在最后一个参数的".mxf"后面多加了一个空格,去掉这个空格就会正常执行。
面对这个诡异的情况(梦回曾经还是学生的时候,写C++程序时因在代码中多加了一个中文空格,而遇到报错的诡异情况),好奇心又出现,空格是一点都不能出现,还是在特定情况下不能出现。
经试验后发现:
list<<"-y"<<"-i"<<"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000"
<<"-f"<<"segment"
<<"-segment_time"<<"01:00:00"
<<"D:/shoulu/shoulu_%02d.mxf ";//有空格报错
list<<"-y"<<"-i"<<"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000"
<<"-f"<<"segment"
<<"-segment_time"<<"01:00:00"
<<"D:/shoulu/shoulu.mxf ";//虽然有空格,但是不报错
list<<"-y"<<"-i"<<"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000"
<<"-f"<<"segment"
<<"-segment_time"<<"01:00:00"
<<"D:/shou lu/shoulu_%02d.mxf"; //虽然也有空格,但是也不报错
list<<"-y"<<"-i"<<"udp://@238.123.43.2:8004?overrun_nonfatal=1&fifo_size=50000000"
<<"-f"<<"segment"
<<"-segment_time"<<"01:00:00"
<<"D:/shoulu/shoulu _%02d.mxf";//有空格报错