使用 avconv 将带字幕的 DVD 图像转换为 MKV

Posted

技术标签:

【中文标题】使用 avconv 将带字幕的 DVD 图像转换为 MKV【英文标题】:Converting DVD image with subtitles to MKV using avconv 【发布时间】:2013-10-12 14:33:57 【问题描述】:

这是我知道的将 DVD 映像转换为另一种视频格式(例如 MP4)的过程:

    VIDEO_TS 文件夹中的VTS_01_n.VOB 文件(对于n >= 0)连接成一个 VOB 文件。 使用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,显示字幕编码错误,但是当使用 -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 命令和输出插入 将 DVD 转换为 MKV:编码使用 Handbrake,不带编码 MakeMKV。 @Endoro:MakeMKV 为我工作。虽然我想要一个完整的开源解决方案(这需要安装二进制文件),但这非常适合我的迫切需要。如果您将其写为答案,我会赞成并(如果没有给出avconv 答案)接受它。谢谢。 @CarlosEugenioThompsonPinzón mkvmerge 是开源的,它在这项任务中表现出色——非常易于使用(默认保留所有曲目,不需要花哨的魔法选项),并且可以容忍各种可能杀死 ffmpeg 的格式错误,例如。我猜 MakeMKV 只是在幕后使用它。 【参考方案1】:

简答:跳到完整命令行部分,然后从this site下载ffmpeg

最初,我计划用avconv 回答如何做到这一点,因为(a)这个答案仍然缺失,(b)avconv 似乎是当今 ubuntu 系统的默认设置。但是,目前似乎无法做到这一点 - 至少对于我的测试用例而言。

ffmpeg 设置

由于您要求avconvffmpeg,而我刚刚得知avconvffmpeg 的一个分支(请参阅this answer 进行讨论),我下载了ffmpeg 的当前版本正如上述答案所解释的,来自this site。 Windows 版本也可用。对于当前典型的 64 位 Linux 构建,直接链接将是 this page。它包含每日构建。所以向下滚动直到你看到最新最好的,下载并解压,例如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 中的选项始终只影响在当前选项之后命名为 的输入或输出文件。这两个选项必须影响输入文件,所以它们必须排在第一位。

this bug ticket 中介绍了此解决方法,但可能并非在所有情况下都有帮助。

缺少部分或全部字幕

这是处理.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

完整的命令行

./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 并改用该工具来解决问题,正如我在上面解释的那样。

【讨论】:

根据我的经验,ffmpeg 完全阻塞了某些输入(生成无效文件和/或挂起),但我成功地将它们转换(重新复用)为 MKV 格式 mkvmerge 它生成完全正确文件。虽然我没有测试它是否也传输字幕,但我相信它也应该照顾它们。 很好的答案!我不知道+genpts,很高兴看到你提到analyzedurationprobesize。我看到的大多数答案只是说连接VOB 文件,然后使用fmpeg 生成视频。不幸的是,正如 Display Name 所说,ffmpeg 仍然会在某些输入文件上卡住。我刚试过,它在转换结束时冻结了。我认为生成的文件应有尽有,但它不应该那样窒息。【参考方案2】:

如果您需要节省质量的解决方案,您应该尝试MakeMKV。 如果您想压缩视频轨道或将 MPEG-2 转换为 H.264,您可以使用handbrake。

【讨论】:

MakeMKV 为我工作。谢谢你。 Handbrake 导致我的系统在完成第一次转换之前关闭。 @CarlosEugenioThompsonPinzón 你试过Nightly build 吗?

以上是关于使用 avconv 将带字幕的 DVD 图像转换为 MKV的主要内容,如果未能解决你的问题,请参考以下文章

使用 avconv 从 .mov 转换为 .mp4(或 h264)

谁有破解的VCD,DVD转换器

ubuntu之视频转换(Avconv的使用)

sh 使用avconv转换音频文件的脚本

sh 使用avconv转换音频文件的脚本

ffmpeg、avconv 和 sameq