Hello @mbunkus,
I’m trying to understand a duration discrepancy when recalculating Matroska track statistics with mkvpropedit on FFmpeg-written files.
What I observed:
A DTS stream extracted from a UHD Blu-ray playlist was copied into .mka/.mkv using FFmpeg with stream copy only.
The DTS payload is intact: hashes of the DTS stream extracted again from the FFmpeg-written Matroska file match the original source.
Playback is fine.
However, after running:
mkvpropedit --delete-track-statistics-tags --add-track-statistics-tags
the DURATION tag is recalculated shorter than expected.
Observed results:
- FFmpeg-written .mka: DURATION becomes 01:52:12.011000000
- FFmpeg-written .mkv: DURATION becomes 01:52:12.010000000
For comparison, the durations I expect from ffprobe / playback are:
- .mka: approximately 01:52:12.021000000
- .mkv: approximately 01:52:12.020000000
Also, when the same DTS stream is muxed with mkvmerge, the recalculated/derived duration matches the expected value much more closely.
This makes me wonder whether mkvpropedit/mkvinfo are recalculating duration differently for some FFmpeg-written Matroska files, or whether there is some Matroska-level timestamp/duration detail written by FFmpeg that affects later recalculation.
At the moment, this looks more like a recalculation/statistics issue than an audio payload issue, since the DTS stream hashes match and playback is correct.
Could you please confirm whether this is expected behavior? If not, should I open a Codeberg issue and provide sample files and exact command lines?
Thanks.
mkvpropedit & mkvmerge calculate slightly differently due to having access to different kinds of information with different precision. mkvpropedit only sees three things:
- frame timestamps
- the track’s default duration
- a
BlockGroup’s duration attribute (if present, if not the track’s default duration / number of frames/blocks in BlockGroup is substituted)
As Matroska only has a limited resolution for timestamps & the duration (files produced by mkvmerge only have 1ms precision by default), the timing information mkvpropedit deals with has the same limited resolution.
mkvmerge on the other hand calculates each and every frame’s duration from a lot of properties, and those methods depend on codec type (mkvpropedit only operates on the container level). Therefore it can calculate timestamps much more precisely internally before writing the limited-precision information to the file. The full-precision information is still used for track statistics (I think).
Both programs ultimately use the same simple algorithm for the duration:
- determine minimum start timestamp for each frame
- determine maximum end timestamp for each frame
- subtract 1 from 2 and you get the duration
In step 2 the end timestamp is the sum of a frame’s start timestamp and its associated duration.
The bitrate written to the track statistics uses the same information (sum of frame sizes * 8 divided by the duration as described above).
I have no insight into how ffmpeg works.
Note that this approach doesn’t take gaps in the track into account, nor am I certain how (if) it deals with things such as pre-roll or last frames that contain fewer samples than a normal encoded frame (Opus can do such things).