我有175个 mp4 视频文件和字幕文件,扩展名为 .ass 。不幸的是,我的智能电视无法读取那些字幕。我计划将字幕刻录(硬编码)到视频中。
我使用这个命令:
bash
有效。所以我计划使用ffmpeg
脚本来自动化这个过程。
脚本中的所有内容都有效,但for f in *.mp4
do
new="${f%%.mp4} (CHT).mp4"
subtitle="${f%%.mp4}.chi.ass"
< /dev/null ffmpeg -i "$f" -vf subtitles="$subtitle" "$new"
done
命令行无法检索字幕变量。
在谷歌搜索后,我发现我的文件名有特殊的字符和空格,导致我的脚本失败。如果视频文件名和字幕文件很简单,那么脚本应该没问题。
这是我的剧本:
ffmpeg
{{1}}行在读取字幕文件变量时遇到问题。有人可以帮忙吗?
答案 0 :(得分:1)
尝试更改:
new="${f%%.mp4} (CHT).mp4"
subtitle="${f%%.mp4}.chi.ass"
< /dev/null ffmpeg -i "$f" -vf subtitles="$subtitle" "$new"
要:
new="${f%%.mp4}.CHT.mp4"
subtitle="${f%%.mp4}.chi.ass"
# make a temp hardlink to evade `ffmpeg`'s
# onerous quoting requirements.
x=`mktemp -u -p . --suffix=.ass`
ln "$subtitle" $x
< /dev/null ffmpeg -i "$f" -vf subtitles=$x "${new}"
rm $x
工作原理。由于ffmpeg
难以使用带转义的字幕文件,只需将字幕文件链接到名称$x
而不用转义,然后让ffmpeg
将其翻过来,然后删除链接。
更简洁的方法是使用名为ffescape
的工具翻译$subtitle
变量;遗憾的是,该工具目前尚未打包在ffmpeg
的源代码树之外。
答案 1 :(得分:1)
我设法使用此脚本解决问题。如果你可以帮助缩短它,它将是完美的。
for f in *.mp4
do
new="${f%%.mp4} (CHT).mp4"
subtitle="${f%%.mp4}.chi.ass"
newsubtitle="${subtitle// /\\ }"
echo $newsubtitle
secsubtitle="${newsubtitle//[/\\[}"
echo $secsubtitle
thirdtitle="${secsubtitle//]/\\]}"
echo $thirdtitle
fourthtitle="${thirdtitle//(/\\(}"
echo $fourthtitle
fifthtitle="${fourthtitle//)/\\)}"
echo $fifthtitle
ffmpeg -i "$f" -vf subtitles="$fifthtitle" "$new"
done
谢谢
答案 2 :(得分:0)
可能是,以下内容有助于阐明它:
一个小的测试程序,它反映了命令行参数的传递方式:
$ cat >print-arg.c <<EOF
#include <stdio.h>
int main(int argc, char **argv)
{
for (int i = 0; i < argc; ++i) printf("argv[%d]: '%s'\n", i, argv[i]);
return 0;
}
EOF
$ gcc -o print-arg print-arg.c
$
这可以用来反映论点:
$ ./print-arg Hello\ World "Hello World"
argv[0]: './print-arg'
argv[1]: 'Hello World'
argv[2]: 'Hello World'
$
为了确保终端不会欺骗我们,我们甚至可以这样做:
$ ./print-arg Hello\ World "Hello World" | hexdump -C
00000000 61 72 67 76 5b 30 5d 3a 20 27 2e 2f 70 72 69 6e |argv[0]: './prin|
00000010 74 2d 61 72 67 27 0a 61 72 67 76 5b 31 5d 3a 20 |t-arg'.argv[1]: |
00000020 27 48 65 6c 6c 6f 20 57 6f 72 6c 64 27 0a 61 72 |'Hello World'.ar|
00000030 67 76 5b 32 5d 3a 20 27 48 65 6c 6c 6f 20 57 6f |gv[2]: 'Hello Wo|
00000040 72 6c 64 27 0a |rld'.|
00000045
$
现在,这个print-arg
工具可用于调试bash脚本test-subtitle.sh
:
#/bin/bash
for f in *.mp4
do
new="${f%%.mp4} (CHT).mp4"
subtitle="${f%%.mp4}.chi.ass"
./print-arg < /dev/null ffmpeg -i "$f" -vf subtitles="$subtitle" "$new"
done
进行测试:
$ touch file1.mp4 file\ 2.mp4 "file 3.mp4"
$ ./test-subtitle.sh
argv[0]: './print-arg'
argv[1]: 'ffmpeg'
argv[2]: '-i'
argv[3]: 'file 2.mp4'
argv[4]: '-vf'
argv[5]: 'subtitles=file 2.chi.ass'
argv[6]: 'file 2 (CHT).mp4'
argv[0]: './print-arg'
argv[1]: 'ffmpeg'
argv[2]: '-i'
argv[3]: 'file 3.mp4'
argv[4]: '-vf'
argv[5]: 'subtitles=file 3.chi.ass'
argv[6]: 'file 3 (CHT).mp4'
argv[0]: './print-arg'
argv[1]: 'ffmpeg'
argv[2]: '-i'
argv[3]: 'file1.mp4'
argv[4]: '-vf'
argv[5]: 'subtitles=file1.chi.ass'
argv[6]: 'file1 (CHT).mp4'
$
此测试应该清楚地说明ffmpeg将如何获得命令行参数。
<强>更新强>
请在命令行上尝试:
$ < /dev/null ffmpeg -i '[アニメ] FAIRY TAIL 第001話「妖精の尻尾(ようせいのしっぽ)」(1280x720 x264 AAC).mp4' -vf 'subtitles=[アニメ] FAIRY TAIL 第001話「妖精の尻尾(ようせいのしっぽ)」(1280x720 x264 AAC).chi.ass' '[アニメ] FAIRY TAIL 第001話「妖精の尻尾(ようせいのしっぽ)」(1280x720 x264 AAC) (CHT).mp4'
在阅读完答案后,我相信字幕确实被提供反斜杠转义。我很好奇引用是否会起作用。
所以,请在命令行上进行最后一次测试:
$ < /dev/null ffmpeg -i '[アニメ] FAIRY TAIL 第001話「妖精の尻尾(ようせいのしっぽ)」(1280x720 x264 AAC).mp4' -vf 'subtitles="[アニメ] FAIRY TAIL 第001話「妖精の尻尾(ようせいのしっぽ)」(1280x720 x264 AAC).chi.ass"' '[アニメ] FAIRY TAIL 第001話「妖精の尻尾(ようせいのしっぽ)」(1280x720 x264 AAC) (CHT).mp4'
根据你的评论,反斜杠转义似乎是传递字幕文件的唯一方法。实际上,我在Stackoverflow中发现了一个更短(可能更强大)的解决方案:Escape FileNames Using The Same Way Bash Do It。
应用于您的脚本:
#/bin/bash
for f in *.mp4
do
new="${f%%.mp4} (CHT).mp4"
subtitle=$(printf '%q' "${f%%.mp4}.chi.ass")
< /dev/null ffmpeg -i "$f" -vf subtitles="$subtitle" "$new"
done
我分别更改了基本脚本test-subtitle.sh
:
#/bin/bash
for f in *.mp4
do
new="${f%%.mp4} (CHT).mp4"
subtitle=$(printf '%q' "${f%%.mp4}.chi.ass")
./print-arg < /dev/null ffmpeg -i "$f" -vf subtitles="$subtitle" "$new"
done
得到了:
$ touch file1.mp4 file\ 2.mp4 "file 3.mp4" 'file[4].mp4'
$ ./test-subtitle.sh
argv[0]: './print-arg'
argv[1]: 'ffmpeg'
argv[2]: '-i'
argv[3]: 'file 2.mp4'
argv[4]: '-vf'
argv[5]: 'subtitles=file\ 2.chi.ass'
argv[6]: 'file 2 (CHT).mp4'
argv[0]: './print-arg'
argv[1]: 'ffmpeg'
argv[2]: '-i'
argv[3]: 'file 3.mp4'
argv[4]: '-vf'
argv[5]: 'subtitles=file\ 3.chi.ass'
argv[6]: 'file 3 (CHT).mp4'
argv[0]: './print-arg'
argv[1]: 'ffmpeg'
argv[2]: '-i'
argv[3]: 'file1.mp4'
argv[4]: '-vf'
argv[5]: 'subtitles=file1.chi.ass'
argv[6]: 'file1 (CHT).mp4'
argv[0]: './print-arg'
argv[1]: 'ffmpeg'
argv[2]: '-i'
argv[3]: 'file[4].mp4'
argv[4]: '-vf'
argv[5]: 'subtitles=file\[4\].chi.ass'
argv[6]: 'file[4] (CHT).mp4'
$