6

My question, I think, is pretty simple...

Sometimes I like to download large MKV files from a webserver of mine, and play them back while they are downloading. However, if I do this on MKV files I've transcoded, often the file will show that it is much shorter than it actually is, and after it gets to the end it will just keep playing and display an incorrect time...e.g. it will display 2:50/2:50 but keep playing, however if I try to seek backwards with the arrow keys the player will either crash or skip back to the beginning of the file.

So, how can I move all the metadata to the beginning of the file while encoding so that the player will know how long the file is without having the whole thing? You can do this with the mp4 format by using -movflags faststart, but how to do it for mkv?

I'm sorry if this is already asked and answered elsewhere, I could not think of better keywords than I used and the ones I used produced no results.

2 Answers2

7

The Matroska foundation offers a tool, mkclean, that performs a task similar to what qt-faststart does for MOV/MP4s.

Syntax:

mkclean in.mkv out.mkv

This will regenerate the cues index. To keep the original cues,

mkclean --keep-cues in.mkv out.mkv

FFmpeg can also do this, with some guesswork, on the user's part.

ffmpeg -i in.mkv -c copy -reserve_index_space 50k out.mkv 

where the reserve_index_space value in bytes is the size needed for the index. 50kbytes is the suggested size for 1 hour of media.

Gyan
  • 38,955
0

Building on top of Gyan's answer, mkclean is that right tool to optimize MKVs for streaming. However, I noticed some quirks in how mkclean produced files, so I made a fork: https://github.com/XMB5/mkclean-pragmatic

Example usage: mkclean test.mkv test_streaming_optimized.mkv

Here are some excerpts from the readme:

Background (why we need mkclean in the first place)

In order to stream mkv files, the video player needs to read the cues element, a part of the file that maps video timestamps to byte offsets. These offsets allow the video player to seek to timestamps throughout the video, without guessing the byte location in the file.

Typically, the cues element is located at the end of a matroska file (see matroska structure diagram). This is because the application that creates the mkv writes all of the video data first, and only afterwards can it know the exact byte locations of the video content.

However, having the cues element at the end of the file is not ideal: the video player must read the seek head at the start of the file, then seek the the end of the file to read the cues information, then seek back to read the video content. With HTTP streaming, this amounts to 3 separate requests, which add a few seconds of delay compared to 1 request.

mkclean restructures a mkv file so that the cues element is at the beginning, allowing the video to start playing sooner.

Technical changes in fork (compared to original mkclean)

  • Set doctype version to matroska v4 by default
    • Set document read version to 2 (for compatibility, otherwise it won't work with vlc, mpv, ffmpeg, etc.)
  • Disable optimizations by default (equivalent to normal mkclean --no-optimize flag)
  • Ignore when cluster timestamps don't go in chronological order
    • Force-changing the timestamps causes mpv to warn "Invalid video timestamp: 10.085000 -> 10.060000"
XMB5
  • 101