[FFmpeg-user] Hardcoding subtitles

Stefano Sabatini stefasab at gmail.com
Fri Jul 5 12:52:17 CEST 2013


On date Wednesday 2013-07-03 16:44:30 +0200, Oliver Fromme wrote:
> I'm trying to "hardcode" forced subtitles into a video, so they are
> always displayed, independent of the player's subtitle support.
> In the end I have been successful, but it was kind of an adventure.
> I'm trying to describe the problems that I encountered, maybe this
> can help to make ffmpeg better.
> 
> My ffmpeg version is a recent git snapshot, just a few days old.
> 
> These are my input files:  Video and audio are in an MPEG2 PS file
> that comes from a DVD (via "mplayer -dumpstream").  The subtitles
> are in VOBSUB format (I think ffmpeg calls this "dvdsub"), i.e.
> .idx + .sub files.  These have been retrieved from the same DVD
> with "mencoder -vobsubout".
> 
> The first problem was that ffmpeg didn't want to read the VOBSUB
> files directly, no matter what I tried.  It seemed to be unable
> to detect the format automatically, and I was unable to find out
> how to specify it on the command line.  I probably tried more
> than 20 variantions, without success.  However, it's not a big
> deal:  I just wrapped the VOBSUB stream into an MKV container
> (using mkvmerge), and ffmpeg happily accepted it.  So, my input
> files are now the MPEG2 PS file (same as before) and an MKV file
> containing just the VOBSUB subtitle stream.
> 
> According to the excellent manual page, the overlay filter can
> be used for hardcoding subtitles, so I tried that.  The filter
> specification was simple:
> 
> -filter_complex "[0:v][1:s]overlay"
> 
> where file 0 is the MPEG2 PS and file 1 is the MKV file with the
> VOBSUB stream.  If it matters (I don't think it does), here's
> the complete command line:
> 
> ffmpeg1 -loglevel warning -stats -i dvdstream-3.mpg -i subtitles-3-1.mkv \
>         -filter_complex "[0:v][1:s]overlay" \
>         -c:v libx264 -preset veryslow -tune film -crf 18 -level 4.1 \
>         -codec:a copy -map 0:a -sn dvdstream-3-vid.mkv
> 
> Basically, that command worked and created a video with hardcoded
> subtitles.  However, there was one small problem:  The duration
> of the last subtitle was "infinite", i.e. the very last subtitle
> stayed on the screen until end of the video.  It was visible for
> several minutes including the whole end credits of the movie.
> Not nice.  So I went back to the manual page and re-read the
> section about the overlay filter.
> 
> I noticed the "repeatlast" option of this filter, but the last
> sentence said something like "A value of 0 ... is enabled by
> default", so I thought that 0 was the default.  But I didn't
> look closely enough ...  Upon further inspection, it's just the
> other way around.  Of course that's my mistake, but maybe the
> manual page could be made a little clearer?  Something like
> "The default value is 1" would probably be clear enough.

Changed.

> Anyway, I tried to disable that flag:
> 
> -filter_complex "[0:v][1:s]overlay=repeatlast=0"
> 
> It did make a difference, but not what I expected:  Now the last
> subtitle didn't appear at all!  I think this is a bug, although
> I wouldn't rule out the possibility that I did something wrong
> again.  I tried with a different DVD, but same result:  When
> repeatlast=0 is specified, the last VOBSUB subtitle is omitted
> completely.

If this is a bug, we need a sample and a command to reproduce the
error. Please consider to file a bug report on trac.

> 
> So, now I pondered over a workaround for that problem.
> I skimmed over some examples in the manual page that gave me an
> Idea:  I could try to use the gte() function to forcefully end
> the last subtitle at the desired time stamp.
> 
> First I used mplayer to look for the exact position where the
> last subtitle was supposed to end.  In this case that was at
> t = 3375 (that's 56 minutes and 15 seconds).  I reverted the
> "repeatlast" flag to the default so the last subtitle was
> visible, and used gte() to cancel it at the proper time:
> 

> -filter_complex "[0:v][1:s]overlay=x='if(gt(t,3375),NAN,x)'"

The problem is that x is NAN when evaluating this expression, so the
result is always NAN. Or in other words, recursive definitions are not
supported (and probably meaningless).

> 
> The idee was:  If the time is beyond 3375, set the x value of
> the subtitle frames to NAN (effectively disabling them),
> otherwise keep them at their original x value.  At least I
> thought that's what the x variable meant.


> 
> Obviously I was wrong, because the resulting video did not
> contain *any* subtitles at all.  No subtitles anywhere.
> Either I misunderstood the description of the x variable in
> the manual page (and in this case the manual page should be
> clarified), or there's another bug.  In my next attempt I
> replaced the x variable with 0, which should be the default
> for x anyway:
> 
> -filter_complex "[0:v][1:s]overlay=x='if(gt(t,3375),NAN,0)'"
> 
> Finally, that produced the expected result, and I'm happy now.

Even better, you could use the enable option (check timeline section
in the manual) to avoid x/NAN hacks:
enable=gt(t,3375)

[...]


More information about the ffmpeg-user mailing list