Media.Open reads an audio file’s tags and its duration with the same calls as a video: media.Tags gives the common fields (title, artist, album, copyright…) whichever tag system the file uses, and media.Metadata.NativeTags lists every tag as stored. The inputs are the soundtrack of the Sintel trailer (CC BY 3.0, © copyright Blender Foundation | durian.blender.org), converted with FFmpeg to MP3, FLAC and WAV; FFmpeg copies the trailer’s tags into each format’s own tag system.
dotnet new console -o AudioTags && cd AudioTags dotnet add package RecursiveAI.OneMedia --version 0.2.0-preview.1 curl -L -o sintel.mp4 https://download.blender.org/durian/trailer/sintel_trailer-480p.mp4 x="-v error -i sintel.mp4 -vn -metadata major_brand= -metadata minor_version= -metadata compatible_brands=" ffmpeg $x -c:a libmp3lame -q:a 4 sintel.mp3 ffmpeg $x sintel.flac ffmpeg $x sintel.wav
Put this in Program.cs and run dotnet run:
using RecursiveAI.OneMedia; using RecursiveAI.OneMedia.Tags; foreach (string path in new[] { "sintel.mp3", "sintel.flac", "sintel.wav" }) { using MediaFile media = Media.Open(path); MediaTrack audio = media.Audio!; string rate = audio.BitRate > 0 ? $", {audio.BitRate / 1000} kbit/s" : ""; Console.WriteLine($"{path}: {media.Format}, {media.Duration:mm\\:ss\\.fff}," + $" {audio.Codec} {audio.Audio?.SampleRate} Hz" + $" {audio.Audio?.Channels} ch{rate}"); // The common view: the same fields for ID3, APE, Vorbis comments, RIFF INFO... CommonTags tags = media.Tags; Console.WriteLine($" title {tags.Title}, artist {tags.Artist}"); Console.WriteLine($" copyright {tags.Copyright}"); // Every native tag: its system, its key and its value as stored. foreach (NativeTag tag in media.Metadata.NativeTags) Console.WriteLine($" {tag.System}:{tag.Key} = {tag.Text}"); }
sintel.mp3: mpegaudio, 00:51.925, mp3 48000 Hz 2 ch, 136 kbit/s title Sintel Trailer, artist Durian Open Movie Team copyright (c) copyright Blender Foundation | durian.blender.org id3v2:TCOP = (c) copyright Blender Foundation | durian.blender.org id3v2:TIT2 = Sintel Trailer id3v2:TPE1 = Durian Open Movie Team id3v2:TXXX:description = Trailer for the Sintel open movie project id3v2:TSSE = Lavf62.3.100 sintel.flac: flac, 00:51.925, flac 48000 Hz 2 ch title Sintel Trailer, artist Durian Open Movie Team copyright (c) copyright Blender Foundation | durian.blender.org vorbis:copyright = (c) copyright Blender Foundation | durian.blender.org vorbis:title = Sintel Trailer vorbis:artist = Durian Open Movie Team vorbis:description = Trailer for the Sintel open movie project vorbis:encoder = Lavf62.3.100 sintel.wav: wav, 00:51.925, pcm 48000 Hz 2 ch, 1536 kbit/s title Sintel Trailer, artist Durian Open Movie Team copyright (c) copyright Blender Foundation | durian.blender.org riff-info:IART = Durian Open Movie Team riff-info:ICOP = (c) copyright Blender Foundation | durian.blender.org riff-info:INAM = Sintel Trailer riff-info:ISFT = Lavf62.3.100
Each format keeps its tags its own way: ID3v2 frames in the MP3 (TIT2 is the title), Vorbis comments in the FLAC (title), RIFF LIST INFO chunks in the WAV (INAM). The common view maps all of them to Title, Artist, Copyright and the rest through a fixed mapping table; when several tags map to one field, the property is the first and media.Tags.Values(CommonField.Title) lists them all. One native tag reads as media.Native["id3v2", "TIT2"].
The duration is exact for all three: the FLAC and WAV state their length in samples, and FFmpeg’s MP3 has a Xing/LAME header with the frame count and the encoder delay and padding, which OneMedia takes off. The same code reads ID3v1, APE and Lyrics3 tags on MP3, Vorbis comments in Ogg Vorbis and Opus, AIFF and CAF text chunks, BWF bext and iXML in WAV, WMA attributes, and iTunes tags in M4A (Read MP4 metadata). Pictures such as cover art are native tags of kind Image; their bytes are read only when you call tag.ReadValue().
Check it with ffprobe
ffprobe -v error -show_entries format=duration:format_tags=title,artist -of compact sintel.flacformat|duration=51.925333|tag:title=Sintel Trailer|tag:artist=Durian Open Movie TeamLimits
- Reading only. OneMedia 0.2 doesn’t write or edit tags. Tag editing is not in this release.
- Estimated durations. An MP3 or ADTS AAC file without a frame count (no Xing, Info or VBRI header) gets a duration estimated from its bit rate, as other tools do.
- Not mapped. A tag the mapping table doesn’t list stays on the native list only, such as the MP3’s
TXXX:descriptionhere. - Decoding is OneAudio’s job:
media.Decode()fromRecursiveAI.OneMedia.Audioplays MP3, FLAC, Vorbis, Opus and AAC, but not PCM, ADPCM, WMA, AC-3 or ALAC tracks. For WAV samples, read the packets or use OneAudio directly. - Known differences from ExifTool, MediaInfo, TagLib# and ATL.NET are listed per format: MP3, AAC, AC-3 and AMR files, FLAC, WAV, AIFF and CAF.
For video files, the same calls work on MP4 (Read MP4 metadata) and MKV (Read MKV and WebM file info).