使用avconv将带字幕的DVD映像转换成MKV格式

22

以下是我知道的将DVD映像转换为其他视频格式(如MP4)的步骤:

  1. 将位于“VIDEO_TS”文件夹中的VTS_01_n.VOB文件(对于所有n >= 0)连接成一个单独的VOB文件。
  2. 使用avconvffmpeg将该VOB文件转换为另一种格式。

到目前为止还不错,但现在我想将带有字幕的DVD映像也转换出来。据我所知,MKV格式支持字幕,因此它似乎是一个很明显的选择。或者,我可以使用任何其他具有硬字幕(字幕作为视频图像的一部分)的格式。

然而,在DVD映像中的字幕编码是dvdsub,我会收到以下错误:

Only SUBTITLE_ASS type supported.
Subtitle encoding failed

然而,运行 avconv -codecs 命令时我得到了以下输出:

...
 DES    dvdsub          DVD subtitles
...

-c:s copy选项虽然可以防止命令失败,但似乎无法产生播放器能理解的字幕。

那么,我该如何使用avconvdvdsub创建ass字幕呢?

我的VOB文件有八个字幕通道和两个音频通道。Ubuntu视频应用程序没有显示任何字幕,只有第一个音频通道似乎在工作,可能是DVD镜像损坏了。

另一个文件,用于双层DVD,显示了“Subtitle encoding error”,但是当使用-c:s copy开关时,它会进一步显示:

Application provided invalid, non monotonically increasing dts to muxer in stream 2: 49 >= 49
av_interleaved_write_frame(): Invalid argument

提前感谢任何有关解决这些问题的想法。

(我正在使用Ubuntu,在那里ffmpegavconv的别名。我知道可以安装真正的ffmpeg,但到目前为止我还没有这样做。)


更新:命令和控制台输出:

命令

cat VTS_01_1.VOB VTS_01_2.VOB VTS_01_3.VOB VTS_01_4.VOB VTS_01_5.VOB > ~/temp/mymovie.VOB
cd ~/temp
avconv -i mymovie.VOB

输出

avconv version 0.8.6-6:0.8.6-1ubuntu2, Copyright (c) 2000-2013 the Libav developers
  built on Mar 30 2013 22:20:06 with gcc 4.7.2
[mpeg @ 0x1a64d40] max_analyze_duration reached
Input #0, mpeg, from 'mymovie.VOB':
  Duration: 00:00:01.95, start: 0.280633, bitrate: -2147483 kb/s
    Stream #0.0[0x1e0]: Video: mpeg2video (Main), yuv420p, 720x480 [PAR 8:9 DAR 4:3], 7500 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
    Stream #0.1[0x20]: Subtitle: dvdsub
    Stream #0.2[0x21]: Subtitle: dvdsub
    Stream #0.3[0x22]: Subtitle: dvdsub
    Stream #0.4[0x23]: Subtitle: dvdsub
    Stream #0.5[0x24]: Subtitle: dvdsub
    Stream #0.6[0x25]: Subtitle: dvdsub
    Stream #0.7[0x26]: Subtitle: dvdsub
    Stream #0.8[0x27]: Subtitle: dvdsub
    Stream #0.9[0x80]: Audio: ac3, 48000 Hz, 5.1, s16, 448 kb/s
    Stream #0.10[0x81]: Audio: ac3, 48000 Hz, 5.1, s16, 448 kb/s
At least one output file must be specified

命令行

avconv -i mymovie.VOB mymovie.mkv

输出

avconv version 0.8.6-6:0.8.6-1ubuntu2, Copyright (c) 2000-2013 the Libav developers
  built on Mar 30 2013 22:20:06 with gcc 4.7.2
[mpeg @ 0x1cdad40] max_analyze_duration reached
Input #0, mpeg, from 'mymovie.VOB':
  Duration: 00:00:01.95, start: 0.280633, bitrate: -2147483 kb/s
    Stream #0.0[0x1e0]: Video: mpeg2video (Main), yuv420p, 720x480 [PAR 8:9 DAR 4:3], 7500 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
    Stream #0.1[0x20]: Subtitle: dvdsub
    Stream #0.2[0x21]: Subtitle: dvdsub
    Stream #0.3[0x22]: Subtitle: dvdsub
    Stream #0.4[0x23]: Subtitle: dvdsub
    Stream #0.5[0x24]: Subtitle: dvdsub
    Stream #0.6[0x25]: Subtitle: dvdsub
    Stream #0.7[0x26]: Subtitle: dvdsub
    Stream #0.8[0x27]: Subtitle: dvdsub
    Stream #0.9[0x80]: Audio: ac3, 48000 Hz, 5.1, s16, 448 kb/s
    Stream #0.10[0x81]: Audio: ac3, 48000 Hz, 5.1, s16, 448 kb/s
File 'mymovie.mkv' already exists. Overwrite ? [y/N] y
[buffer @ 0x1ce23c0] w:720 h:480 pixfmt:yuv420p
Output #0, matroska, to 'mymovie.mkv':
  Metadata:
    encoder         : Lavf53.21.1
    Stream #0.0: Video: mpeg4, yuv420p, 720x480 [PAR 8:9 DAR 4:3], q=2-31, 200 kb/s, 1k tbn, 29.97 tbc
    Stream #0.1: Audio: libvorbis, 48000 Hz, 5.1, s16
    Stream #0.2: Subtitle: ass, 200 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (mpeg2video -> mpeg4)
  Stream #0:9 -> #0:1 (ac3 -> libvorbis)
  Stream #0:1 -> #0:2 (dvdsub -> ass)
Press ctrl-c to stop encoding
[ass @ 0x1ce0140] Only SUBTITLE_ASS type supported.
Subtitle encoding failed

命令

avconv -i mymovie.VOB -c:s copy mymovie.mkv
输出省略。 命令
avconv -i mymovie.mkv

输出

avconv version 0.8.6-6:0.8.6-1ubuntu2, Copyright (c) 2000-2013 the Libav developers
  built on Mar 30 2013 22:20:06 with gcc 4.7.2
[matroska,webm @ 0xbc1d40] Estimating duration from bitrate, this may be inaccurate
Input #0, matroska,webm, from 'mymovie.mkv':
  Metadata:
    ENCODER         : Lavf53.21.1
  Duration: 01:05:09.47, start: 0.000000, bitrate: N/A
    Stream #0.0: Video: mpeg4 (Simple Profile), yuv420p, 720x480 [PAR 8:9 DAR 4:3], 29.97 fps, 29.97 tbr, 1k tbn, 30k tbc (default)
    Stream #0.1: Audio: vorbis, 48000 Hz, 5.1, s16 (default)
    Stream #0.2: Subtitle: dvdsub (default)
At least one output file must be specified

现在,关于双层:命令

cat VTS_01_1.VOB VTS_01_2.VOB VTS_01_3.VOB VTS_01_4.VOB VTS_01_5.VOB VTS_01_6.VOB VTS_01_7.VOB VTS_01_8.VOB > ~/temp/mylongmovie.VOB
cd ~/temp
avconv -i mylongmovie.VOB mylongmovie.mkv

输出

avconv version 0.8.6-6:0.8.6-1ubuntu2, Copyright (c) 2000-2013 the Libav developers
  built on Mar 30 2013 22:20:06 with gcc 4.7.2
[mpeg @ 0x13c2d40] max_analyze_duration reached
Input #0, mpeg, from 'Cosmos-0203.VOB':
  Duration: 00:00:30.24, start: 0.280633, bitrate: 2103365 kb/s
    Stream #0.0[0x1e0]: Video: mpeg2video (Main), yuv420p, 720x480 [PAR 8:9 DAR 4:3], 8000 kb/s, 27.46 fps, 59.94 tbr, 90k tbn, 59.94 tbc
    Stream #0.1[0x20]: Subtitle: dvdsub
    Stream #0.2[0x21]: Subtitle: dvdsub
    Stream #0.3[0x22]: Subtitle: dvdsub
    Stream #0.4[0x23]: Subtitle: dvdsub
    Stream #0.5[0x24]: Subtitle: dvdsub
    Stream #0.6[0x25]: Subtitle: dvdsub
    Stream #0.7[0x26]: Subtitle: dvdsub
    Stream #0.8[0x27]: Subtitle: dvdsub
    Stream #0.9[0x81]: Audio: ac3, 48000 Hz, 5.1, s16, 448 kb/s
    Stream #0.10[0x80]: Audio: ac3, 48000 Hz, 5.1, s16, 448 kb/s
File 'mylongmovie.mkv' already exists. Overwrite ? [y/N] y
[buffer @ 0x13ca3c0] w:720 h:480 pixfmt:yuv420p
Output #0, matroska, to 'mylongmovie.mkv':
  Metadata:
    encoder         : Lavf53.21.1
    Stream #0.0: Video: mpeg4, yuv420p, 720x480 [PAR 8:9 DAR 4:3], q=2-31, 200 kb/s, 1k tbn, 59.94 tbc
    Stream #0.1: Audio: libvorbis, 48000 Hz, 5.1, s16
    Stream #0.2: Subtitle: ass, 200 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (mpeg2video -> mpeg4)
  Stream #0:9 -> #0:1 (ac3 -> libvorbis)
  Stream #0:1 -> #0:2 (dvdsub -> ass)
Press ctrl-c to stop encoding
[ass @ 0x13d19c0] Only SUBTITLE_ASS type supported.
Subtitle encoding failed

命令

avconv -i mylongmovie.VOB -c:s copy mylongmovie.mkv 

输出

avconv version 0.8.6-6:0.8.6-1ubuntu2, Copyright (c) 2000-2013 the Libav developers
  built on Mar 30 2013 22:20:06 with gcc 4.7.2
[mpeg @ 0xce1d40] max_analyze_duration reached
Input #0, mpeg, from 'mylongmovie.VOB':
  Duration: 00:00:30.24, start: 0.280633, bitrate: 2103365 kb/s
    Stream #0.0[0x1e0]: Video: mpeg2video (Main), yuv420p, 720x480 [PAR 8:9 DAR 4:3], 8000 kb/s, 27.46 fps, 59.94 tbr, 90k tbn, 59.94 tbc
    Stream #0.1[0x20]: Subtitle: dvdsub
    Stream #0.2[0x21]: Subtitle: dvdsub
    Stream #0.3[0x22]: Subtitle: dvdsub
    Stream #0.4[0x23]: Subtitle: dvdsub
    Stream #0.5[0x24]: Subtitle: dvdsub
    Stream #0.6[0x25]: Subtitle: dvdsub
    Stream #0.7[0x26]: Subtitle: dvdsub
    Stream #0.8[0x27]: Subtitle: dvdsub
    Stream #0.9[0x81]: Audio: ac3, 48000 Hz, 5.1, s16, 448 kb/s
    Stream #0.10[0x80]: Audio: ac3, 48000 Hz, 5.1, s16, 448 kb/s
File 'mylongmovie.mkv' already exists. Overwrite ? [y/N] y
[buffer @ 0xce93c0] w:720 h:480 pixfmt:yuv420p
Output #0, matroska, to 'mylongmovie.mkv':
  Metadata:
    encoder         : Lavf53.21.1
    Stream #0.0: Video: mpeg4, yuv420p, 720x480 [PAR 8:9 DAR 4:3], q=2-31, 200 kb/s, 1k tbn, 59.94 tbc
    Stream #0.1: Audio: libvorbis, 48000 Hz, 5.1, s16
    Stream #0.2: Subtitle: dvdsub
Stream mapping:
  Stream #0:0 -> #0:0 (mpeg2video -> mpeg4)
  Stream #0:9 -> #0:1 (ac3 -> libvorbis)
  Stream #0:1 -> #0:2 (copy)
Press ctrl-c to stop encoding
[matroska @ 0xce4b40] Application provided invalid, non monotonically increasing dts to muxer in stream 2: 49 >= 49
av_interleaved_write_frame(): Invalid argument

@LordNeckbeard 命令和输出已插入。 - Carlos Eugenio Thompson Pinzón
1
将DVD转换为MKV:使用Handbrake进行编码,不使用MakeMKV进行编码。 - Endoro
@Endoro:MakeMKV 对我很有用。虽然我更喜欢完全开源的解决方案(这需要安装二进制文件),但它完美地满足了我的即时需求。如果你把它写成一个答案,我会点赞并接受它(如果没有给出 avconv 的答案)。谢谢。 - Carlos Eugenio Thompson Pinzón
@CarlosEugenioThompsonPinzón mkvmerge是开源的,在这项任务中表现优异 - 非常易于使用(默认情况下保留所有轨道,不需要花哨的魔法选项),并且对各种格式错误具有容忍性,这些错误可能会导致ffmpeg崩溃。我猜MakeMKV只是在其内部使用它。 - Display Name
2个回答

44
简短回答:跳到 完整命令行 部分,从此网站下载ffmpeg
原本,我计划回答如何使用avconv来实现这个问题,因为 (a) 这个答案仍然缺失,(b) avconv 看起来是今天ubuntu系统上的默认选项。但是,它似乎当前太有bug,以至于无法完成这个任务,至少对于我的测试用例来说。 ffmpeg安装设置 由于您要求使用avconv 或者 ffmpeg,而我刚刚了解到avconvffmpeg的一个分支(请参阅这个答案进行讨论),所以我从这个网站下载了最新版本的ffmpeg,如上述答案所解释的那样。Windows版本也可用。对于典型的当前64位Linux版本,直接链接到这个页面。它包含日常构建。因此,向下滚动,直到看到最新的版本,下载并解压缩,例如tar xzvf ffmpeg.static.64bit.2014-02-14.tar.gz。静态构建的优点在于它具有更少的依赖关系,如果没有的话。解包tar文件将在当前目录中创建两个新可执行文件ffmpegffprobe基本命令行 现在,我们可以使用这个最新的ffmpegmymovie.vob*中的所有流复制到不同的格式。例如:
./ffmpeg -i mymovie.vob -c:v copy -c:a copy -c:s copy -map 0 mymovie.mkv

这个命令行:
  • 从输入文件-i filename读取
  • 复制其中的视频流-c:v copy
  • 复制其中的音频流-c:a copy
  • 复制其中的字幕-c:s copy
  • 而不是只使用每个流的第一个,它使用并复制所有流-map 0
  • 到输出文件outputfile
让我们扩展上述命令行以解决工具中可能出现的一些错误、损坏的输入文件或有关 .vob 文件的特定问题。 解决错误 Can't write packet with unknown timestamp 的方法 在输入文件之前添加选项 -fflags +genpts
./ffmpeg -fflags +genpts -i mymovie.vob -c:v copy -c:a copy -c:s copy -map 0 mymovie.mkv

ffmpeg中的选项始终仅影响在当前选项之后命名的输入或输出文件。这两个选项必须影响输入文件,因此必须首先出现。

这种解决方法在这个错误票中有所涵盖,但可能并不适用于所有情况。

缺少一些或所有字幕

处理.vob文件时,这是非常典型的行为,ffmpeg FAQ中有介绍。像.avi.mp4.mkv等视频容器文件类型都具有标头(文件开头的数据),列出文件的所有内容。这使得播放器和转换工具很容易知道预期的数据类型。但是,.vob文件没有这样明确的标头。因此,当ffmpegavconv启动时,它们会查看前几千个字节。在vob文件中,字幕可能出现得非常晚。在我的测试中,第一个字幕出现在几秒钟后,因此工具在启动时无法看到它。下面是这些情况下的典型输出示例:

Output #0, matroska, to 'test.mkv':
  Metadata:
    encoder         : Lavf55.32.101
    Stream #0:0: Video: mpeg2video (mpg2 / 0x3267706D), yuv420p, 720x576 [SAR 64:45 DAR 16:9], q=2-31, max. 9800 kb/s, 25 fps, 1k tbn, 90k tbc
    Stream #0:1: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, 5.1(side), 448 kb/s
    Stream #0:2: Audio: dts ([1] [0][0] / 0x2001), 48000 Hz, 5.1(side), 768 kb/s
    Stream #0:3: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, 5.1(side), 448 kb/s
    Stream #0:4: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, stereo, 224 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
  Stream #0:2 -> #0:2 (copy)
  Stream #0:3 -> #0:3 (copy)
  Stream #0:4 -> #0:4 (copy)
Press [q] to stop, [?] for help
[mpeg @ 0x31f2540] New subtitle stream 0:5 at pos:16945166 and DTS:22.2473s
[mpeg @ 0x31f2540] New subtitle stream 0:6 at pos:16951310 and DTS:22.2473s
[mpeg @ 0x31f2540] New subtitle stream 0:7 at pos:16957454 and DTS:22.2873s
[mpeg @ 0x31f2540] New subtitle stream 0:8 at pos:16963598 and DTS:22.2873s
[mpeg @ 0x31f2540] New subtitle stream 0:9 at pos:18405390 and DTS:25.4873s
[mpeg @ 0x31f2540] New subtitle stream 0:10 at pos:18417678 and DTS:25.4873s
[mpeg @ 0x31f2540] New subtitle stream 0:11 at pos:264593422 and DTS:288.207sts/s    
[mpeg @ 0x31f2540] New subtitle stream 0:12 at pos:264597518 and DTS:288.207s
frame=24694 fps=7322 q=-1.0 Lsize=  859345kB time=00:16:27.74 bitrate=7127.1kbits/s    
video:632823kB audio:224996kB subtitle:0 data:0 global headers:0kB muxing overhead 0.177935%

如您所见,在实际编码过程中发现了新的字幕流。如果尝试添加 -map 5 选项以包括该流,则ffmpeg在启动时会抱怨该流号不存在。
解决方法是告诉ffmpeg在文件开头分析更多字节以查找所有流。
在输入文件之前尝试添加 -analyzeduration 1000000k -probesize 1000000k 选项。
如果仍然找不到流,请尝试增加这些数字。在我的测试用例中,这些数字已经足够大了。输出结果将会改变为:
Input #0, mpeg, from 'mymovie.vob':
  Duration: 00:59:39.90, start: 0.287267, bitrate: 5915 kb/s
    Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, bt470bg), 720x576 [SAR 64:45 DAR 16:9], max. 9800 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x80]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
    Stream #0:2[0x89]: Audio: dts (DTS), 48000 Hz, 5.1(side), fltp, 768 kb/s
    Stream #0:3[0x82]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
    Stream #0:4[0x83]: Audio: ac3, 48000 Hz, stereo, fltp, 224 kb/s
    Stream #0:5[0x20]: Subtitle: dvd_subtitle
    Stream #0:6[0x21]: Subtitle: dvd_subtitle
    Stream #0:7[0x22]: Subtitle: dvd_subtitle
    Stream #0:8[0x23]: Subtitle: dvd_subtitle
    Stream #0:9[0x24]: Subtitle: dvd_subtitle
    Stream #0:10[0x25]: Subtitle: dvd_subtitle
    Stream #0:11[0x26]: Subtitle: dvd_subtitle
    Stream #0:12[0x27]: Subtitle: dvd_subtitle
File 'test.mkv' already exists. Overwrite ? [y/N] y
Output #0, matroska, to 'test.mkv':
  Metadata:
    encoder         : Lavf55.32.101
    Stream #0:0: Video: mpeg2video (mpg2 / 0x3267706D), yuv420p, 720x576 [SAR 64:45 DAR 16:9], q=2-31, max. 9800 kb/s, 25 fps, 1k tbn, 90k tbc
    Stream #0:1: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, 5.1(side), 448 kb/s
    Stream #0:2: Audio: dts ([1] [0][0] / 0x2001), 48000 Hz, 5.1(side), 768 kb/s
    Stream #0:3: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, 5.1(side), 448 kb/s
    Stream #0:4: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, stereo, 224 kb/s
    Stream #0:5: Subtitle: dvd_subtitle
    Stream #0:6: Subtitle: dvd_subtitle
    Stream #0:7: Subtitle: dvd_subtitle
    Stream #0:8: Subtitle: dvd_subtitle
    Stream #0:9: Subtitle: dvd_subtitle
    Stream #0:10: Subtitle: dvd_subtitle
    Stream #0:11: Subtitle: dvd_subtitle
    Stream #0:12: Subtitle: dvd_subtitle

完整命令行

(相关于IT技术)
./ffmpeg -fflags +genpts -analyzeduration 1000000k -probesize 1000000k -i mymovie.vob -c:v copy -c:a copy -c:s copy -map 0 mymovie.mkv

任何一份副本都可以被替换成编解码器,来实际转换并很可能压缩数据。但如果只有三份副本,那么命令可以简化为:
./ffmpeg -fflags +genpts -analyzeduration 1000000k -probesize 1000000k -i mymovie.vob  -c copy -map 0 mymovie.mkv

所有这些选项也被avconv支持。然而,这个工具似乎仍然存在一些字幕问题。如果您看到以下错误:
[matroska @ 0x383aee60] Application provided invalid, non monotonically increasing dts to muxer in stream 7: 58280 >= 58280
av_interleaved_write_frame(): Invalid argument

如果遇到这种情况,你可以通过下载最新的ffmpeg并使用该工具来规避问题,正如我上面所解释的那样。


1
根据我的经验,FFmpeg 有时会完全无法处理某些输入(生成无效文件和/或挂起),但是我使用 mkvmerge 成功将它们转换(重新混合)为 MKV 格式,并生成了完全正确的文件。虽然我没有测试它是否也可以传输字幕,但我相信它也应该能够处理它们。 - Display Name
太棒了!我不知道+genpts,看到你提到analyzedurationprobesize很好。大多数答案只是说要连接VOB文件,然后使用fmpeg生成视频。不幸的是,正如Display Name所说,ffmpeg仍然无法处理某些输入文件。我刚试过,它在转换结束时卡住了。我认为生成的文件已经包含了所有内容,但不应该这样卡住。 - user1593842

5

如果你需要一种高质量的保存解决方案,你可以尝试使用MakeMKV

如果你想要压缩视频轨道或者将MPEG-2转换为H.264,你可以使用HandBrake


MakeMKV对我很有用,谢谢。Handbrake在第一次转换完成之前会导致我的系统关闭。 - Carlos Eugenio Thompson Pinzón
@CarlosEugenioThompsonPinzón 你尝试过 夜间构建版本 了吗? - Endoro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接