使用forfiles+FFmpeg批量加字幕报错:空格文件名致格式选择失败
问题
尝试用forfiles脚本批量给文件夹内的MP4视频添加字幕,脚本如下:
forfiles /p "C:\Users\titos\Resilio_Sync\4K_Video_Downloader\videoprocess" /m *.mp4 /C "cmd /c set filename=@fname & ffmpeg -i @file -vf subtitles=\"C:\Users\titos\Resilio_Sync\4K_Video_Downloader\videoprocess\@fname.srt\" -f mp4 \"C:\Users\titos\Resilio_Sync\4K_Video_Downloader\donesubs\@fname_srt.mp4\""
但所有文件名含空格的视频都会触发错误,示例错误信息:
[AVFormatContext @ 0000020c20220680] Unable to choose an output format for 'Der'; use a standard extension for the filename or specify the format manually. [out#0 @ 0000020c20220580] Error initializing the muxer for Der: Invalid argument Error opening output file Der. Error opening output files: Invalid argument
其中“Der”是视频标题的第二个单词,推测是空格导致FFmpeg解析异常,但不清楚为何是第二个单词触发错误,也不知道如何修复脚本。
原因分析
问题出在forfiles的参数传递与cmd的引号解析冲突:
- 当文件名带空格时,
@fname会被拆分成多个独立参数,比如文件名是X Der Y.mp4,@fname会被解析成X、Der、Y三个部分。 - 脚本里的引号只包裹了路径,但
@fname本身没有被额外引号包裹,导致cmd执行时,空格后的Der被当成了ffmpeg的新参数——也就是错误里的“输出文件Der”,自然无法识别格式。
解决方法
需要给@fname添加额外的引号,同时调整forfiles里的转义方式,确保cmd能正确识别带空格的文件名。修正后的脚本如下:
forfiles /p "C:\Users\titos\Resilio_Sync\4K_Video_Downloader\videoprocess" /m *.mp4 /C "cmd /c ffmpeg -i \"@file\" -vf subtitles=\"C:\Users\titos\Resilio_Sync\4K_Video_Downloader\videoprocess\@fname.srt\" -f mp4 \"C:\Users\titos\Resilio_Sync\4K_Video_Downloader\donesubs\@fname_srt.mp4\""
关键修改点:
- 给
@file加上转义引号\"@file\",确保输入文件路径被完整识别,避免空格拆分。 - 去掉多余的
set filename=@fname,直接使用@fname变量,减少参数传递的歧义。 - 确保所有包含变量的路径都被转义引号包裹,让ffmpeg能正确读取带空格的字幕文件和输出路径。
如果上述脚本仍有问题,可以改用延迟变量扩展的方式,进一步避免解析冲突:
forfiles /p "C:\Users\titos\Resilio_Sync\4K_Video_Downloader\videoprocess" /m *.mp4 /C "cmd /v:on /c set \"fname=@fname\" & ffmpeg -i \"@file\" -vf subtitles=\"C:\Users\titos\Resilio_Sync\4K_Video_Downloader\videoprocess\!fname!.srt\" -f mp4 \"C:\Users\titos\Resilio_Sync\4K_Video_Downloader\donesubs\!fname!_srt.mp4\""
这里开启了/v:on启用延迟变量扩展,用!fname!代替%fname%,确保变量在文件名带空格时不会被拆分。
内容的提问来源于stack exchange,提问作者Miguel Arrieche
相关产品推荐
相关产品推荐

