[FFmpeg-trac] #5756(ffmpeg:new): Robustness issue with nul character in ASS subtitle streams

FFmpeg trac at avcodec.org
Thu Aug 4 15:01:50 EEST 2016


#5756: Robustness issue with nul character in ASS subtitle streams
----------------------------------+---------------------------------------
             Reporter:  lelegard  |                     Type:  enhancement
               Status:  new       |                 Priority:  normal
            Component:  ffmpeg    |                  Version:  git-master
             Keywords:            |               Blocked By:
             Blocking:            |  Reproduced by developer:  0
Analyzed by developer:  0         |
----------------------------------+---------------------------------------
 This report describes a robustness issue with the processing of ASS
 subtitles.

 ffmpeg version N-81256-gd3426fb (full text in commands below)

 == Summary ==

 Some MKV files (but not all) containing ASS subtitles contain a nul
 character at the end of the ASS header (this is text). I do not know if
 this character is valid or not.

 When the subtitle track is extracted using ffmpeg, the nul character can
 be seen in the middle of the ASS text file, at the end of the "[V4+
 Styles]" section, before the "[Events]" section. Then, when this file is
 used to burn the subtitles using the "ass" video filter, no subtitle is
 seen in the video. If we manually modify the ASS text file to remove the
 nul character and retry the "ass" video filter, then the subtitles are
 correctly inserted in the video.

 Even if the nul character is invalid (to be confirmed), failing because of
 it is a pity. Other tools handle that situation without problem:

 1. VLC correctly displays the subtitle track when playing the MKV file.
 2. When mkvextract is used to extract the subtitle track, the created ASS
 text file does not have the nul character.

 So, for the sake of robustness, whether the nul character in the input
 file is valid or not, I suggest the following two enhancements. They are
 redundant in the specific example of this report, but they are in fact two
 independent robustness improvements for distinct use cases.

 1. When extracting the ASS header in a text file, remove the nul
 character, just like mkvextract.
 2. In the "ass" video filter, ignore nul characters from the text file
 containing the subtitles.

 == Demonstration ==

 I have a small MKV file named im.mkv, 10 MB, 30 seconds of playback,
 demonstrating the problem. This file is extracted from a larger MKV file.
 Several other MKV from multiple origins have the same nul character in the
 ASS header.

 Extracting the subtitles using mkvextract into a text file named im-
 mkvextract.ass:

 {{{
 $ mkvextract tracks im.mkv 2:im-mkvextract.ass
 Extracting track 2 with the CodecID 'S_TEXT/ASS' to the file 'im-
 mkvextract.ass'. Container format: SSA/ASS text subtitles
 Progress: 100%
 $
 }}}

 Extracting the subtitles using ffmpeg into a text file named im-
 ffmpeg.ass:

 {{{
 $ ffmpeg -i im.mkv -vn -an -codec:s ass -f ass -y im-ffmpeg.ass
 ffmpeg version N-81256-gd3426fb Copyright (c) 2000-2016 the FFmpeg
 developers
   built with gcc 5.4.0 (GCC)
   configuration: --enable-gpl --enable-version3 --disable-w32threads
 --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-
 bzlib --enable-libebur128 --enable-fontconfig --enable-frei0r --enable-
 gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b
 --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm
 --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-
 libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg
 --enable-libopus --enable-librtmp --enable-libschroedinger --enable-
 libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-
 libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis
 --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264
 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg
 --enable-lzma --enable-decklink --enable-zlib
   libavutil      55. 28.100 / 55. 28.100
   libavcodec     57. 51.100 / 57. 51.100
   libavformat    57. 44.100 / 57. 44.100
   libavdevice    57.  0.102 / 57.  0.102
   libavfilter     6. 49.100 /  6. 49.100
   libswscale      4.  1.100 /  4.  1.100
   libswresample   2.  1.100 /  2.  1.100
   libpostproc    54.  0.100 / 54.  0.100
 Input #0, matroska,webm, from 'im.mkv':
   Metadata:
     ENCODER         : Lavf57.25.100
   Duration: 00:00:30.60, start: 0.000000, bitrate: 2618 kb/s
     Chapter #0:0: start 0.000000, end 30.000000
     Metadata:
       title           : 00:00:00.000
     Stream #0:0(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 384 kb/s
     Metadata:
       title           : Surround
       DURATION        : 00:00:30.016000000
     Stream #0:1: Video: h264 (High), yuv420p(tv, bt709), 1920x800 [SAR 1:1
 DAR 12:5], 23.98 fps, 23.98 tbr, 1k tbn, 180k tbc (default)
     Metadata:
       DURATION        : 00:00:30.182000000
     Stream #0:2(fre): Subtitle: ass
     Metadata:
       DURATION        : 00:00:30.601000000
 [ass @ 0000000002865500] Using AVStream.codec to pass codec parameters to
 muxers is deprecated, use AVStream.codecpar instead.
 Output #0, ass, to 'im-ffmpeg.ass':
   Metadata:
     encoder         : Lavf57.44.100
     Chapter #0:0: start 0.000000, end 30.000000
     Metadata:
       title           : 00:00:00.000
     Stream #0:0(fre): Subtitle: ass
     Metadata:
       DURATION        : 00:00:30.601000000
       encoder         : Lavc57.51.100 ass
 Stream mapping:
   Stream #0:2 -> #0:0 (ass (ssa) -> ass (native))
 Press [q] to stop, [?] for help
 size=       1kB time=00:00:28.68 bitrate=   0.4kbits/s speed=50.9x
 video:0kB audio:0kB subtitle:1kB other streams:0kB global headers:0kB
 muxing overhead: 167.719299%
 $
 }}}

 The file im-ffmpeg.ass contains a nul character as illustrated below. The
 file im-mkvextract.ass does not have this nul character.

 {{{
 [Script Info]
 ScriptType: v4.00+
 Collisions: Normal
 PlayResX: 1920
 PlayResY: 800
 Timer: 100.0
 WrapStyle: 0

 [V4+ Styles]
 Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour,
 OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX,
 ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL,
 MarginR, MarginV, Encoding
 Style:
 Default,Arial,52,&H00FFFFFF,&H00FFFFFF,&H000F0F0F,&H000F0F0F,0,0,0,0,100,100,0,0.00,1,2,3,2,20,20,20,0
 ^@ <==== nul character here
 [Events]
 Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect,
 Text
 .....
 }}}

 Now, we try to burn the two subtitle files im-ffmpeg.ass and im-
 mkvextract.ass in the video, separately.

 In the file im1.mpg, generated using im-ffmpeg.ass, there is no subtitle
 in the video. In the file im2.mpg, generated using im-mkvextract.ass, the
 subtitles are correctly inserted in the video.

 {{{
 $ ffmpeg -i im.mkv -codec:a ac3 -codec:v mpeg2video -vf ass=filename=im-
 ffmpeg.ass -f dvd -y im1.mpg
 ffmpeg version N-81256-gd3426fb Copyright (c) 2000-2016 the FFmpeg
 developers
   built with gcc 5.4.0 (GCC)
   configuration: --enable-gpl --enable-version3 --disable-w32threads
 --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-
 bzlib --enable-libebur128 --enable-fontconfig --enable-frei0r --enable-
 gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b
 --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm
 --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-
 libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg
 --enable-libopus --enable-librtmp --enable-libschroedinger --enable-
 libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-
 libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis
 --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264
 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg
 --enable-lzma --enable-decklink --enable-zlib
   libavutil      55. 28.100 / 55. 28.100
   libavcodec     57. 51.100 / 57. 51.100
   libavformat    57. 44.100 / 57. 44.100
   libavdevice    57.  0.102 / 57.  0.102
   libavfilter     6. 49.100 /  6. 49.100
   libswscale      4.  1.100 /  4.  1.100
   libswresample   2.  1.100 /  2.  1.100
   libpostproc    54.  0.100 / 54.  0.100
 Input #0, matroska,webm, from 'im.mkv':
   Metadata:
     ENCODER         : Lavf57.25.100
   Duration: 00:00:30.60, start: 0.000000, bitrate: 2618 kb/s
     Chapter #0:0: start 0.000000, end 30.000000
     Metadata:
       title           : 00:00:00.000
     Stream #0:0(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 384 kb/s
     Metadata:
       title           : Surround
       DURATION        : 00:00:30.016000000
     Stream #0:1: Video: h264 (High), yuv420p(tv, bt709), 1920x800 [SAR 1:1
 DAR 12:5], 23.98 fps, 23.98 tbr, 1k tbn, 180k tbc (default)
     Metadata:
       DURATION        : 00:00:30.182000000
     Stream #0:2(fre): Subtitle: ass
     Metadata:
       DURATION        : 00:00:30.601000000
 [Parsed_ass_0 @ 000000000073ff20] Shaper: FriBidi 0.19.6 (SIMPLE)
 [Parsed_ass_0 @ 000000000073ff20] Using font provider directwrite
 [Parsed_ass_0 @ 000000000073ff20] Added subtitle file: 'im-ffmpeg.ass' (2
 styles, 0 events)
 [dvd @ 00000000027f8500] Using AVStream.codec to pass codec parameters to
 muxers is deprecated, use AVStream.codecpar instead.
     Last message repeated 1 times
 [dvd @ 00000000027f8500] VBV buffer size not set, using default size of
 130KB
 If you want the mpeg file to be compliant to some specification
 Like DVD, VCD or others, make sure you set the correct buffer size
 Output #0, dvd, to 'im1.mpg':
   Metadata:
     encoder         : Lavf57.44.100
     Chapter #0:0: start 0.000000, end 30.000000
     Metadata:
       title           : 00:00:00.000
     Stream #0:0: Video: mpeg2video (Main), yuv420p, 1920x800 [SAR 1:1 DAR
 12:5], q=2-31, 200 kb/s, 23.98 fps, 90k tbn, 23.98 tbc (default)
     Metadata:
       DURATION        : 00:00:30.182000000
       encoder         : Lavc57.51.100 mpeg2video
     Side data:
       cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
     Stream #0:1(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
     Metadata:
       title           : Surround
       DURATION        : 00:00:30.016000000
       encoder         : Lavc57.51.100 ac3
 Stream mapping:
   Stream #0:1 -> #0:0 (h264 (native) -> mpeg2video (native))
   Stream #0:0 -> #0:1 (ac3 (native) -> ac3 (native))
 Press [q] to stop, [?] for help
 frame=  724 fps=126 q=24.8 Lsize=    6742kB time=00:00:30.11
 bitrate=1834.1kbits/s dup=22 drop=0 speed=5.23x
 video:4832kB audio:1642kB subtitle:0kB other streams:0kB global
 headers:0kB muxing overhead: 4.153100%
 $
 $
 $ ffmpeg -i im.mkv -codec:a ac3 -codec:v mpeg2video -vf ass=filename=im-
 mkvextract.ass -f dvd -y im2.mpg
 ffmpeg version N-81256-gd3426fb Copyright (c) 2000-2016 the FFmpeg
 developers
   built with gcc 5.4.0 (GCC)
   configuration: --enable-gpl --enable-version3 --disable-w32threads
 --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-
 bzlib --enable-libebur128 --enable-fontconfig --enable-frei0r --enable-
 gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b
 --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm
 --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-
 libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg
 --enable-libopus --enable-librtmp --enable-libschroedinger --enable-
 libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-
 libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis
 --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264
 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg
 --enable-lzma --enable-decklink --enable-zlib
   libavutil      55. 28.100 / 55. 28.100
   libavcodec     57. 51.100 / 57. 51.100
   libavformat    57. 44.100 / 57. 44.100
   libavdevice    57.  0.102 / 57.  0.102
   libavfilter     6. 49.100 /  6. 49.100
   libswscale      4.  1.100 /  4.  1.100
   libswresample   2.  1.100 /  2.  1.100
   libpostproc    54.  0.100 / 54.  0.100
 Input #0, matroska,webm, from 'im.mkv':
   Metadata:
     ENCODER         : Lavf57.25.100
   Duration: 00:00:30.60, start: 0.000000, bitrate: 2618 kb/s
     Chapter #0:0: start 0.000000, end 30.000000
     Metadata:
       title           : 00:00:00.000
     Stream #0:0(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 384 kb/s
     Metadata:
       title           : Surround
       DURATION        : 00:00:30.016000000
     Stream #0:1: Video: h264 (High), yuv420p(tv, bt709), 1920x800 [SAR 1:1
 DAR 12:5], 23.98 fps, 23.98 tbr, 1k tbn, 180k tbc (default)
     Metadata:
       DURATION        : 00:00:30.182000000
     Stream #0:2(fre): Subtitle: ass
     Metadata:
       DURATION        : 00:00:30.601000000
 [Parsed_ass_0 @ 00000000027a96c0] Shaper: FriBidi 0.19.6 (SIMPLE)
 [Parsed_ass_0 @ 00000000027a96c0] Using font provider directwrite
 [Parsed_ass_0 @ 00000000027a96c0] Added subtitle file: 'im-mkvextract.ass'
 (2 styles, 12 events)
 [dvd @ 00000000029700a0] Using AVStream.codec to pass codec parameters to
 muxers is deprecated, use AVStream.codecpar instead.
     Last message repeated 1 times
 [dvd @ 00000000029700a0] VBV buffer size not set, using default size of
 130KB
 If you want the mpeg file to be compliant to some specification
 Like DVD, VCD or others, make sure you set the correct buffer size
 Output #0, dvd, to 'im2.mpg':
   Metadata:
     encoder         : Lavf57.44.100
     Chapter #0:0: start 0.000000, end 30.000000
     Metadata:
       title           : 00:00:00.000
     Stream #0:0: Video: mpeg2video (Main), yuv420p, 1920x800 [SAR 1:1 DAR
 12:5], q=2-31, 200 kb/s, 23.98 fps, 90k tbn, 23.98 tbc (default)
     Metadata:
       DURATION        : 00:00:30.182000000
       encoder         : Lavc57.51.100 mpeg2video
     Side data:
       cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
     Stream #0:1(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
     Metadata:
       title           : Surround
       DURATION        : 00:00:30.016000000
       encoder         : Lavc57.51.100 ac3
 Stream mapping:
   Stream #0:1 -> #0:0 (h264 (native) -> mpeg2video (native))
   Stream #0:0 -> #0:1 (ac3 (native) -> ac3 (native))
 Press [q] to stop, [?] for help
 [Parsed_ass_0 @ 00000000027a96c0] fontselect: (Arial, 400, 0) -> ArialMT,
 0, ArialMTp=20 drop=0 speed=5.77x
 frame=  724 fps=110 q=24.8 Lsize=    6914kB time=00:00:30.11
 bitrate=1880.9kbits/s dup=22 drop=0 speed= 4.6x
 video:5003kB audio:1642kB subtitle:0kB other streams:0kB global
 headers:0kB muxing overhead: 4.057209%
 $
 }}}

--
Ticket URL: <https://trac.ffmpeg.org/ticket/5756>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list