Media.Open reads Matroska (.mkv, .mka, .mk3d) and WebM the same way as MP4: duration, tracks and codecs, a common tag view, and every Matroska tag with its target. The inputs are a WebM clip from MDN’s CC0 sample videos and test5.mkv from the Matroska project’s test files, 32 MB, cut from Elephants Dream (CC BY: © copyright 2006, Blender Foundation / Netherlands Media Art Institute / www.elephantsdream.org).
dotnet new console -o MkvInfo && cd MkvInfo dotnet add package RecursiveAI.OneMedia --version 0.1.0-preview.1 curl -L -o flower.webm https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm curl -L -o test5.mkv https://raw.githubusercontent.com/ietf-wg-cellar/matroska-test-files/master/test_files/test5.mkv
Put this in Program.cs and run dotnet run:
using RecursiveAI.OneMedia; using RecursiveAI.OneMedia.Matroska; using RecursiveAI.OneMedia.Tags; foreach (string path in new[] { "flower.webm", "test5.mkv" }) { using MediaFile media = Media.Open(path); // Both are "matroska"; the EBML header's DocType tells WebM apart. string docType = (media.Demuxer as MatroskaDemuxer)?.Header.DocType ?? "?"; Console.WriteLine($"{path}: {docType}, {media.Duration}, {media.Tracks.Count} tracks"); foreach (MediaTrack t in media.Tracks.Take(3)) Console.WriteLine($" track {t.Index}: {t.Kind} {t.Codec} [{t.CodecTag}]"); // Common fields, then each native tag: Segment Info (mkv-info) and Tags (mkv). Console.WriteLine($" title: {media.Tags.Title}"); foreach (NativeTag tag in media.Metadata.NativeTags) { string target = tag.TargetTypeValue is long level ? $" (target {level})" : ""; Console.WriteLine($" {tag.System}:{tag.Key}{target} = {tag.Text}"); } }
flower.webm: webm, 00:00:05.0590000, 2 tracks track 0: Video vp8 [V_VP8] track 1: Audio vorbis [A_VORBIS] title: mkv-info:MuxingApp = Lavf57.71.100 mkv-info:WritingApp = Lavf57.71.100 test5.mkv: matroska, 00:00:46.6650000, 11 tracks track 0: Video h264 [V_MPEG4/ISO/AVC] track 1: Audio aac [A_AAC] track 2: Subtitle subrip [S_TEXT/UTF8] title: Big Buck Bunny - test 8 mkv-info:MuxingApp = libebml v1.0.0 + libmatroska v1.0.0 mkv-info:WritingApp = mkvmerge v4.0.0 ('The Stars were mine') built on Jun 6 2010 16:18:42 mkv-info:DateUTC = 2010-08-21T18:06:43Z mkv:TITLE (target 50) = Big Buck Bunny - test 8 mkv:DATE_RELEASED (target 50) = 2010 mkv:COMMENT (target 50) = Matroska Validation File 8, secondary audio commentary track, misc subtitle tracks
The tags are what each file stores: test5.mkv is titled “Big Buck Bunny - test 8” although its pictures come from Elephants Dream, and flower.webm has no title at all.
mkv-info holds the Segment Info element: the title, the muxing library, the writing application and DateUTC, when the file was muxed. mkv holds the Tags element: each SimpleTag with its target level (50 is the whole movie or album, 30 a track or chapter, per RFC 9559) and the track it targets, if any (tag.TrackId). Nested tags are keyed PARENT/CHILD.
The common view (media.Tags) takes only tags that target the whole file, plus a single-track file’s track tags, and puts the lowest level of 30 or above first. Everything else stays on the native list. Attachments, such as cover art and fonts, are listed as native tags of kind Image or Binary, and their bytes are read only when you call tag.ReadValue().
Streams and remote files
Media.Open(stream) takes any readable, seekable Stream and throws ArgumentException for one that can’t seek. The Matroska reader also has a live, forward-only mode for streams that can’t seek, through the lower-level StreamForwardSource; it is not behind Media.Open in 0.1. For a file on a web server, Media.OpenAsync reads byte ranges (see Read video metadata from a URL).
Limits
- Reading only. No writing, remuxing or tag editing in 0.1.
- Subtitles are listed as tracks, with their packets, but not converted or parsed: subtitles are not in this release.
- Track durations are unknown for Matroska: the container states the Segment’s duration only, so
track.Durationis unknown andmedia.Durationis the Segment’s. - Chapters in Matroska
Chapterselements are not read yet. - Known differences from ffprobe, MKVToolNix and MediaInfo (attachments are not streams, RealAudio is not de-interleaved, RealVideo timestamps are as stored) are listed in Matroska and WebM.
To list every track with its language and flags, see List the tracks of a video.