mono/taglib-sharp

TagLib Sharp allows you to read and write audo and video metadata

Works with many popular video,audio and animated image formats all with one package

TagLib#

(aka Taglib-sharp) is a .NET platform-independent library (tested on Windows/Linux) for reading and writing metadata in media files, including video, audio, and photo formats. This is a convenient one-stop-shop to present or tag all your media collection, regardless of which format/container these might use. You can read/write the standard or more common tags/properties of a media, or you can also create and retrieve your own custom tags.

It supports the following formats (by file-extensions):

  • Video: mkv, ogv, avi, wmv, asf, mp4 (m4p, m4v), mpeg (mpg, mpe, mpv, mpg, m2v)
  • Audio: aa, aax, aac, aiff, ape, dsf, flac, m4a, m4b, m4p, mp3, mpc, mpp, ogg, oga, wav, wma, wv, webm
  • Images: bmp, gif, jpeg, pbm, pgm, ppm, pnm, pcx, png, tiff, dng, svg

It is API stable, with only API additions (not changes or removals) occuring in the 2.0 series.

Examples

Read/write metadata from a video

Read/write metadata from a Audio file

Read/write metadata from an Image

Read/write custom tags from a specific format

Website

TagLib# is available on GitHub: https://github.com/mono/taglib-sharp

  • Bugs: Create an issue
  • Chat: Join us at Gitter
  • Git: Get the source at git://github.com/mono/taglib-sharp.git

Installation From NuGet

TagLib# is available on NuGet: <#404>

Install from package manager:

PM> Install-Package TagLibSharp -Version 2.3.0

Building and Running

Command Line

To Build From Git:

To Test:

Build in IDE (Visual Studio, Visual Studio for Mac, Rider, etc):

You can open it in Visual Studio by using TaglibSharp.sln

Running regression by using Nunit 3 Test Adapter:

  1. Ensure NuGet packages have been restored
    1. See: https://docs.microsoft.com/en-us/nuget/consume-packages/package-restore
  2. In Visual Studio, go to menu: Tools > Extensions and Updates > Online (In Visual Studio 2019, use Extensions > Manage Extensions)
  3. Search: Nunit 3 Test Adapter
  4. Download and install it
  5. Open from menu: Test > Windows > Test Explorer (In Visual Studio 2019, use Test > Test Explorer)
  6. You can run your tests from this panel (not using the "Start" button)
  7. You can debug your tests from this panel:
    1. Double click on a test. Set some breakpoints in the test in the editor panel.
    2. right-click on the same test, select "Debug Selected tests".

To test some scenarios and take advantage of the debugger:

  1. Make the "debug" project the Startup project (Right-click on the project, select: "Set as StartUp Project")
  2. Just modify the "Program.cs"
  3. Set some breakpoints and hit the "Start" button

They also use TagLib#

Non exhaustive list of projects that use TagLib#:

  • Lidarr
  • MediaPortal 2
  • F-Spot

And you, what do you use TagLib# for? Reply here

Contributions

TagLib# is free/open source software, released under the LGPL. We welcome contributions! Please try to match our coding style, and include unit tests with any patches. Patches can be submitted by issuing a Pull Request (Git).

Issues

Quick list of the latest Issues we found

BourgeoisDirk

BourgeoisDirk

Icon For Comments0

I'm having some strange behavior with Adding the Picture... It sometimes does not show up consistently, across converting an entire Album (list of MP4 files). The same Tags are always used: Title, Artist, Album, Year, Picture ... E.G.: I set the Artist to Robin Williams (each download shows the Image), I set the Artist to James Horner (none of the downloads show an Image), I only set Artist to James Horner (each download shows the Image), ... I can add any other combination of Tags, but for some reason, adding certain Artist names consistently results in a Missing Picture. The above example is done in consecutive runs (chronologically, without exiting the application).. For some reason anytime I set

` public string ConvertToMp3(string mp4File, string title, IDictionary<Enumeration.Tag, object>? tags = null) { try { var inputFile = new MediaToolkit.Model.MediaFile { Filename = mp4File }; var thumbnailFile = new MediaToolkit.Model.MediaFile { Filename = Path.ChangeExtension(mp4File, "jpg") }; var outputFile = new MediaToolkit.Model.MediaFile { Filename = Path.ChangeExtension(mp4File, "mp3") };

using (var engine = new Engine()) { engine.GetMetadata(inputFile); var options = new MediaToolkit.Options.ConversionOptions { Seek = TimeSpan.FromSeconds(15) }; engine.GetThumbnail(inputFile, thumbnailFile, options);
            engine.<span>Convert(<span>inputFile</span>, <span>outputFile</span>)</span>;                    
        }

        File.<span>Delete(<span>inputFile</span>.Filename)</span>;

        Tools.<span>AddTags(<span>outputFile</span>.Filename, Tools.AddTagTitle(<span>tags</span>, <span>title</span>)</span>, thumbnailFile.Filename);
        File.<span>Delete(<span>thumbnailFile</span>.Filename)</span>;

        return outputFile.Filename;
    }
    catch (Exception ex)
    {
        ErrorOccurred?.<span>Invoke(<span>ex</span>)</span>;
    }
    
    return String.Empty;
}
public static IDictionary&lt;Enumeration.Tag, object&gt;? <span>AddTagTitle(IDictionary&lt;Enumeration.Tag, <span>object</span>&gt;? <span>tags</span>, <span>string</span> <span>title</span>)</span>
{
    <span>if</span> (tags<span> == </span>null)
        tags = <span>new</span> Dictionary&lt;Enumeration.Tag, object&gt;<span>()</span>;

    <span>if</span> (tags.<span>ContainsKey(Enumeration.Tag.Title)</span>)
        tags<span>[E<span>numeration</span>.T<span>ag</span>.T<span>itle</span>]</span> = title;
    <span>else</span>
        tags.<span>Add(Enumeration.Tag.Title, <span>title</span>)</span>;

    return tags;
}

public static void <span>AddTags(<span>string</span> <span>filepath</span>, IDictionary&lt;Enumeration.Tag, <span>object</span>&gt;? <span>tags</span>, <span>string</span>? <span>thumbnail</span> = <span>null</span>)</span>
{
    <span>if</span> ((tags<span> == </span>null)<span> || </span>(tags.Count<span> == </span><span>0</span>))
        tags = <span>new</span> Dictionary&lt;Enumeration.Tag, object&gt;<span>()</span>;

    var tagFile = TagLib.File.<span>Create(<span>filepath</span>)</span>;
    <span>if</span> (tagFile<span> == </span>null)
        return;            

    foreach (var tag <span>in</span> tags)
    {
        switch (tag.Key)
        {
            case Enumeration.Tag.Title:
                tagFile.Tag.Title = tag.Value.<span>ToString()</span>;
                break;
            case Enumeration.Tag.Artist:
                tagFile.Tag.Performers = <span>new</span> <span>string</span><span>[]</span> { tag.Value.<span>ToString()</span> };
                break;
            case Enumeration.Tag.Album:
                tagFile.Tag.Album = tag.Value.<span>ToString()</span>;
                break;
            case Enumeration.Tag.Year:
                tagFile.Tag.Year = Convert.<span>ToUInt32(<span>tag</span>.Value)</span>;
                break;
            default:
                break;
        }
    }

    <span>if</span> (!String.<span>IsNullOrEmpty(<span>thumbnail</span>)</span>)
        tagFile.Tag.Pictures = <span>new</span> TagLib.Picture<span>[<span>1</span>]</span> { <span>new</span> TagLib.<span>Picture(<span>thumbnail</span>)</span> };

    tagFile.<span>Save()</span>;            
}`

And i just noticed that simply changing this: tagFile.Tag.Performers = new string[] { tag.Value.ToString() }; To this: tagFile.Tag.AlbumArtists = new string[] { tag.Value.ToString() }; Seems to have resolved the Issue entirely ....

Weissu

Weissu

Icon For Comments2

SAVE freezes inconsistently on FLAC files.

The following lines are enough to freeze.

using TagLib.File tagFile = TagLib.File.Create(fileAbstraction); tagFile.Save();

But if make code like following and catch error:

using TagLib.File tagFile = TagLib.File.Create(fileAbstraction); Task WriteTagsTask = Task.Run(() => { try { tagFile.Save(); } catch { throw new Exception(); } }).ContinueWith((task) => { //Throw exception -> will recall this void again ... if (task.IsFaulted) throw new CannotWriteTrackAudioFileRetry(CannotWriteTrackAudioFileRetryMessage); }); WriteTagsTask.Wait(TimeSpan.FromSeconds(15));

and wait 'task' about 15 sec (or anything) and recall this void again if 'task' failed. After recalling this void again Save will pass normally and all tags will be written correctly.

benrr101

benrr101

Icon For Comments0

This is more of a question that might turn into an issue than an outright issue.

Still working on my port of taglib-sharp to node, and I was wondering if I could substitute a CRC library for having the big CRC table in the ByteVector class. However, when I compared the output of the CRC library with the output of the taglib-sharp, the values don't match. Which leads me to ask what checksum algorithm is being used?

The docs show it's CRC32, but I can't seem to replicate the output with any of the CRC32 algorithms in https://www.nuget.org/packages/System.Data.HashFunction.CRC/ Here's a test program I wrote to try and figure it out.

output:

hinterlandcreative

hinterlandcreative

Icon For Comments0

Videos recorded on iOS and Android both record the orientation of the device (portrait or landscape) in the Rotation metadata flag. See notes here: https://blog.addpipe.com/mp4-rotation-metadata-in-mobile-video-files/

This means that a vertical video with dimensions of 1920x1080 will have it's height and width in the mp4 as 1080x1920 and the rotation metadata set as 90˚.

Repro steps:

  1. Record a video on an Android device in vertical (portrait mode).
  2. Read the metadata with Taglib-Sharp
  3. No Rotation property is read and dimensions are reversed.
guzelonur

guzelonur

Icon For Comments0

Hi there,

I came across an issue with some of my very old mp3 files that cause crash at Create() method when they're passed as parameter. Then I decided to inspect them and found that they have NO metadata (ID3 tags) at all.

Additionaly, I passed a file with ID3 (v1 and v2) tag on Create method just fine. To test the behaviour, I removed its tag using TagLib Sharp's RemoveTags method, then saved it using Save() method. In the end I passed the final file (with no ID3 tag) again on Create() method again, exception happened as expected (Method Not Found exception).

Has anybody discovered that before?

Best regards.

hippogamesunity

hippogamesunity

Icon For Comments3

Hello! Please consider replacing reflection (File) Activator.CreateInstance to make this library compatible with Unity game engine.

Arlodotexe

Arlodotexe

Icon For Comments2

When scanning a file on WebAssembly via Uno Platform, the following error is logged:

dotnet.js:1 ThreadPool Callback threw an unhandled exception of type System.MissingMethodException

Full, minimal repro here: TagLibSharpOnUnoWasm.zip

I've tested UWP and Android, both are working as expected. This issue only occurs when running in the browser.

Aionir

Aionir

Icon For Comments0

For M4A files, TL# gets most of the tag info properly but when it comes to the properties BitsPerSample and AudioBitrate, they return 0. Also these files contain one image (Front Cover) but TL# reports the type as NotAPicture. I can still extract said image fine.

Several media players and tag editors show this info properly so I'm fairly certain there isn't an issue with the files or the way the tags were written.

Miner-2021

Miner-2021

Icon For Comments0

ByteVector.cs

2460 if (use_broken_latin1) 2461 return Encoding.Default;

On .NET Core, the Default property always returns the UTF8Encoding In .NET Framework - ANSI

does UseBrokenLatin1Behavior work correctly in both cases?

mitchfizz05

mitchfizz05

Icon For Comments3

When loading music files using TagLib.File.Create(file, ReadStyle.PictureLazy), the album art continues to be loaded. This causes huge RAM usage when dealing with many files.

Adding file.Tag.Pictures = null; mitigates the RAM usage issue, however isn't ideal. (Images cannot be lazily accessed, constant GCs)

RAM usage without Pictures = null: Default Behaviour

RAM usage with Pictures = null immediately after File.Create: Set pictures null

SID9-HoneyBee

SID9-HoneyBee

Icon For Comments0

I want to get rotation tag information from a video file in MP4 format.

MediaElement in WPF ignores rotation tags. so I I want to control LayoutTransForm by utilizing that tag information.

Is there any way to get rotation tag information from my video?

BlackTieSoftware

BlackTieSoftware

Icon For Comments0

On lines 768, 773 and 777, TITLE should be changed to ALBUM. Here's what it should be.

/// <summary> /// Gets and sets the album of the media represented by the /// current instance. /// </summary> /// <value> /// A <see cref="string" /> object containing the album of /// the media represented by the current instance or <see /// langword="null" /> if no value is present. /// </value> /// <remarks> /// This property is implemented using the "ALBUM" Tag in the Collection Tags. /// </remarks> public override string Album { get { var tag = TagsAlbum (false); return tag?.GetString ("ALBUM"); } set { var tag = TagsAlbum (true); if (tag != null) tag.Set ("ALBUM", null, value); } }
rb0135

rb0135

Icon For Comments2

Hi,

Ive run into a problem where executing the .Save() command freezes. There is no returned error, just seems the save thread freezes.

To elaborate, I am using the small routine (see below code) to change the Title of my movie files (mp4, mkv and avi files only) and if I run a single movie through the routine to change the title it will work. If I start a batch with a lot of files to change, I might get through 3-5 then the freeze occurs. I have never had it freeze on the 1st one. If I run the batch again, starting at the file that it froze on, it is fine, updates the title and runs for another 3-5 until it occurs again. I though the file might have been corrupted, but since it worked the second time around, then Im not sure that is the case.

Any ideas to try? I've tried to read/search this issue, but there doesnt seem to be much information, and certainly none about freezing when saving.

Edit: Something I have noticed. when it fails, I have checked the Title Tag in the file it froze on. So, it seems it must have written the new tag information, then froze after that.

public static void UpdateMediaTitle(string path, string title) { try { TagLib.File tfile = TagLib.File.Create(path); tfile.Tag.Title = title; tfile.Save(); <---- freezes here } catch { } <----- never gets any exception }

EpsiRho

EpsiRho

Icon For Comments0

Images with keywords already will show properly, but when an image doesn't already have Keywords, the array wont set. I also cannot resize or copy my array into it.

Array.Copy() Returns Destination array was not long enough. Check destIndex and length, and the array's lower bounds.

And when trying to resize the array, I find that I can't use ref or out keywords with properties or indexers.

forReason

forReason

Icon For Comments0

So for normal tags such as title, artist etc, the library works fine.

I am in dare need for custom fields. I have looked at the readme example which states the following code:

unfortunately, this does not bring me any further. When I execute the code, after the following section, the variable custom is null. There is no error thrown:

However. Later, when trying to add or remove a tag, a NullReferenceException is thrown, stating that custom == null:

hyperpixel34

hyperpixel34

Icon For Comments0

Hello,

I can't see the Album Art on Windows Media Player, but I can see it on VLC. I'm using this Code:

TagLib.File trackFile = TagLib.File.Create("/path/to/mp3"); Picture picture = new Picture("/path/to/jpeg")); picture.Type = PictureType.FrontCover; picture.MimeType = "image/jpeg"; trackFile.Tag.Pictures = new TagLib.IPicture[1] { picture }; trackFile.Save();

Hope you can help me

KoenDeMol

KoenDeMol

Icon For Comments5

I tried to use this library in .Net Core 5 application just as described in the docs. I can "create" the TagLib file. I set some tags, like example file.Tag.Title = "xxxx" (which can be seen as succesfully set in the debugger). I can do .Save() without getting any errors, but the tags are not written/saved. I can't see it in the "Property/Details" in Windows Eplorer and when I reopen the file with TagLib.File.Create() method, the Title is still "NULL".

Am I forgetting something?

FYI: Tried on MKV and JPG files.

var fullPath2 = @"D:\Temp\550x471.jpg"; var t = TagLib.File.Create(fullPath2); t.Tag.Title = "Hello"; t.Tag.Comment = "This is a test"; t.Tag.Year = 2021; t.Save();
SMRShahim

SMRShahim

Icon For Comments0

hi i use taglibe sharp but this has a problem with arabic character in reading tag info its show up the arabic character to latin! and make a problem to copy tags

in detail : مباحث but it showed : ÇÈÌÏåæÒ

powercode

powercode

Icon For Comments0

is used to parse BeatsPerMinute

Should probably be used, since the parsing will fail on cultures that have a comma , as decimal separator.

vrdriver

vrdriver

Icon For Comments6

Hi, I'm attempting to read (and later write) WAV files with known custom APE tags, but there doesn't seem to be a way to do it? Am I missing something?

The main help example says it's possible (basically)

This code of mine works if the file is an MP3, but will fail in this example, as it's been given a WAV File.

This also fails as well, because Riff doesn't appear to have custom tags?

TagLib.Riff.InfoTag test = (TagLib.Riff.InfoTag)file.GetTag(TagLib.TagTypes.RiffInfo); test = custom.GetField("MY_TAG");

A program I'm using (while written in Delphi) has a stand-alone program in it called TrackTool, and it's able to read and write custom APE metadata to just about any audio file.

It basically writes and reads the following metadata fields with a value in milliseconds to keep up with its cue points for audio playout.

Is what I'm trying to do even possible using taglib-sharp? Thanks.

mgomez00

mgomez00

Icon For Comments1

Hello,

I originally opened a post at https://community.metabrainz.org/t/newbie-first-day-first-question/491935/3 about this issue, but after a short discussion with one of the member he suggested thet I bring the issue here,

The case is; I have noticed that some tags are not saved to the fuile metadata (specially for mp4 files) , for example Tone (or BPM in mp4). Is there a way to intercept this output from picard and store it to an empty tag in the file?.

I update the tags with MusicBraibz Picard and once updated, the tags are shown in that program (reading the updated file), but I can not get any information in tags such as ARTIST, BPM and some more with TagLibSharp. I am using C# and i can perfectly read these tags from mp3 files. The problem is on mp4. Any suggestion?

Thanks

JerzyR

JerzyR

Icon For Comments1

Dim fl As TagLib.File = TagLib.File.Create(pth) Dim tak As TagLib.Image.CombinedImageTag = CType(fl.Tag, TagLib.Image.CombinedImageTag) tak.Software = "my software" Cannot assign to property, it is Nothing , also many other properties does not work, especially dates The only one Comment property accepts new data in code when i debug but after i call fl.Save() it is not saved

How to write tags to pictures?

pallaviagarwal0301

pallaviagarwal0301

Icon For Comments0

Dear Sir,

I am facing a one major issue .when i add keyword in image than in case of null date taken it does nothing. and when i added date taken by code still it doesnt work but if i added date manually then it work

but i have to add date using code

please help

david-hill

david-hill

Icon For Comments1

"Morton Feldman - Sabat / Clarke" becomes: "Morton Feldman - Sabat Clarke"

$taglib = "d:\tools\taglib-sharp.dll" [system.reflection.assembly]::loadfile($taglib)

function find_artist { $=$args[0] $media = [taglib.file]::create($.FullName) $tags = $media.GetTag('Id3v2') $fileperformers = $tags.performers $filealbumartists = $tags.albumartists if (-not ( $fileperformers -eq $null) -and [string]::IsNullOrEmpty($fileperformers) -eq $False ) { return $fileperformers } elseif ( -not ( $filealbumartists -eq $null ) -and [string]::IsNullOrEmpty($filealbumartists) -eq $False ) { return $filealbumartists } else { return $False } }

$basepath="D:\files" $a = Get-ChildItem $basepath -recurse | Where-Object {$_.PSIsContainer -eq $True}

$a | Where-Object {$.GetFiles().Count -ne 0 -and $.GetDirectories().count -eq 0} | get-childitem | ForEach-Object { if ( $.FullName -like '*mp3' -or $.FullName -like '*flac' -or $.FullName -like '*m4a' -or $.FullName -like '*wav') { if (Test-Path -LiteralPath $.FullName) { $artist=find_artist $ if (-not ( $artist -eq $False) ) { if ( ( -not ( $artist -match "&") ) -and ( -not ( $artist -match "/" ) ) ) { $dir=Split-Path -Path $_.FullName -Parent if ( -not ( "$dir" -like "$basepath$artist*" ) -and -not ("$dir" -like "$basepath$artist") ) { write-host "dir" $dir write-host "$basepath$artist" write-host $artist if (-not(Test-Path -LiteralPath "$basepath$artist") ) { New-Item -Path "$basepath" -Name "$artist" -ItemType "directory" } move-item -literalpath "$dir" -destination "$basepath$artist" -Force } } else { write-host "$artist" } } } } }

Versions

Quick list of the latest released versions

TaglibSharp-2.3.0.0 - Jul 30, 2022

  • Added support for chapters by implementing the frames CHAP and CTOC (#228) - Jan Romero
  • Adding extended precision ByteVector conversion (#245) - Benjamin Russell Using extended precision conversion to get any possible AIFF sample rate
  • Audio Id3v2 add support for the Tag Length (#284) - L Carroll
  • ASF Duration Calculation Fix, Creation Date Fix (#256) - Benjamin Russell
  • Property preventing autocreate id3 tag types (#254) - Helmut Wahrmann
  • Multiple music brainz entries (#253) - Helmut Wahrmann
  • MusicBrainz Tags should be retrieved case insensitive (#243) - Helmut Wahrmann
  • Make methods SetUserTextAsString public (#242) - Helmut Wahrmann
  • MPEG Audio Header Offset Calculation (#241) - Benjamin Russell
  • Add format to TrackCount setter (#240) - EatonZ
  • Improve JPG detection in GetExtensionFromData (#239) - EatonZ
  • Fixed: Corrupting OPUS files on write (#232) - ta264
  • Add support for webm audio files (#219) - Michael Phillips
  • Bump to net462 - Stephen Shaw
  • Remove gtk# dependency in tests. Replaced with SixLabors.ImageSharp - Stephen Shaw
  • Added support for IPLS Frame (#208) - Helmut Wahrmann
  • Fixes #200 and copies Pictures over from Id3v2 Tag to File.Tag (#201) - Sean Kearney
  • Disregard case in Apple box names + initial unit test (#187)
  • Various repo maintenance fixes - Stephen Shaw, Andrew Sun, Mike Blaszczak, James John McGuire, ta264, Alex Koeplinger, Immanuel Martini

TaglibSharp-2.2.0.0 - Jul 24, 2019

Version 2.2.0.0 July 22, 2019

  • Remove autotools and friends. Simply code base.
  • Include a few fixes from lidarr Project

January 21, 2019

  • Lots and lots of updates including net45 and .netstandard 2.0

https://www.nuget.org/packages/TagLibSharp/2.2.0#