C++通过Boost调用FFmpeg失败,终端执行正常问题排查
Boost启动FFmpeg进程时滤镜链解析失败的问题
错误信息
[AVFilterGraph @ 0x3cfadc0] Error parsing filterchain "[0:v]split=3[v1][v2][v3];[v1]copy[v1out];[v2]scale=w=1280:h=720[v2out];[v3]scale=w=640:h=360[v3out]" [AVFilterGraph @ 0x2f9fb00] Error parsing filterchain [AVFilterGraph @ 0x3cfadc0] Trailing garbage after a filter: split=3[v1][v2][v3];[v1]copy[v1out];[v2]scale=w=1280:h=720[v2out];[v3]scale=w=640:h=360[v3out]
代码实现
std::vector<std::string> args; args.push_back("-i"); args.push_back("input.mp4"); args.push_back("-filter_complex"); args.push_back("\"[0:v]split=3[v1][v2][v3];[v1]copy[v1out];[v2]scale=w=1280:h=720[v2out];[v3]scale=w=640:h=360[v3out]\""); args.push_back("-map"); args.push_back("[v1out]"); args.push_back("-c:v:0"); args.push_back("libx264"); args.push_back("-x264-params"); args.push_back("\"nal-hrd=cbr:force-cfr=1\""); args.push_back("-b:v:0"); args.push_back("1M"); args.push_back("-maxrate:v:0"); args.push_back("2M"); args.push_back("-minrate:v:0"); args.push_back("2M"); args.push_back("-bufsize:v:0"); args.push_back("2M"); args.push_back("-preset"); args.push_back("fast"); args.push_back("-g"); args.push_back("48"); args.push_back("-sc_threshold"); args.push_back("0"); args.push_back("-keyint_min"); args.push_back("48"); args.push_back("-map"); args.push_back("[v2out]"); args.push_back("-c:v:1"); args.push_back("libx264"); args.push_back("-x264-params"); args.push_back("\"nal-hrd=cbr:force-cfr=1\""); args.push_back("-b:v:1"); args.push_back("1M"); args.push_back("-maxrate:v:1"); args.push_back("1M"); args.push_back("-minrate:v:1"); args.push_back("1M"); args.push_back("-bufsize:v:1"); args.push_back("1M"); args.push_back("-preset"); args.push_back("fast"); args.push_back("-g"); args.push_back("48"); args.push_back("-sc_threshold"); args.push_back("0"); args.push_back("-keyint_min"); args.push_back("48"); args.push_back("-map"); args.push_back("[v3out]"); args.push_back("-c:v:2"); args.push_back("libx264"); args.push_back("-x264-params"); args.push_back("\"nal-hrd=cbr:force-cfr=1\""); args.push_back("-b:v:2"); args.push_back("500K"); args.push_back("-maxrate:v:2"); args.push_back("500K"); args.push_back("-minrate:v:2"); args.push_back("500K"); args.push_back("-bufsize:v:2"); args.push_back("500K"); args.push_back("-preset"); args.push_back("fast"); args.push_back("-g"); args.push_back("48"); args.push_back("-sc_threshold"); args.push_back("0"); args.push_back("-keyint_min"); args.push_back("48"); args.push_back("-map"); args.push_back("a:0"); args.push_back("-c:a:0"); args.push_back("aac"); args.push_back("-b:a:0"); args.push_back("96k"); args.push_back("-ac"); args.push_back("2"); args.push_back("-map"); args.push_back("a:0"); args.push_back("-c:a:1"); args.push_back("aac"); args.push_back("-b:a:1"); args.push_back("96k"); args.push_back("-ac"); args.push_back("2"); args.push_back("-map"); args.push_back("a:0"); args.push_back("-c:a:2"); args.push_back("aac"); args.push_back("-b:a:2"); args.push_back("48k"); args.push_back("-ac"); args.push_back("2"); args.push_back("-avoid_negative_ts"); args.push_back("1"); args.push_back("-f"); args.push_back("hls"); args.push_back("-hls_time"); args.push_back("6"); args.push_back("-hls_list_size"); args.push_back("15"); args.push_back("-hls_flags"); args.push_back("independent_segments"); args.push_back("-hls_segment_type"); args.push_back("mpegts"); args.push_back("-hls_segment_filename"); args.push_back("/output/stream_%v_data%02d.ts"); args.push_back("-master_pl_name"); args.push_back("index.m3u8"); args.push_back("-var_stream_map"); args.push_back("\"v:0,a:0 v:1,a:1 v:2,a:2\""); args.push_back("/output/stream_%v.m3u8"); m_childProcess = std::make_unique<bp::child>( bp::exe = ffmpegPath, bp::args = args);
代码生成的命令(格式化后)
ffmpeg -i input.mp4 -c copy -filter_complex "[0:v]split=3[v1][v2][v3];[v1]copy[v1out];[v2]scale=w=1280:h=720[v2out];[v3]scale=w=640:h=360[v3out]" -map [v1out] -c:v:0 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b:v:0 1M -maxrate:v:0 2M -minrate:v:0 2M -bufsize:v:0 2M -preset fast -g 48 -sc_threshold 0 -keyint_min 48 -map [v2out] -c:v:1 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b:v:1 1M -maxrate:v:1 1M -minrate:v:1 1M -bufsize:v:1 1M -preset fast -g 48 -sc_threshold 0 -keyint_min 48 -map [v3out] -c:v:2 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b:v:2 500K -maxrate:v:2 500K -minrate:v:2 500K -bufsize:v:2 500K -preset fast -g 48 -sc_threshold 0 -keyint_min 48 -map a:0 -c:a:0 aac -b:a:0 96k -ac 2 -map a:0 -c:a:1 aac -b:a:1 96k -ac 2 -map a:0 -c:a:2 aac -b:a:2 48k -ac 2 -avoid_negative_ts 1 -f hls -hls_time 6 -hls_list_size 15 -hls_flags independent_segments -hls_segment_type mpegts -hls_segment_filename /output/stream_%v_data%02d.ts -master_pl_name index.m3u8 -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2" /output/stream_%v.m3u8
问题原因及解决办法
问题出在参数中多余的双引号:
- 终端里用双引号是为了让Shell把包含分号、空格等特殊字符的内容识别为单个参数,但Boost的
bp::args是直接将每个元素作为独立参数传递给FFmpeg,不需要额外加引号。 - 你代码中给
-filter_complex、-x264-params、-var_stream_map的参数加了\",这些引号会被FFmpeg当作参数内容的一部分解析,导致滤镜链内容包含多余的首尾引号,触发"Trailing garbage"解析错误。
修改方法:去掉所有参数前后的双引号,示例如下:
// 原错误写法 // args.push_back("\"[0:v]split=3[v1][v2][v3];[v1]copy[v1out];[v2]scale=w=1280:h=720[v2out];[v3]scale=w=640:h=360[v3out]\""); // 修改后 args.push_back("[0:v]split=3[v1][v2][v3];[v1]copy[v1out];[v2]scale=w=1280:h=720[v2out];[v3]scale=w=640:h=360[v3out]"); // 原错误写法 // args.push_back("\"nal-hrd=cbr:force-cfr=1\""); // 修改后 args.push_back("nal-hrd=cbr:force-cfr=1"); // 原错误写法 // args.push_back("\"v:0,a:0 v:1,a:1 v:2,a:2\""); // 修改后 args.push_back("v:0,a:0 v:1,a:1 v:2,a:2");
内容的提问来源于stack exchange,提问作者Pit Digger
相关产品推荐
相关产品推荐

