Skip to content

tags / cover

Metadata: textual tags and embedded cover art, backed by TagLib when the build includes it (builds without it keep the rest of the audio module; these functions then raise with a message saying so). One vocabulary across formats: ID3v2 for MP3, Vorbis comments for FLAC/OGG, MP4 atoms for M4A. Every function has a bytes twin for in-memory files.

tags

specux.audio.tags("song.flac")
# {'title': 'Take 3', 'artist': ..., 'album': ..., ...}
specux.audio.write_tags("song.flac", {"title": "Take 4", "artist": "P"})

write_tags merges: keys you pass are updated, the rest are preserved, and a value of None or "" removes that tag. Keys are the case-insensitive standard names (title, artist, album, date, tracknumber, …).

blob = open("song.flac", "rb").read()
blob = specux.audio.write_tags_bytes(blob, {"title": "Take 4"})
specux.audio.tags(blob)["title"] # 'Take 4' (tags reads bytes too)

cover

art = open("art.png", "rb").read()
c = specux.audio.cover("song.mp3") # Cover(data=..., mime=...) or None
specux.audio.write_cover("song.mp3", art)
specux.audio.write_cover("song.mp3", None) # remove
blob = open("song.mp3", "rb").read()
blob = specux.audio.write_cover_bytes(blob, art) # bytes in, bytes out
  • The image format is sniffed from the data; pass mime= to override, and description= for formats that store one.
  • Cover.data is the raw image bytes, Cover.mime its type: feed it straight to an image decoder or an HTTP response.
  • Audio samples are untouched by any tag or cover rewrite; only the metadata block changes.

Stream parameters (frames, samplerate, channels) need no TagLib and live on info.