Recursive AI

Read MP4 metadata tags in C#

All onemedia recipes

media.Tags gives the common fields of an MP4, M4A or MOV file (title, artist, album, comment, description, copyright, date, encoder) whichever tag system the file uses, and media.Metadata.NativeTags lists every tag exactly as stored. The input is the Sintel trailer, 4.4 MB, from the Blender Foundation (CC BY 3.0).

Terminal
dotnet new console -o Mp4Tags && cd Mp4Tags
dotnet add package RecursiveAI.OneMedia --version 0.1.0-preview.1
curl -L -o sintel.mp4 https://download.blender.org/durian/trailer/sintel_trailer-480p.mp4

Put this in Program.cs and run dotnet run:

C#
using RecursiveAI.OneMedia;
using RecursiveAI.OneMedia.Tags;
 
using MediaFile media = Media.Open("sintel.mp4");
 
// The common view: the same fields for iTunes, QuickTime, 3GPP, XMP and Matroska tags.
CommonTags tags = media.Tags;
Console.WriteLine($"Title:       {tags.Title}");
Console.WriteLine($"Artist:      {tags.Artist}");
Console.WriteLine($"Description: {tags.Description}");
Console.WriteLine($"Copyright:   {tags.Copyright}");
Console.WriteLine($"Encoder:     {tags.Encoder}");
 
// Every native tag: its system, its key and its value as stored.
Console.WriteLine();
foreach (NativeTag tag in media.Metadata.NativeTags)
    Console.WriteLine($"{tag.System,-5} {tag.Key,-5} {tag.Text}");
 
// One native tag by system and key.
Console.WriteLine();
Console.WriteLine(media.Native["ilst", "©cpy"]?.Text);
Text
Title:       Sintel Trailer
Artist:      Durian Open Movie Team
Description: Trailer for the Sintel open movie project
Copyright:
Encoder:     Lavf52.62.0
 
ilst  ©nam  Sintel Trailer
ilst  ©ART  Durian Open Movie Team
ilst  ©too  Lavf52.62.0
ilst  ©cpy  (c) copyright Blender Foundation | durian.blender.org
ilst  desc  Trailer for the Sintel open movie project
 
(c) copyright Blender Foundation | durian.blender.org

Copyright is empty although the file has a copyright: this file stores it as ©cpy in the iTunes list, and the 0.1 mapping takes copyright from cprt there (©cpy only from QuickTime user data). The native lookup at the end reads it whatever the mapping says.

The common view is computed from the native tags each time you ask, through a fixed mapping table: ©nam in an iTunes list, com.apple.quicktime.title in QuickTime keys, titl in a 3GPP file and TITLE in Matroska all become Title. When several native tags map to one field, the property is the first and tags.Values(CommonField.Title) lists them all.

The native systems are ilst (iTunes items, what ffmpeg and most tools write to MP4), udta (QuickTime user data), mdta (QuickTime keys, what phones write), 3gpp, xmp, and mkv and mkv-info for Matroska. Text values are decoded when the file is opened; pictures and long binary values are read only when you ask, with tag.ReadValue().

Check it with ffprobe

Terminal
ffprobe -v error -show_entries format_tags -of default=nw=1 sintel.mp4
Text
TAG:major_brand=isom
TAG:minor_version=512
TAG:compatible_brands=isomiso2avc1mp41
TAG:creation_time=1970-01-01T00:00:00.000000Z
TAG:title=Sintel Trailer
TAG:artist=Durian Open Movie Team
TAG:encoder=Lavf52.62.0
TAG:copyright=(c) copyright Blender Foundation | durian.blender.org
TAG:description=Trailer for the Sintel open movie project

ffprobe lists the file type brands and the movie header’s creation time with the tags. In OneMedia the creation time is a candidate of media.CaptureTime (here the 1970 date the muxer wrote; see When and where a video was recorded).

Limits

  • Reading only. OneMedia 0.1 doesn’t write or edit tags. Tag editing is not in this release.
  • Chapters. Nero chpl chapter lists are read (media.Metadata.Chapters); QuickTime text chapter tracks and Matroska Chapters are not read yet.
  • Mapping gaps. A tag the mapping table doesn’t list, such as ©cpy in an iTunes list, stays on the native list only.
  • Values that disagree. Where a file has the same field in several systems, OneMedia picks by a fixed order and keeps the rest. ExifTool and MediaInfo sometimes pick a different one; Tags and capture facts lists every known difference.
  • Bad text. Invalid UTF-8 or UTF-16 is replaced with U+FFFD and reported in media.Metadata.Defects, not thrown.

The same calls work on MKV and WebM: Read MKV and WebM file info.