Skip to content
/ taggy Public

Dart & Flutter packages to read, write and convert audio tags

License

MIT, MIT licenses found

Licenses found

MIT
LICENSE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

DMouayad/taggy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

59 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Release taggy flutter_taggy Build Status Github Stars MIT License

taggy cover image

Provides a simple yet powerful API for reading, writing and converting audio tags (metadata).

Table of contents:

Features

Planned features ⏳

  • Batches: write to multiple files at the same time.
  • Editing file name: add the option to rename a file based on its track title.
  • TaggyFileResult: all public APIs should return a universal result; a value of TaggyFile type or an error of TaggyError type.
  • Converting tags

Getting started

Installation

Run the following command:

  • For a Dart project:

    dart pub add taggy
  • For a Flutter project:

    flutter pub add flutter_taggy

Usage

Initialization

  • With Dart

    import 'package:taggy/taggy.dart';
    
    void main(){
      Taggy.initializeFrom(DynamicLibrary.open('path/to/library.dll'));
    }

    Or

    import 'package:taggy/taggy.dart';
    
    // call this helper function which takes care of loading the library for you.
    Taggy.initializeFrom(getTaggyDylibFromDirectory('path/of/binaries/directory'));
  • With Flutter

    import 'package:flutter_taggy/flutter_taggy.dart';
    
    void main(){
      // When using the Flutter package, we don't have to pass the dynamic library 
      // ourselves but it'll be automatically fetched then loaded for us.
      // So You only need to add the following line.
      Taggy.initialize();
      
      // build something cool
    }

About TaggyFile

  • It gives us a little more information about the file(s) we're reading from or writing to, so alongside the list of Tag, we get:

    • the file size (in bytes).
    • a FileType: whether it's (flac, wav, mpeg, etc).
    • an AudioInfo, which is another type, holds the properties of the audio track.
  • you can pretty-print a TaggyFile instance by calling formatAsAString():

    output example
    TaggyFile: {
        size: 12494053 bytes ~ 12.2 MB,
        fileType: FileType.Mpeg
        primaryTagType: TagType.Id3v2,
        tags: {
        count: 1,
        items: 
          [ Tag(
                tagType: Id3v2,
                trackTitle: Fine Line,
                trackArtist: Eminem,
                trackNumber: 9,
                trackTotal: 1,
                discTotal: null,
                discNumber: null,
                album: SHADYXV,
                albumArtist: Various Artists,
                genre: null,
                language: null,
                year: null,
                recordingDate: null,
                originalReleaseDate: null,
                has lyrics: true,
                pictures: {
                  count: 1,
                  items: [ Picture(
                    picType: PictureType.CoverFront,
                    picData(Bytes): 168312,
                    mimeType: MimeType.Jpeg,
                    width: 1000,
                    height: 1000,
                    colorDepth: 24,
                    numColors: 0,
                    )],
                },
              ),
          ],
        },
        audio: AudioInfo(
        channelMask: 3,
        channels: 2,
        sampleRate: 44100,
        audioBitrate: 321,
        overallBitrate: 326,
        bitDepth: null,
        durationSec: 306,
        ),
    }
    

Reading tags

  • Reading all tags:

    const path = 'path/to/audio/file.mp3';
    
    final TaggyFile taggyFile = await Taggy.readAll(path);
    // you can use the getter which, under the hood, is [taggyFile.tags.firstOrNull]
    print(taggyFile.firstTagIfAny);
    
    // or easily access all returned tags
    for (var tag in taggyFile.tags) {
      print(tag.tagType);
    }
  • Reading primary tag:

    final path = 'path/to/audio/file.mp3';
    final TaggyFile taggyFile = await Taggy.readPrimary(path);
  • Reading any tag:

    It's similar to readPrimary except that the returned TaggyFile.tags might be empty.

    const path = 'path/to/audio/file.mp3';
    final TaggyFile taggyFile = await Taggy.readyAny(path);
    
    // you can also use [formatAsString], we still get a [TaggyFile].
    print(taggyFile.formatAsString());
    
    // you may want to check if it has any tags
    final hasTags = taggyFile.tags.isNotEmpty();
    // Or use the getter
    final Tag? tag = taggyFile.firstTagIfAny;

Writing tags

  • About specifying the TagType

    A tag type is required for creating a new Tag instance. You can:

    • check what TagType the file supports based on its type(extension). see this table.

    • Use the function Taggy.writePrimary() and pass it a Tag with a type of TagType.FilePrimaryType, as shown in example below.

  • Example of creating a new Tag
    Tag getTagInstance(TagType tagType){
      return Tag(
        tagType: tagType,
        album: 'Some Album',
        trackTitle: 'some Track',
        trackArtist: 'Some Artist',
        trackTotal: 10,
        trackNumber: 1,
        discNumber: 1,
        discTotal: 2,
        year: 2023,
        recordingDate: '1/3/2019',
        language: 'EN',
        pictures: [
          Picture(
            // zeros are used to demonstrate how to provide a picture's data.
            picData: Uint8List.fromList([0, 0, 0, 0]),
            mimeType: MimeType.Jpeg,
            picType: PictureType.CoverFront,
            width: 1000,
            height: 800,
          ),
        ],
      );
    }
  • Writing primary tag:

    final path = 'path/to/audio/file.mp3';
    
    final tagToWrite = getTagInstance(TagType.FilePrimaryType);
    
    final TaggyFile taggyFile = await Taggy.writePrimary(
      path: path, tag: tagToWrite, keepOthers: false);
    
    // On Success, [taggyFile.tags] will contain the newly added tag.
    // NOTE: this tag may not contain the same properties of [tagToWrite].
    final pTag = taggyFile.primaryTag;
  • Writing multiple tags:

    In most use-cases, you'll use Taggy.writePrimary() to add/edit an audio tag metadata, but you can also provide multiple tags to be written to the same file.

    final path = 'path/to/audio/file.mp3';
    
    final tags = [
      getTagInstance(TagType.FilePrimaryType),
      getTagInstance(TagType.Id3v1),
    ];
        
    final TaggyFile taggyFile = await Taggy.writeAll(
      path: path, tag: tagToWrite, overrideExistent: true);

Removing tags

  • Remove a specific Tag

    You can delete a tag from file by specifying its tag type.

    final path = 'path/to/audio/file.mp3';
    
    // The type of to-remove-tag
    final tagType = TagType.Ape;
    
    final TaggyFile taggyFile = await Taggy.removeTag(path: path, tagType: tagType);
  • Remove all tags

    final path = 'path/to/audio/file.mp3';
    final TaggyFile taggyFile = await Taggy.removeAll(path: path);
    
    print(taggyFile.tags);
    // output is []

Feed back & Contributions

  • πŸ› Found an issue or encountered a bug? please check the existing issues or create a new one.

  • πŸ’ͺ🏻 Want to contribute? Thank you, its always welcomed!. You can start by reading the Contributing guide.

  • πŸ™πŸ» You can also contribute if you ⭐ this repository and πŸ‘πŸ» the Dart and Flutter packages on Pub.dev, we do appreciate your love.

Acknowledgement

  • lofty: a Rust library which provides Taggy with its functionality.

  • Flutter Rust Bridge: connects Rust APIs with Dart & Flutter.