首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更正ffmpeg字幕脚本中的变量名

更正ffmpeg字幕脚本中的变量名
EN

Stack Overflow用户
提问于 2017-06-20 05:57:16
回答 3查看 818关注 0票数 2

我有175个mp4视频文件和扩展名为.ass的字幕文件。不幸的是,我的智能电视看不懂那些字幕。我计划在视频中刻录(硬编码)字幕。

我使用以下命令:

代码语言:javascript
复制
ffmpeg -i orgvideo.mp4 -vf subtitles="subtitle.ass" newvideo.mp4     <br>

它起作用了。因此,我计划使用一个bash脚本来自动化这个过程。

脚本中的所有内容都正常工作,但是ffmpeg命令行无法检索字幕变量。

搜索完后,我发现我的文件名具有特殊的字符和空间,这会导致我的脚本失败。如果视频文件名和字幕文件很简单,那么脚本就没有问题。

这是我的剧本:

代码语言:javascript
复制
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行在读取字幕文件变量时遇到问题。有人能帮忙吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-06-20 12:55:16

试着改变:

代码语言:javascript
复制
new="${f%%.mp4} (CHT).mp4"
subtitle="${f%%.mp4}.chi.ass"
< /dev/null ffmpeg -i "$f" -vf subtitles="$subtitle" "$new"

至:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2017-06-20 14:53:06

我用这个脚本设法解决了这个问题。如果你能帮助缩短它,它将是完美的。

代码语言:javascript
复制
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

谢谢

票数 1
EN

Stack Overflow用户

发布于 2017-06-20 12:30:37

也许,以下几点可能有助于阐明这一问题:

反映命令行参数传递方式的小型测试程序:

代码语言:javascript
复制
$ 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

$

这可以用来反映论点:

代码语言:javascript
复制
$ ./print-arg Hello\ World "Hello World"
argv[0]: './print-arg'
argv[1]: 'Hello World'
argv[2]: 'Hello World'

$

为了确保终端机不会欺骗我们,我们甚至可以这样做:

代码语言:javascript
复制
$ ./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

代码语言:javascript
复制
#/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

执行测试:

代码语言:javascript
复制
$ 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将如何得到命令行参数。

更新

请在命令行上试试这个:

代码语言:javascript
复制
$ < /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'

在阅读了你的答案后,我相信副标题真的必须提供反斜杠逃脱。我很想知道引用是否有效。

所以,请在命令行上做最后一次测试:

代码语言:javascript
复制
$ < /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

应用于您的脚本:

代码语言:javascript
复制
#/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

代码语言:javascript
复制
#/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

并得到:

代码语言:javascript
复制
$ 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'

$
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44644890

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档