Skip to content

feat: add Matroska/WebM (mkv/webm) file support with library duration - #16886

Open
hdp1972be-svg wants to merge 8 commits into
mixxxdj:mainfrom
hdp1972be-svg:mkv-webm-support
Open

feat: add Matroska/WebM (mkv/webm) file support with library duration#16886
hdp1972be-svg wants to merge 8 commits into
mixxxdj:mainfrom
hdp1972be-svg:mkv-webm-support

Conversation

@hdp1972be-svg

@hdp1972be-svg hdp1972be-svg commented Aug 14, 2026

Copy link
Copy Markdown

feat: add Matroska/WebM (mkv/webm) file support with library duration

Text is partly AI written as I am no native english language speaker, however manually checked against errors.
Code patches are checked on a ubuntu 20.04 container, build with CI, then tested on a 20.04 system.
All features tested manually, code reviewed by hand.

  • MKV/WEBM extensions are loaded in the file browser
  • playing of those formats works
  • no seek errors
  • spectroscope waveform buildup works
  • seeking in files works
  • scratching works.
  • duration timing is correct in the file browser

tested with ffmpeg 4.2.7, custom compiled QT6 (so it works on 20.04)

Motivation

The FFmpeg sound source provider already advertises .mkv and .webm, and
such files can be opened and played. However, the library showed an empty
Duration column
for these files.

Root cause:

  • SoundSourceFFmpeg had no metadata override, so no stream info was imported
    from the container.
  • MetadataSourceTagLib returned ImportResult::Unavailable for mkv/webm
    (TagLib cannot read these containers), which made updateTrackFromSource()
    skip the import entirely.

Changes

  1. feat: advertise MKV/WebM as supported file types — register the mkv /
    webm suffixes in SoundSourceProviderFFmpeg::getSupportedFileTypes().
  2. fix: drop stray brace from MKV/WebM file type block — cleanup of the
    previous commit.
  3. fix: bypass content mime lookup for MKV/WebM — resolve the sound source
    type by file suffix in SoundSource::getTypeFromFile(), because Qt's
    QMimeDatabase may not recognize Matroska/WebM from content.
  4. Add mkv/webm bypass in MetadataSourceTagLib — return
    ImportResult::Unavailable for mkv/webm so the FFmpeg path is used,
    avoiding a TagLib "unsupported type" warning.
  5. Add QFileInfo include for TagLib mkv/webm bypass — needed include for the
    suffix check.
  6. fix: fall back to format context duration for MKV/WebM — in tryOpen(),
    use the format context duration when the stream duration is
    AV_NOPTS_VALUE instead of failing to open.
  7. fix: rescale format context duration to stream time base — rescale the
    container duration to the stream time base before use.
  8. feat: import Matroska/WebM stream info from FFmpeg container — new
    importTrackMetadataAndCoverImage() override in SoundSourceFFmpeg that
    opens the container, picks the audio stream with av_find_best_stream, and
    imports duration, channels, sample rate and bitrate from AVCodecParameters.
    All other file types are delegated to MetadataSourceTagLib.

Add the "mkv" and "webm" suffixes to the file types reported by the
FFmpeg sound source provider, so Matroska/WebM files become selectable.
Remove the leftover "}" from the previous commit so the mkv/webm
branch ends after "continue;" as intended.
Qt's QMimeDatabase may not recognize Matroska/WebM containers from
content, so resolve the type by file suffix for mkv/webm instead.

add mkv and webm in soundsource
Matroska/WebM streams often report an unknown stream duration.
Use the format context duration as a fallback so such files can
be opened and seeked correctly.
The duration fallback for streams with unknown duration assigned
AVFormatContext::duration, which is measured in AV_TIME_BASE units
(1/1e6 s), directly to AVStream::duration, which is measured in
stream time_base units. For webm/mkv streams with a 1/1000 s time
base this inflated the frame index range by ~1000x, breaking
seeking and the waveform/spectrogram (e.g. "Stream ends at sample
frame 18534900 instead of 18535728336"). Rescale the duration
with av_rescale_q before assigning it.
TagLib does not support Matroska/WebM containers, so MetadataSourceTagLib
returns ImportResult::Unavailable for these file types. As a result the
library showed an empty duration column for such files, because the
FFmpeg-based SoundSource never fed the imported stream info back into the
track metadata.

Add an importTrackMetadataAndCoverImage override that delegates all
TagLib-supported file types to the default implementation, and for
mkv/webm opens the FFmpeg container and reports the stream info (channel
count, sample rate, bitrate and duration) matching the native values used
by initResampling(). The duration is derived from the stream frame index
range, mirroring the format-context duration fallback of tryOpen() when
the stream duration is unknown.
@JoergAtGithub

Copy link
Copy Markdown
Member

Which taglib version did you tried? taglib official supports Matroska.

@hdp1972be-svg

hdp1972be-svg commented Aug 15, 2026

Copy link
Copy Markdown
Author

My system has a custom build o taglib v2.0.2 in /usr/local which gave always an Unknown filetype respons. That's the reason I branched it to a more native ffmpeg duration implementation. In the focal-CI for building I use 1.11.1 (alas, same problem)

However, it seems - indeed - that mkv support was added in taglib but only version 2.2 (Feb 2026) upwards. (confirmed in taglib CHANGELOG)

In mixxx requirements taglib (the find_package(TagLib 1.11 REQUIRED) ) a minimum of taglib 1.11 is required.
I asume due to this version requirements many who compile from source would have no taglib >= 2.2 as their (dev) system needs to be up to date and in the (dev) docs there is atm no clue about it.

If needed or wanted I could implement a check on the version of taglib in the code too and if >=2.2 is found use taglib support for mkv/webm ; i.e. add/use the path in trackmetadata_file.cpp. Otherwise fallback on the ffmpeg support. That patch (not upstream pushed atm) is actually 90% ready, I only need to check it if it compiles and works correctly in my CI and make another workflow file to test it against the v2.2 version of taglib.

@JoergAtGithub

Copy link
Copy Markdown
Member

We've another PR #15888 by @acolombier where taglib 2.2 is needed. As soon as Ubuntu 26.04.01 is out, we will raise the minimum requirement according to our policy.
Could you please test and confirm, that using taglib 2.2 solves your issue.

@JoergAtGithub

Copy link
Copy Markdown
Member

As a first-time contributor we need you to sign the Mixxx Contributor Agreement and comment here when you have done so. It gives us permission to distribute your contribution under the GPL v2 or later license and the Apple Mac App Store. It is also helpful for us to have contact information for contributors in case we may need it in the future.

@hdp1972be-svg

hdp1972be-svg commented Aug 15, 2026

Copy link
Copy Markdown
Author

Upgrading to taglib 2.2 alone doesn't solve the issue completely, because

  1. the file extensions mkv & webm aren't checked in the main code (fixed by commit [57b8d5f] e.a.)
  2. the mimetypes for matroska/webm - which are in ffmpeg - don't get populated in the soundsource code. (fixed by commit [7e637eb])

However it's good to know the dependency to taglib will be bumped to v2.2 when 26.04.01 will come out.

I will add a bit of code around the patch so depending on the taglib version it branches to the specific code.
That way you could use the patch now and when dependencies are shifted the patch will work out of the box only branching of the pre 2.2 code in dead code.

So in the end it will do

  • taglib < 2.2 -> code like it is in this PR
  • taglib >= 2.2 -> code will work using the taglib API (todo, working on it)

Working on the implementation of cover art too, so the first non-black frame of the 1st video stream (if there is one) is taken as cover art pic) (in progress)

I've build this PR (without the taglib 2.2 implementation code) against taglib and it doesn't break anything.

Different taglib dependency versions (2.2 and 1.x) can be checked (if needed) here


Contributor agreement -> signed

@JoergAtGithub

Copy link
Copy Markdown
Member

Please note, that Mixxx is a cross-platform software and for legal issues we can use FFmpeg only very limited. But taglib we can use on any platform.

@hdp1972be-svg

hdp1972be-svg commented Aug 15, 2026

Copy link
Copy Markdown
Author

Okay, ffmpeg info noted. Can uou elabotate more which exact FFmpeg use is restricted so I can make sure the implementation stays within those constraints?

As far as I'm aware, this PR does not introduce any new FFmpeg functionality or a new SoundSource; it only extends the existing FFmpeg SoundSource path to handle Matroska/WebM with FFmpeg being used as a fallback where TagLib <2.2 doesn't provide the required information. The TagLib 2.2 implementation, including the conditional compilation, will be done as well, but that's beyond the scope of this PR.

I also saw the failed test: SoundSourceProxyTest.taglibStringToEnumFileType. Could you provide the exact failure output for that test? (which is unviewabe from the CI pre-commit workflow)/ I suspect it may be related to the difference between the file types supported by FFmpeg and those supported by TagLib, but I'd like to confirm the exact failing type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants