2

I'm trying to create an HLS subtitle playlist from subtitles embedded within a video file. So the input looks something like this:

container: mkv
  stream 0: video h264
  stream 1: audio aac
  stream 2: subtitle ass

And the output folder should look something like this:

index.m3u8
subs_0.vtt
subs_1.vtt
subs_2.vtt
...

Currently, I get to the desired output by using the following two commands:

ffmpeg \
  -i in.mkv \
  -map 0:2 \
  -scodec webvtt \
  temp.vtt

ffmpeg -y \
  -i temp.vtt \
  -scodec webvtt \
  -f segment \
  -segment_list_type m3u8 \
  -segment_list_size 0 \
  -segment_time 6 \
  -segment_start_number 0 \
  -segment_format webvtt \
  -segment_list index.m3u8 \
  -map 0:0 \
  -scodec copy subs_%d.vtt

However, due to constraints in the surrounding system, I'd prefer to combine these two steps into a single command. But, whenever I try that, the output file is collapsed to a single subs_0.vtt file.

Currently failing attempt:

ffmpeg -y \
  -f matroska,webm \
  -i in.mkv \
  -scodec webvtt \
  -f segment \
  -segment_list_type m3u8 \
  -segment_list_size 0 \
  -segment_time 6 \
  -segment_start_number 0 \
  -segment_format webvtt \
  -segment_list index.m3u8 \
  -map 0:2 \
  out_%d.vtt

This command only creates a single vtt file, rather than the desired segmented files.

Is there a way to combine the two commands without losing the segmentation?

Edit:

I'm not sure if this is relevant, so I'm going to add it here. The failing command produces multiple "Non-monotonous DTS in output stream" messages. It sources from "segment", so I'd assume at least the correct format should be active, but maybe it prevents the segmented from splitting the file?

Example line:

[segment @ 0000011cec905440] Non-monotonous DTS in output stream 0:0; previous: 90402, current: 90400; changing to 90403. This may result in incorrect timestamps in the output file.

1 Answer 1

1

You need to disable the video and audio streams with -an and -vn options respectively, then use the generic segment output format instead of hls.

The segment muxer can produce HLS playlist format if the output file format has .m3u8 extension.

Copied from my answer on S:O (https://stackoverflow.com/a/76920564/1957951):

Here's an example that creates segmented VTT subtitles with 0000.vtt filename format and a playlist named index.m3u8. Please note that FFmpeg automatically determines the internal format of the playlist by analyzing the file extension of the -segment_list, but this can be set with the segment_format option.

Command breakdown:

ffmpeg -y -hide_banner -i input.mp4 \
-vn \                       # drop all video streams
-an \                       # drop all audio streams
-map s:0 \                  # select the first embedded subtitle stream
-f segment \                # use generic segment format
-segment_time 3.0 \         # set segment duration
-segment_list index.m3u8 \  # set playlist filename (internal format determined by extension)
%04d.vtt

Output files:

By printing the contents of a subtitle segment, you can see that these contain only fragments of the original subtitle:

$ cat 0000.vtt
WEBVTT

00:00.000 --> 00:02.880
you may have seen videos in which someone is using  

00:02.880 --> 00:06.660
an old computer when it suddenly 
makes popping and crackling noises

The command produces a playlist in HLS format:

$ head -n9 index.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:12
#EXTINF:6.660000,
0000.vtt
#EXTINF:6.120000,
0001.vtt
2
  • I honestly forgot that I ever asked that question. The current solution saves the subtitles as a separate file and provides that to the frontend. The frontend then is responsible for overlaying the subtitles. It's a pretty hacky solution, but it got me around and allows for ass subtitles. I'll try it out and see if I can integrate it into the current solution. Thanks for your response!
    – Euklios
    Aug 24 at 17:24
  • No probs! I've recently run into the same issue and I tought I'll check if someone else had the same problem. :D Aug 25 at 7:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.