我正在尝试自动将字幕添加到包含一些视频的文件夹中,因此我编写了以下脚本:
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 无法正确解析它?但为什么在这种情况下它得到的是第二个单词而不是第一个单词?更重要的是,我该怎么做才能解决这个问题?
我确实找到了一些讨论类似问题的其他帖子,但坦率地说,我仍然太新手了,无法理解任何答案,因此无法将其改编到我的脚本中,哈哈。感谢您的帮助,提前谢谢 :)
我设置了一个目录,其中包含一些与问题名称格式匹配的虚拟文件,并简单地
echo
编辑了结果ffmpeg
行。结果的形式如下(好的 - 为了方便查看,我断开了该线并用
subtitledir
和替换了donesubsdir
目录名称。)观察到引用的文件名出现在字符串中,并推测
ffmpeg
该结构可能存在困难,我建议您需要跟随弹跳的球
subtitledir
移动donesubsdir
。我的结果是:
(好的 - 为了方便查看,我断开了该线并用
subtitledir
和替换了donesubsdir
目录名称。)理论:
该命令
dir /b /a-d "%vpath%\*.mp4" 2^>nul
被执行并生成仅有文件名的行 (/b
),没有目录名 (/a-d
),这些行应用于%%e
。“delims=”表示for
不需要标记,因此整个名称出现在 中%%e
,2^>nul
抑制错误消息 -^
表示cmd
是命令>
的一部分dir
,而不是for
。(SO 上发布了数百甚至数千个类似的申请)
参见
for /?
SO 上的数千个关于使用元变量修饰符的示例。那么,
%%~ne
文件名中的名称部分仅仅是%%e
。该实用程序的帮助信息
forfiles
解释了如何"
用十六进制等效项替换嵌套的双引号0x22
。请使用该信息更改:
到
您可以将嵌套在外部双引号之间的任何导致问题的字符替换为其十六进制等效字符。例如
&
->0x26
、=
->0x3D
。对于嵌套的双引号,您还可以选择将其转义,而不是将其转换为十六进制。您可以使用反斜杠 来实现这一点
\
。就您而言,这意味着使用:
但是,这里还有另一个潜在问题;
forfiles
变量 、@File
、@FName
、@Ext
和@Path
均@RelPath
用双引号括起来。这些双引号可能会造成混淆ffmpeg.exe
。它将会看到:
为了解决这个问题,你需要以某种方式扩展这些变量以删除它们周围的双引号。这可以通过使用
for
循环来完成:十六进制转换的双引号示例:
转义双引号示例:
上面的内容通常是适合您所展示任务的正确语法,但是,这里还有另一个问题,您可能会遇到。 选项的值
cmd.exe
不能/C
超过253
字符长度,我认为上面的内容会超出该长度并返回一条ERROR
消息。为了解决这个问题,最好先更改目录,然后使用相对路径,而不是重复
C:\Users\titos\Resilio_Sync\4K_Video_Downloader\
,看看是否可以将字符数减少到可行的数量。十六进制转换的双引号示例:
转义双引号示例:
仅当上述方法无法充分减少字符数时,您才应该考虑删除
forfiles.exe
、cmd.exe
和ffmpeg.exe
文件的完整路径(在确认每个文件都在 的值中列出了其父位置之后%Path%
):十六进制转换的双引号示例:
转义双引号示例:
如您所见,使用
forfiles.exe
可能会给您带来许多障碍,尽管.mp4
它遇到的每个匹配文件都会在新cmd.exe
实例中运行,但对于除了少量匹配之外的任何情况,这都是非常低效的。我认为这种类型的任务更适合标准
For
/For /F
循环,(forfiles.exe
更适合那些@RelPath
需要其变量的罕见情况)。您已经有了一个使用其中一种的答案,因此我不会在这里发布我的版本。