---
title: "List the audio, video and subtitle tracks of a video in C#"
url: https://recursiveai.org/onemedia/cookbook/list-video-tracks/
description: "List every video, audio and subtitle track of an MKV or MP4 file in C#, with codec, language, name and default flags, and pick a track by language."
version: "0.1.0-preview.1"
---

# List the audio, video and subtitle tracks of a video in C#

`media.Tracks` lists every track of an MP4, MOV, MKV or WebM file with its kind, codec, language, name and flags, in file order. The input is `test5.mkv` from the Matroska project’s test files: one video track, two audio tracks and eight subtitle tracks, cut from Elephants Dream (CC BY: © copyright 2006, Blender Foundation / Netherlands Media Art Institute / www.elephantsdream.org).

```shell
dotnet new console -o ListTracks && cd ListTracks
dotnet add package RecursiveAI.OneMedia --version 0.1.0-preview.1
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`:

```csharp
using RecursiveAI.OneMedia;

using MediaFile media = Media.Open("test5.mkv");

Console.WriteLine("#   kind      codec   lang  name        flags");
foreach (MediaTrack t in media.Tracks)
{
    string detail = t.Video is { } v ? $" {v.Width}x{v.Height}"
                  : t.Audio is { } a ? $" {a.SampleRate} Hz {a.Channels} ch" : "";
    Console.WriteLine($"{t.Index,-3} {t.Kind,-9} {t.Codec,-7} {t.Language,-5} " +
                      $"{t.Name ?? "",-11} {t.Disposition}{detail}");
}

// Pick tracks the way a player would.
MediaTrack? english = media.Tracks.FirstOrDefault(t =>
    t.Kind == TrackKind.Subtitle && t.Language == "eng");
MediaTrack? secondAudio = media.Tracks.Where(t => t.Kind == TrackKind.Audio)
                                      .Skip(1).FirstOrDefault();
Console.WriteLine($"English subtitles: track {english?.Index}");
Console.WriteLine($"Second audio: track {secondAudio?.Index}, \"{secondAudio?.Name}\"");
```

```text
#   kind      codec   lang  name        flags
0   Video     h264    und               Default 1024x576
1   Audio     aac     und               Default 48000 Hz 2 ch
2   Subtitle  subrip  eng               Default
3   Subtitle  subrip  hun               None
4   Subtitle  subrip  ger               None
5   Subtitle  subrip  fre               None
6   Subtitle  subrip  spa               None
7   Subtitle  subrip  ita               None
8   Audio     aac     eng   Commentary  None 44100 Hz 1 ch
9   Subtitle  subrip  jpn               None
10  Subtitle  subrip  und               None
English subtitles: track 2
Second audio: track 8, "Commentary"
```

`Index` is the track’s position in `media.Tracks` and the number every other call uses. `Id` is the number the container gives it (the Matroska `TrackNumber` or the MP4 `track_ID`), which need not be in order: here track 10 has `Id` 7. `Language` is the code as stored: Matroska and MP4 use ISO 639-2 (`eng`, `ger`, `fre`), and `und` means undetermined. `Disposition` holds the default, forced, commentary, hearing-impaired, original and similar flags the file sets.

## Check it with ffprobe

ffprobe lists the same tracks in the same order:

```shell
ffprobe -v error -show_entries stream=index,codec_type,codec_name:stream_tags=language,title -of compact test5.mkv
```

```text
stream|index=0|codec_name=h264|codec_type=video
stream|index=1|codec_name=aac|codec_type=audio
stream|index=2|codec_name=subrip|codec_type=subtitle|tag:language=eng
stream|index=3|codec_name=subrip|codec_type=subtitle|tag:language=hun
stream|index=4|codec_name=subrip|codec_type=subtitle|tag:language=ger
stream|index=5|codec_name=subrip|codec_type=subtitle|tag:language=fre
stream|index=6|codec_name=subrip|codec_type=subtitle|tag:language=spa
stream|index=7|codec_name=subrip|codec_type=subtitle|tag:language=ita
stream|index=8|codec_name=aac|codec_type=audio|tag:language=eng|tag:title=Commentary
stream|index=9|codec_name=subrip|codec_type=subtitle|tag:language=jpn
stream|index=10|codec_name=subrip|codec_type=subtitle
```

## Limits

- **Listing, not extracting subtitles.** Subtitle tracks are listed and their packets can be read with `media.Packets(track)`, but OneMedia 0.1 doesn’t parse or convert subtitles, and it can’t write a track out to a new file: remuxing is not in this release.
- **Attachments are not tracks.** Fonts and cover art in a Matroska file are native tags, not entries in `media.Tracks` (ffprobe lists them as streams).
- **Protected tracks.** An encrypted track is listed with `IsProtected` set; its packets are delivered as stored.
- **Language codes** are as stored, not translated: a Matroska track’s `LanguageBCP47` when it has one (`de`), else its ISO 639-2 code (`ger` or `deu`).

To decode one of the audio tracks, see [Extract the audio from a video](https://recursiveai.org/onemedia/cookbook/extract-audio-from-video/).
