Giter Club home page Giter Club logo

id3's Introduction

ID3.NET

Build status Test status codecov NuGet Version NuGet Downloads

ID3.NET is a set of libraries for reading, modifying and writing ID3 and Lyrics3 tags in MP3 audio files. The core library supports netstandard20 and the full .NET 4.x frameworks.

ID3.NET also provides an extensible metadata discovery framework that can discover specific ID3 frame data (like album art, lyrics, etc.) from various online services such as Amazon, ChartLyrics.com, Discogs and more.

ID3 Support

Currently, ID3.NET supports the two most popular ID3 versions, v1.x and v2.3.

The v1.x support applies to both v1.0 and v1.1, as the difference between the two versions is very small.

While ID3.NET can read v2.3 tags, it does not recognize all v2.3 frames yet. Unrecognized frames are stored in a special UnknownFrame class and do not raise exceptions. Most of the commonly-used frames such as title, album, artist, etc. are implemented and we are actively working on completing the remaining frame support. This will be done in the ID3.NET v0.x version range, culminating in a v1.0 release with full ID3 v2.3 frame support. You can track the progress of frame implementation and see the list of currently supported frames here.

We will start on ID3 v2.2 and v2.4 tag support as soon as the v2.3 codebase is done. Please see the project roadmap for more details.

Examples

Reading ID3 tags

Reads all .mp3 files in a directory and outputs their title, artist and album details to the console.

string[] musicFiles = Directory.GetFiles(@"C:\Music", "*.mp3");
foreach (string musicFile in musicFiles)
{
    using (var mp3 = new Mp3(musicFile))
    {
        Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);
        Console.WriteLine("Title: {0}", tag.Title);
        Console.WriteLine("Artist: {0}", tag.Artists);
        Console.WriteLine("Album: {0}", tag.Album);
    }
}

Method to enumerate theough the specified MP3 files and return those from the 1980's.

IEnumerable<string> GetMusicFrom80s(IEnumerable<string> mp3FilePaths)
{
    foreach (var mp3FilePath in mp3FilePaths)
    {
        using (var mp3 = new Mp3(mp3FilePath))
        {
            Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);
            if (!tag.Year.HasValue)
                continue;
            if (tag.Year >= 1980 && tag.Year < 1990)
                yield return mp3FilePath;
        }
    }
}

Writing ID3 tags

Method to write a generic copyright message to the ID3 tag, if one does not exist.

void SetCopyright(string mp3FilePath)
{
    using (var mp3 = new Mp3(mp3FilePath, Mp3Permissions.ReadWrite))
    {
        Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);
        if (!tag.Copyright.IsAssigned)
        {
            int year = tag.Year.GetValueOrDefault(2000);
            string artists = tag.Artists.ToString();
            tag.Copyright = $"{year} {artists}";
            mp3.WriteTag(tag, WriteConflictAction.Replace);
        }
    }
}

id3's People

Contributors

dependabot-preview[bot] avatar dependabot-support avatar jeevanjames avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

id3's Issues

Parsing song length

Hi, is it possible to extract the song length and convert it to say a time span. Any info would be appreciated!

Thanks!

Not reading entire tag

This library isn't parsing all of the frames in this file:
01-02- DNA [Explicit] - Copy.zip

For example, if I read that file and then write it back out, I see differences. Here's one:

image

I know some of these frames are not implemented, like TPOS but some are like TCOP.

Unable to Add an ID3.v2 Tag to an MP3

Hey, so far this is one of the most convenient ID3 Tag Editors I've come across.
Only thing is, I can't actually Add an ID3 tag to a freshly created MP3.

    _private void ApplyID3Tags(string filepath)
    {
        using (var file = new Mp3(filepath, Mp3Permissions.ReadWrite))
        {
            var tag = file.GetTag(Id3TagFamily.Version2X);
            if (tag == null)
                tag = new Id3Tag();
            
            tag.Title = Title;
            
            if (!file.WriteTag(tag, WriteConflictAction.Replace))
                throw new Exception("Applying ID3 Tags Failed");
        }
    }_

This seems simple enough, but I get this error on the "file.WriteTag()" function at the end: "Sequence contains no matching element"

System.InvalidOperationException
HResult=0x80131509
Message=Sequence contains no matching element
Source=System.Linq
StackTrace:
at System.Linq.ThrowHelper.ThrowNoMatchException()
at Id3.Id3Handler.GetHandler(Id3Version version)
at Id3.Mp3.WriteTag(Id3Tag tag, WriteConflictAction conflictAction)

Any clue as to why I can't add an ID3 tag ?
PS: GetTag() resulted in null, so i added "new Id3Tag()"
Also, "file.AvailableTagVersions" count = 0

Delete Pictures Tag

I use tag.Pictures.Clear() and tag.Remove<Id3.Frames.PictureFrame>() to delete the picture frame of mp3 file, but both of these methods will let the music player(I have tried WMP and MPC-HC) work abnormally, (when I use WMP, it will try to decode the mp3 file and then crash).
Here is my code:

public static bool ClearMp3Cover(Mp3 mp3) {
    Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);

    if (tag.Pictures != null) {
        // tag.Remove<Id3.Frames.PictureFrame>();
        tag.Pictures.Clear();
    }
    return mp3.UpdateTag(tag);
    // return mp3.WriteTag(tag, WriteConflictAction.Replace);
}

image
image

Discover tags

Hi,

how we can do for discover tags from online services?

thanks

Issue with blank lines in the comment tag and empty PRIV frame.

Whilst tagging some of my music files I found that if there were blank line in the comment tag then a NULL EXCEPTION is thrown,

Also I found that if there is an empty private frame then again an exception is thrown. I am not sure that empty private frames are valid though.

Revamp the genre frame

The genre frame currently exposes its data as a string, which is not really useful. It needs to be more strongly-typed.

  • Add enums for the ID3v1 genres as well as the Winamp extensions mentioned in the spec.
  • Since multiple genre values can be specified, make it a collection.
  • As per the ID3v2 spec, have special properties to indicate whether the track is a remix (RX) or a cover (CR).

Whitelist frames that can be used in FileNamer pattern

Not all ID3 frames can be used for the FileNamer pattern (for example, the lyrics frame). Only frames who's ToString() method returns a single, reasonably short line of text can be considered.

Consider adding a list of allowed frame types as an enum and using that to validate the pattern.

Adding lyrics: System.NotImplementedException: The method or operation is not implemented.

trying to add lyrics:

Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);
tag.Lyrics.Add("foo", "bar");
mp3.WriteTag(tag, WriteConflictAction.Replace);

throws:

System.NotImplementedException: The method or operation is not implemented.
at Id3.v2.Id3V23Handler.EncodeLyrics(Id3Frame id3Frame)
at Id3.v2.Id3V23Handler.GetTagBytes(Id3Tag tag)
at Id3.v2.Id3V23Handler.WriteTag(Stream stream, Id3Tag tag)
at Id3.Mp3.WriteTag(Id3Tag tag, WriteConflictAction conflictAction)

, as does

Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);
Id3.Frames.LyricsFrame lf = new Id3.Frames.LyricsFrame("foo", "bar");
lf.Language = Id3Language.ger;
lf.EncodingType = Id3TextEncoding.Unicode;
tag.Lyrics.Add(lf);
mp3.WriteTag(tag, WriteConflictAction.Replace);

I thought maybe setting language and encoding type might help, but no luck.
Am I doing something wrong, or is there something actually not implemented?

Strong type the copyright frame

Instead of having a string for the copyright value and expecting consumers to understand its conventions, use two properties for the year (integer) and the copyright message.

tag.Copyright.Year = 1977;
tag.Copyright.Message = "Aerosmith";

Since these two properties are mandatory, there would not be any default property, and hence no need for an implicit cast operator for the default value to frame instance.

I'm also not sure of the frame having the ability to output the complete copyright string (i.e. Copyright (c) 1977 Aerosmith). This is not localized and will not be useful for any language other than English. Instead, leave it to the consumer to construct the string.

However, as per the spec, it would be useful to have a read-only property that can combine the Year and Message properties correctly.

Audio File Length 00:00:00

Hello,
I have 2 questions/issues that I hope you can help me with:

  1. When I try to retrieve the audio file's length (which is clearly set under the Details tab of the file -> Length), it always shows as "00:00:00". Am I doing something wrong or is this not supported?

image
image

  1. Some MP3 files work just fine, and some I get the Id3Tag as null for some reason. Any particular reason why this might be happening?

This is the basic code I am using to extract the file properties:

string[] filePaths = Directory.GetFiles(Path.Combine(_environment.WebRootPath, "audio/songs")); List<SongModel> files = new List<SongModel>(); foreach (string filePath in filePaths){ using(var mp3 = new Mp3(filePath)){ Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X); if (tag != null) { files.Add(new SongModel{ Album = tag.Album ?? "", Title = tag.Title ?? "", Artist = tag.Band ?? "", Year = tag.Year ?? "", Length = (tag.Length.Value.Minutes.ToString() + ":" + tag.Length.Value.Seconds.ToString()) ?? "00:00", FileName = Path.GetFileName(filePath) }); } } }

Implement tag merging

Allow two or more tags to be merged into a single Id3Tag instance.

Implement as a static method on Id3Tag:

Id3Tag merged = Id3Tag.Merge(tag1, tag2, tag3);

Adding Tags To a File with No Tags

Not sure if this is an issue or not, or just me not being able to figure out how to do it.

If I read in a file with no tags in it at all, and then attempt to add some 2x tags to it I get exceptions.

        using (var mp3 = new Mp3(mp3File, Mp3Permissions.ReadWrite))
        {
            Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);
            if (tag == null)
            {
                tag = new Id3Tag();
            }

            tag.Artists.Value.Clear();
            tag.Artists.Value.Add(artistName);
            
            tag.Title.Value = trackTitle;

            mp3.WriteTag(tag, WriteConflictAction.Replace);
        }

System.InvalidOperationException: 'Sequence contains no matching element'

at System.Linq.Enumerable.First[TSource](IEnumerable1 source, Func2 predicate)
at Id3.Id3Handler.GetHandler(Id3Version version)
at Id3.Mp3.WriteTag(Id3Tag tag, WriteConflictAction conflictAction)

It looks to be that when I new an Id3Tag, its version property is not initialized, and since that property setter is internal, I can't just set it myself. However if I cheat and use reflection, as below to initialize the version, the file is saved out correctly with my tags in place:

        using (var mp3 = new Mp3(mp3File, Mp3Permissions.ReadWrite))
        {
            Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);
            if (tag == null)
            {
                tag = new Id3Tag();
                //tag.Version = Id3Version.V23;
                // version is internal set, but if we use reflection to set it, the mp3.WriteTag below works.
                var propinfo = typeof(Id3Tag).GetProperty("Version", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                propinfo.SetValue(tag, Id3Version.V23);
            }

            tag.Artists.Value.Clear();
            tag.Artists.Value.Add(artistName);
            
            tag.Title.Value = trackTitle;

            mp3.WriteTag(tag, WriteConflictAction.Replace);
        }

Arithmetic operation resulted in an overflow in mp3.GetTag

image

at Id3.TextEncodingHelper.GetSplitterBytes(Id3TextEncoding encodingType)
at Id3.v2.Id3V23Handler.DecodePicture(Byte[] data)
at Id3.v2.Id3V23Handler.ReadTag(Stream stream, Object& additionalData)
at Id3.Mp3.GetTag(Id3TagFamily family)
at Program.<

$>g__readFile|0_0(String musicFile) in C:\Temp\fixMp3\Program.cs:line 9
at Program.$(String[] args) in C:\Temp\fixMp3\Program.cs:line 35

Unicode not supported

I call "WriteTag" with unicode characters and the MP3 title was updated with "???:????". Apparently it does not support unicode characters.

Also consider ID3v1 tags for FileNamer

The FileNamer class currently only uses ID3 v2 tags. Consider using ID3 v1 tags, if available, in cases where the corresponding ID3 v2 tag is missing.

TRCK Parsing

I have some songs, from Amazon.com, that have a frame value of new byte[] { 0, 50, 47, 49, 53, 0 } for the TRCK frame and this library isn't recognizing the values.

foobar2000 doesn't have any issues parsing it though.

I've removed the beginning, ^, and end of line, $, anchors and now it parses the values.

[Fact]
public void TRCK_BugTest()
{
	//arrange
	var path = $@"{dirStart}\01-02- DNA [Explicit] - Copy.mp3";
	var mp3 = new Mp3(path, Mp3Permissions.ReadWrite);
	var tag = mp3.GetTag(Id3TagFamily.Version2X);
	//works after changing regex
	//removing start and end things
	//data that doesn't currently work:
	//var data = new byte[] { 0, 50, 47, 49, 53, 0 };
	//was
	//Regex TrackPattern = new Regex(@"^(\d+)(?:/(\d+))?$");
	//now
	//Regex TrackPattern = new Regex(@"(\d+)(?:/(\d+))?");
	Assert.Equal(2, tag.Track.Value);
	Assert.Equal(15, tag.Track.TrackCount);

	//act 
	//should throw an exception that data will be lost
	var newMp3 = new Mp3(path + " - trck test.mp3", Mp3Permissions.ReadWrite);
	newMp3.WriteTag(tag);
	newMp3.Dispose();

	//assert
	var newMp3Assert = new Mp3(path + " - trck test.mp3", Mp3Permissions.Read);
	var tagAssert = newMp3Assert.GetTag(Id3TagFamily.Version2X);
	Assert.Equal(tag.Track.TrackCount, tagAssert.Track.TrackCount);
	Assert.Equal(tag.Track.Value, tagAssert.Track.Value);
}

Thoughts? 💭

Recording date frame issues

According to the spec, the recording date is actually a combination of the TDAT frame (which contains the day and month in DDMM format) and the TYER frame (which contains the year as a numeric string).

Instead of exposing both separately, it would be useful to have a composite kind of frame property that can encapsulate both frames and get/set the value as a DateTime.

Multiple patterns for FileNamer

Allow multiple patterns to be specified in the FileNamer class, in order of preference. The class should try to match them in order, and use the first match found. Only if it cannot find any matches for all patterns should it attempt to raise the ResolveMissingData event

Don't lose frames option

If the library doesn't know about a frame, it will get lost if the ID3 tag is read-in and written out.

What about a parameter to allow/disallow this? I don't want to lose tags, at least w/o know I am.

Thoughts? 💭

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.