Metatag is a metadata read/write library for Nim that supports id3v2.3.0 and flac metadata.
Its only dependency is nim-lang/zip
and zlib
& iconv
(on Unix).
Metatag is relatively "low level". It gives you raw access to relevant frames & attached Pictures for id3 and vorbis comments & pictures for flac. Skim through the id3v2 spec for frame ids or the vorbis comment spec for flac fieldnames. However the usage section, should guide you enough.
In this example we are reading a mp3 file, echoing all text & picture frames and exporting the pictures.
import std/[enumerate, streams, strformat]
import metatag/id3
var tag = readId3("music.mp3")
for textFrame in tag.textFrames: # echo all text frames
echo fmt"id: {textFrame.id}"
echo fmt"content: {textFrame.content}"
for userDefinedFrame in tag.userDefinedFrames: # a.k.a. TXXX & WXXX
echo fmt"id: {userDefinedFrame.id}"
echo fmt"description: {userDefinedFrame.description}"
echo fmt"content: {userDefinedFrame.content}"
for (i, picture) in enumerate(1, tag.attachedPictures): # echo all pictures & exporting them
echo fmt"picture: '{picture.mime}', '{picture.pictureType}', '{picture.description}'"
var filename:string
case picture.mime:
of "image/jpeg":
filename = fmt"picture ({i}).jpg"
of "image/png":
filename = fmt"picture ({i}).png"
of "image/webp":
filename = fmt"picture ({i}).webp"
else:
filename = fmt"picture ({i}).dat"
var strm = newFileStream(filename, fmWrite)
var picbuffer = picture.data
strm.writeData(picbuffer[0].addr,picbuffer.len)
strm.close()
In this example we are creating a new tag and an attached picture, reading the cover and write the tag to the file.
import std/streams
import metatag/id3
# Create the tag
var tag = Id3Tag(
textFrames: @[
("TIT2", "Girlfriend"),
("TPE1", "Avril Lavigne"),
("TALB", "The Best Damn Thing"),
("TRCK", "1"),
("TCON", "Pop-punk"),
("TYER", "2007"),
("TPUB", "RCA Records")
],
urlFrames: @[
("WOAF", "https://music.youtube.com/watch?v=Bg59q4puhmg"),
("WOAR", "https://www.avrillavigne.com/"),
("WPUB", "https://www.rcarecords.com/")
],
userDefinedFrames: @[
("TXXX", "BARCODE", "886970377423")
]
)
# Create an attached picture
var strm = newFileStream("picture.jpg", fmRead)
tag.attachedPictures.add(
AttachedPicture(
mime: "image/jpeg",
pictureType: 3,
description: "Idk. the cover I guess.",
data: cast[seq[byte]](strm.readAll())
)
)
strm.close()
# Write the tag to your file
writeId3("music.mp3", tag)
In this example we are reading a flac file, echoing all comments & pictures and exporting them.
import std/[enumerate, streams, strformat]
import metatag/flac
var tag = readFlac("music.flac")
echo tag.vendorString # Read the vendor string
for comment in tag.userComment: # echo every user comment
echo fmt"fieldname: {comment.fieldname}"
echo fmt"content: {comment.content}"
for (i, picture) in enumerate(1, tag.pictures): # echo all pictures & exporting them
echo fmt"picture: '{picture.pictureType}', '{picture.mime}', '{picture.description}'"
var filename:string
case picture.mime:
of "image/jpeg":
filename = fmt"picture ({i}).jpg"
of "image/png":
filename = fmt"picture ({i}).png"
of "image/webp":
filename = fmt"picture ({i}).webp"
else: # Some Devs doesnt set the mime type
filename = fmt"picture ({i}).dat"
var strm = newFileStream(filename, fmWrite)
var picbuffer = picture.data
strm.writeData(picbuffer[0].addr,picbuffer.len)
strm.close()
In this example we are creating a new tag and a flac picture, reading the cover and write the tag to the file.
import std/streams
import metatag/flac
# Create the tag
var tag = FlacTag(
userComment: @[
("TITLE", "Girlfriend"),
("ALBUM", "The Best Damn Thing"),
("TRACKNUMBER", "1"),
("ARTIST", "Avril Lavigne"),
("ORGANIZATION", "RCA Records"),
("GENRE", "Pop-punk"),
("CONTACT", "https://www.rcarecords.com/")
]
)
# Create a flac picture
var strm = newFileStream("picture.jpg", fmRead)
tag.pictures.add(
FlacPicture(
pictureType: 3,
mime: "image/jpeg",
description: "Cover of the album",
data: cast[seq[byte]](strm.readAll())
)
)
strm.close()
# Write the tag to your file
writeFlac("music.flac", tag)
-
Can you support
x
metadata format?
Maybe, currently the most popular metadata formats are supported. If you want to help out, consider contributing. -
How can I help?
You're more than welcome to contribute to this library, grab yourself a module and try to improve it or write a new parser for a soon to be supported format. -
Well, reading this file doesnt work, but it should?
Everything in this library should work™. However this library is written according to the specs and handles "dirty files" with mediocre success. Plz be gentle. -
How does it compare to Taglib?
Metatag is badly written, supports less formats, doesnt handle edge cases at all and not all features are supported. On the other hand, it's written from scratch in Nim, "easy" to use, reasonable fast and coded like my grandma could understand. -
What is unsupported?
ID3v2.3.0: UTF16BE frames on Win, unsynchronisation, encryption, Synchronised lyrics and more ... Miscellaneous: ID3v2.4.0, ID3v2.2.0 -
Great music taste.
Thanks.
Metatag - a tag reading/writing library
Copyright (C) 2022 Sauerbread
Metatag is licensed under the MIT License