---
title: "Read MP4 metadata tags in C#"
url: https://recursiveai.org/onemedia/cookbook/read-mp4-metadata/
description: "Read the title, artist, description, copyright and every other tag of an MP4, M4A or MOV file in C#: iTunes, QuickTime, 3GPP and XMP tags, with a common view over all of them."
version: "0.1.0-preview.1"
---

# Read MP4 metadata tags in C#

`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).

```shell
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`:

```csharp
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](https://recursiveai.org/onemedia/docs/tag-mapping/): `©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

```shell
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](https://recursiveai.org/onemedia/cookbook/video-recording-date-location/)).

## 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](https://recursiveai.org/onemedia/docs/tag-mapping/) 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](https://recursiveai.org/onemedia/docs/tags/) 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](https://recursiveai.org/onemedia/cookbook/read-mkv-webm-info/).
