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 Nonespecux.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, anddescription=for formats that store one. Cover.datais the raw image bytes,Cover.mimeits 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.