Read music meta data and length of MP3, OGG, OPUS, MP4, M4A, FLAC, WMA and Wave files with python 2 or 3

Related tags

Audio tinytag
Overview

tinytag

tinytag is a library for reading music meta data of MP3, OGG, OPUS, MP4, M4A, FLAC, WMA and Wave files with python

Build Status Build status Coverage Status

Install

pip install tinytag

Features:

  • Read tags, length and cover images of audio files
  • supported formats
    • MP3 (ID3 v1, v1.1, v2.2, v2.3+)
    • Wave/RIFF
    • OGG
    • OPUS
    • FLAC
    • WMA
    • MP4/M4A/M4B
  • pure python, no dependencies
  • supports python 2.7 and 3.4 or higher
  • high test coverage
  • Just a few hundred lines of code (just include it in your project!)

tinytag only provides the minimum needed for reading MP3, OGG, OPUS, MP4, M4A, FLAC, WMA and Wave meta-data. It can determine track number, total tracks, title, artist, album, year, duration and more.

from tinytag import TinyTag
tag = TinyTag.get('/some/music.mp3')
print('This track is by %s.' % tag.artist)
print('It is %f seconds long.' % tag.duration)

Alternatively you can use tinytag directly on the command line:

$ python -m tinytag --format csv /some/music.mp3
> {"filename": "/some/music.mp3", "filesize": 30212227, "album": "Album", "albumartist": "Artist", "artist": "Artist", "audio_offset": null, "bitrate": 256, "channels": 2, "comment": null, "composer": null, "disc": "1", "disc_total": null, "duration": 10, "genre": null, "samplerate": 44100, "title": "Title", "track": "5", "track_total": null, "year": "2012"}

Check python -m tinytag --help for all CLI options, for example other output formats`

List of possible attributes you can get with TinyTag:

tag.album         # album as string
tag.albumartist   # album artist as string
tag.artist        # artist name as string
tag.audio_offset  # number of bytes before audio data begins
tag.bitrate       # bitrate in kBits/s
tag.comment       # file comment as string
tag.composer      # composer as string 
tag.disc          # disc number
tag.disc_total    # the total number of discs
tag.duration      # duration of the song in seconds
tag.filesize      # file size in bytes
tag.genre         # genre as string
tag.samplerate    # samples per second
tag.title         # title of the song
tag.track         # track number as string
tag.track_total   # total number of tracks as string
tag.year          # year or data as string

Additionally you can also get cover images from ID3 tags:

tag = TinyTag.get('/some/music.mp3', image=True)
image_data = tag.get_image()

Changelog:

  • 1.5.0 (2020-11-05):
    • fixed data type to always return str for disc, disc_total, track, track_total #97 (thanks to kostalski)
    • fixed package install being reported as UNKNOWN for some python/pip variations #90 (thanks to russpoutine)
    • Added automatic detection for certain MP4 file headers
  • 1.4.0 (2020-04-23):
    • detecting file types based on their magic header bytes, #85
    • fixed opus duration being wrong for files with lower sample rate #81
    • implemented support for binary paths #72
    • always cast mp3 bitrates to int, so that CBR and VBR output behaves the sam
    • made str deterministic and use json as output format
  • 1.3.0 (2020-03-09):
    • added option to ignore encoding errors ignore_errors #73
    • Improved text decoding for many malformed files
  • 1.2.2 (2019-04-13):
    • Improved stability when reading corrupted mp3 files
  • 1.2.1 (2019-04-13):
    • fixed wav files not correctly reporting the number of channels #61
  • 1.2.0 (2019-04-13):
    • using setup.cfg instead of setup.py (thanks to scivision)
    • added support for calling TinyTag.get with pathlib.Path (thanks to scivision)
    • added appveyor windows test CI (thanks to scivision)
    • using pytest instead of nosetest (thanks to scivision)
  • 1.1.0 (2019-04-13):
    • added new field "composer" (Thanks to Phil Borman)
  • 1.0.1 (2019-04-13):
    • fixed ID3 loading for files with corrupt header (thanks to Ian Homer)
    • fixed parsing of duration in wav file (thanks to Ian Homer)
  • 1.0.0 (2018-12-12):
    • added comment field
    • added wav-riff format support
    • use MP4 parser for m4b files
    • added simple cli tool
    • fix parsing of FLAC files with ID3 header (thanks to minus7)
    • added method TinyTag.is_supported(filename)
  • 0.19.0 (2018-02-11):
    • fixed corrupted images for some mp3s (#45)
  • 0.18.0 (2017-04-29):
    • fixed wrong bitrate and crash when parsing xing header
  • 0.17.0 (2016-10-02):
    • supporting ID3v2.2 images
  • 0.16.0 (2016-08-06):
    • MP4 cover image support
  • 0.15.2 (2016-08-06):
    • fixed crash for malformed MP4 files (#34)
  • 0.15.0 (2016-08-06):
    • fixed decoding of UTF-16LE ID3v2 Tags, improved overall stability
  • 0.14.0 (2016-06-05):
    • MP4/M4A and Opus support
Comments
  • tinytag unable to process valid mp3

    tinytag unable to process valid mp3

    I was trying to use tinytag.TinyTag.get(filename), but it errored and said tinytag.tinytag.TinyTagException: mp3 parsing failed. Now I get that this means the mp3 is invalid, but the weird thing is: It works with ffplay, VLC and WMP (and probably all music playing software)

    File was downloaded using youtube_dl, not sure if that matters.

    Traceback (most recent call last):
      File "D:\Program_Files\Python\lib\site-packages\tinytag\tinytag.py", line 311, in _determine_duration
        frame_bitrate = ID3.bitrate_by_version_by_layer[mpeg_id][layer_id][br_id]
    TypeError: 'NoneType' object is not subscriptable
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "D:\Program_Files\Python\lib\site-packages\tinytag\tinytag.py", line 94, in get
        tag.load(tags=tags, duration=duration, image=image)
      File "D:\Program_Files\Python\lib\site-packages\tinytag\tinytag.py", line 115, in load
        self._determine_duration(self._filehandler)
      File "D:\Program_Files\Python\lib\site-packages\tinytag\tinytag.py", line 313, in _determine_duration
        raise TinyTagException('mp3 parsing failed')
    tinytag.tinytag.TinyTagException: mp3 parsing failed
    
    bug need more info 
    opened by Martmists-GH 9
  • found (and fixed) a bug in the _set_field function

    found (and fixed) a bug in the _set_field function

    This is my first time using tinytag I have a collection of 75000 mp3s Turns out that one of the files had 1/4/4/4/4/4 stored in the "disc" tag which made _set_field crash

    If you change the lines from current, total = str(value).split('/') #which of course only works if the value is xx/xx

    to this: splits = str(value).split('/') current, total = splits[0], splits[1]

    it will work every time

    opened by domingobernardo 9
  • [BUG] struct.error: unpack requires a buffer of 4 bytes

    [BUG] struct.error: unpack requires a buffer of 4 bytes

    Describe the bug When I trying to get file duration: TinyTag.get(filename).duration

    and for some files I have exception:

        return TinyTag.get(filename).duration
      File "/opt/virtualenvs/lib/python3.6/site-packages/tinytag/tinytag.py", line 194, in get
        tag.load(tags=tags, duration=duration, image=image)
      File "/opt/virtualenvs/lib/python3.6/site-packages/tinytag/tinytag.py", line 212, in load
        self._determine_duration(self._filehandler)
      File "/opt/virtualenvs/lib/python3.6/site-packages/tinytag/tinytag.py", line 655, in _determine_duration
        xframes, byte_count, toc, vbr_scale = ID3._parse_xing_header(fh)
      File "/opt/virtualenvs/lib/python3.6/site-packages/tinytag/tinytag.py", line 604, in _parse_xing_header
        vbr_scale = struct.unpack('>i', fh.read(4))[0]
    struct.error: unpack requires a buffer of 4 bytes
    

    Expected behavior I think that the file is damaged but tinytag should return 0 for duration, not raising strange exception. Or raising own exception.

    Sample File I can't upload it :(

    bug 
    opened by mmazurekdev 8
  • add a setup.py and organize the package files

    add a setup.py and organize the package files

    I wanted to install this to check it out via pypi or pip but first it needs a setup.py, so here you go.

    I also move the tests to the top level, and the code out of init and into tinytag.py

    setup.py gets the version number from tinytag/init.py

    note: You can run tests with ./runtests.py

    opened by rizumu 8
  • Output garbled characters when ID3V1 contains Chinese characters.

    Output garbled characters when ID3V1 contains Chinese characters.

    I changed this line to return self._unpad(codecs.decode(x, 'gbk')) got the correct meta data. https://github.com/devsnd/tinytag/blob/e9b301d9a9bc2e7645c3b6364a593ce09c32736a/tinytag/tinytag.py#L607

    Add an option of encoding? or other solution?

    bug solved in next release 
    opened by cdhigh 7
  • bitrate is in bps (not kbps) for VBR mp3 files

    bitrate is in bps (not kbps) for VBR mp3 files

    Hi,

    Any VBR mp3 file I point tinytag at gives me a bitrate value which is about 1000x what audio software reports. I expect that this value is bps rather than kbps.

    For example, for the file at (https antisol dot org slash brass dot mp3), tinytag gives me a bitrate value of 195206.785168, whereas various audio software reports the file as being 195kbps, including:

    • audacious
    • qmmp
    • vlc ('input bitrate' on 'statistics' screen lists ~195kbps, but codec info tab shows 128kbps)

    I've seen this with all other VBR mp3 files I've tried, they all give a value ~1000x the value reported by audacious.

    As a workaround I was able to do something like:

    if bitrate > 320: bitrate = bitrate / 1099
    

    to get a pretty good bitrate value. But it would be nice to see a more accurate value come from TinyTag.

    Thanks!

    opened by AntiSol 7
  • Read disc number / total number of discs?

    Read disc number / total number of discs?

    Thanks for the great library. I'm using it to build a script to automatically file audio files in a correct location and it's been really helpful.

    However, I have several multiple-disc albums where track numbers are duplicated on each disc. The actual disc number is stored in the disc number part of the track. However, tinytag doesn't seem to read this information. Any chance for adding this in a future release?

    I could give it a shot myself, but I have no idea about FLAC / OGG / MP3 ID3tag specifications and wouldn't know where to actually find this information. What sources did you use in order to implement tintytag?

    opened by EgbertW 7
  • extra 10 bytes to start get_image() ?

    extra 10 bytes to start get_image() ?

    Hi, not sure if this is an issue, or I am not using TinyTag properly!

    I am using tinytag to get image data embedded in my audio files, and passing the image data into PIL/Pillow. i have noticed that some of the image data cannot be loaded. upon closer inspection of the data, it appears that I am getting a strange 10 B prefix for all of the ones that fail.

    Here's a code fragment:

    from tinytag import TinyTag
    from PIL import Image
    import io
    
    filename = 'some/path/to/a/file.mp3
    tags = TinyTag.get(filename, image=True)
    image_data = tags.get_image()
    img = Image.open(io.BytesIO(image_data))
    # ^^^ this will fail for *some* of my audio files
    

    I noticed that it is consistent which files fail and which pass, so it must be something with my audio files. when i print out the start of the data for one of these, and compare it to a file that is OK, i see a difference:

    Good File: b'\xff\xd8\xff\xe0\x00\x10JFIF....' Bad File: b'o\x00v\x00e\x00r\x00\x00\x00\xff\xd8\xff\xe0\x00\x10JFIF......' so, it looks like the Bad File has a prefix of 10 bytes, followed by the same start as 'good file'. b'o\x00v\x00e\x00r\x00\x00\xoo' (does that say 'o v e r ' ?? weird...)

    is this expected? i'm not sure why this is showing up, and only for some audio files. my script seems to work just fine if i do this:

    if image_data[:10] == b'o\x00v\x00e\x00r\x00\x00\x00':
        image_data = image_data[10:]
    

    but this feels a bit clumsy!

    anyway, thanks in advance for taking a look! I can provide my audio files for you if needed.

    bug missing sample file 
    opened by mdougher 6
  • Invalid duration

    Invalid duration

    Hello. I open this ticket which seems to correspond to #37. I have an album with tracks about twice as long as their true duration. I send a mp3 file by email.

    bug solved in next release 
    opened by ghost 6
  • [BUG] Incorrect bitrate and duration for VBR mp3s

    [BUG] Incorrect bitrate and duration for VBR mp3s

    Describe the bug tinytag currently returns an incorrect bitrate and duration for several VBR encoded MP3 files, as seen in this screenshot:

    Screenshot from 2021-12-16 07-06-18

    There seem to be two issues that are causing this:

    The number of audio channels is included in this calculation, but it shouldn't be here: https://github.com/devsnd/tinytag/blob/2d6d51b2797565293d17b0029ad03107bceef6a0/tinytag/tinytag.py#L620

    If we change the line to self.duration = xframes * ID3.samples_per_frame / float(self.samplerate), the situation improves somewhat:

    There's still another issue that should be addressed in order to retrieve correct info for all files. samples_per_frame is always set to 1152. This is valid for MPEG-1 Audio Layer III, but the value should be 576 for MPEG-2 Audio Layer III and MPEG-2.5 Audio Layer III (lower sampling rates).

    To Reproduce Let tinytag parse the sample files.

    Expected behavior tinytag should return the same duration for all attached files, a bitrate of 32 kbps for files with a sampling rate of >=32 khz, and a bitrate of 8 kbps for files with a sampling rate of <32 khz.

    Sample File vbr_samples.zip

    bug 
    opened by mathiascode 5
  • Add support for unsynced lyrics tag?

    Add support for unsynced lyrics tag?

    I have a preliminary change in my fork of the library that supports extraction of the USLT lyrics tag if present in mp3 files, using for my own benefit. Should I submit a pull request for that if there's any interest in using it?

    There are a number of utilities out there (e.g., Lyrics Finder, mp3tag, etc.) that find and add lyrics to mp3 files for you, which I used to enhance my own music library. I've been tinkering with tinytag for a python search project on my own and thought I would add this to it.

    opened by nensor 5
  • Expose a list of supported file extensions

    Expose a list of supported file extensions

    Is your feature request related to a problem? Please describe. I'm using watchdog to watch for music file changes in the file system. I am currently passing a list of file extensions that should trigger events like this:

    ...
    
    PatternMatchingEventHandler.__init__(
        ...
        patterns=["*.flac", "*.mp3"],
        ...
    )
    
    ...
    

    I want to trigger events for all files that are supported by TinyTag. Can you expose a list or set of supported file extension that we can use for this purpose? I have checked #53 and the solution there does not work for this specific problem.

    Describe the solution you'd like A simple list of supported formats. For example:

    >>> TinyTag.SUPPORTED_EXTENSIONS
    [".mp4", ".mp3", ".flac", ...]
    
    opened by geoffrey45 0
  • [BUG] Can't read `extra` tags from .m4a files

    [BUG] Can't read `extra` tags from .m4a files

    Describe the bug I added a custom field (via mp3tag) to audio files of various types, but that custom field only appears in tinytag's extra collection for the mp3 files and not the m4a files.

    To Reproduce

    1. Unzip the Songs.zip attachment to find two files - both have a custom tag called KPL_DATE with the value TEST_DATE
    2. Dump the tags for the two contained files using tinytag: python3 -m tinytag --format json Symphony1.m4a Symphony2.mp3
    3. See that the custom tag is listed in extra for the mp3 file but not for the m4a file.
    image

    Expected behavior The custom tag is listed under extra for both files

    Sample File Songs.zip

    bug 
    opened by kylelambert101 0
  • Add support for atoms: aavd, adrm

    Add support for atoms: aavd, adrm

    Audible's proprietary .aax format uses the adrm atom (under an aavd atom, which is just a renamed mp4a atom) to store data that external tools need to decrypt the encrypted AAC audio. Also, I was able to test one of the commented out data atoms, extra.description. Just had to add the extra. to the front of description. I can provide a sample audio file if you'd like to verify it further.

    opened by snowskeleton 2
  • [BUG] TDRC tag not captured as

    [BUG] TDRC tag not captured as "year"

    Describe the bug I have a program that captures album information from my collection to a spreadsheet. Files tagged with TDRC came up with an empty year cell.

    This change to 1.8.1 caused tinytag to capture the tag to .year, instead of "extra.tdrc" 490c490 < 'TYER': 'year', 'TYE': 'year',

        'TYER': 'year', 'TYE': 'year', 'TDRC': 'year',
    

    501a502

    'TDRC': 'extra.tdrc',

    bug 
    opened by RanTalbott 2
Owner
Tom Wallroth
Tom Wallroth
convert-to-opus-cli is a Python CLI program for converting audio files to opus audio format.

convert-to-opus-cli convert-to-opus-cli is a Python CLI program for converting audio files to opus audio format. Installation Must have installed ffmp

null 4 Dec 21, 2022
Library for working with sound files of the format: .ogg, .mp3, .wav

Library for working with sound files of the format: .ogg, .mp3, .wav. By work is meant - playing sound files in a straight line and in the background, obtaining information about the sound file (author, performer, duration, bitrate, and so on). Playing goes through the pygame, and getting information through the mutagen.

Romanin 2 Dec 15, 2022
Automatically move or copy files based on metadata associated with the files. For example, file your photos based on EXIF metadata or use MP3 tags to file your music files.

Automatically move or copy files based on metadata associated with the files. For example, file your photos based on EXIF metadata or use MP3 tags to file your music files.

Rhet Turnbull 14 Nov 2, 2022
Synchronize a local directory of songs' (MP3, MP4) metadata (genre, ratings) and playlists with a Plex server.

PlexMusicSync Synchronize a local directory of songs' (MP3, MP4) metadata (genre, ratings) and playlists (m3u, m3u8) with a Plex server. The song file

Tom Goetz 9 Jul 7, 2022
❤️ Hi There Im Cozmo Music Bot A next gen powerful telegram group Music bot for get your Songs and music @Venuja_Sadew

?? Cozmo MUSIC ?? Cozmo Music is a Music powerfull bot for playing music on telegram voice chat groups. Requirements FFmpeg NodeJS nodesource.com Pyth

Venuja Sadew 3 Jan 8, 2022
NovaMusic is a music sharing robot. Users can get music and music lyrics using inline queries.

A music sharing telegram robot using Redis database and Telebot python library using Redis database.

Hesam Norin 7 Oct 21, 2022
nicfit 425 Jan 1, 2023
Okaeri-Music is a telegram music bot project, allow you to play music on voice chat group telegram.

Okaeri-Music is a telegram bot project that's allow you to play music on telegram voice chat group

Wahyusaputra 1 Dec 22, 2021
Okaeri-Music is a telegram music bot project, allow you to play music on voice chat group telegram.

??️ PROJECT MUSIC,THIS IS MAINTAINED Okaeri-Music is a telegram bot project that's allow you to play music on telegram voice chat group Features ?? Th

Okaeri-Project 2 Dec 23, 2021
python script for getting mp3 files from yaoutube playlist

mp3-from-youtube-playlist python script for getting mp3 files from youtube playlist. Do your non-tech brown relatives ask you for downloading music fr

Shuhan Mirza 7 Oct 19, 2022
A python program to cut longer MP3 files (i.e. recordings of several songs) into the individual tracks.

I'm writing a python script to cut longer MP3 files (i.e. recordings of several songs) into the individual tracks called ReCut. So far there are two

Dönerspiess 1 Oct 27, 2021
Code to work with wave files!

Code to work with wave files!

Mohammad Dori 3 Jul 15, 2022
An app made in Python using the PyTube and Tkinter libraries to download videos and MP3 audio.

yt-dl (GUI Edition) An app made in Python using the PyTube and Tkinter libraries to download videos and MP3 audio. How do I download this? Windows: Fi

null 1 Oct 23, 2021
Improved Python UI to convert Youtube URL to .mp3 file.

YT-MP3 Improved Python UI to convert Youtube URL to .mp3 file. How to use? Just run python3 main.py Enter the URL of the video Enter the PATH of where

null 8 Jun 19, 2022
A python script that can play .mp3 URLs upon the ringing or motion detection of a Ring doorbell. The sound plays through Sonos speakers.

Ring x Sonos A python script that plays .mp3 files whenever a doorbell is rung or a doorbell detects motion. Features Music! Authors @braden Running T

braden 0 Nov 12, 2021
Hide Your Secret Message in any Wave Audio File.

HiddenWave Embedding secret messages in wave audio file What is HiddenWave Hiddenwave is a python based program for simple audio steganography. You ca

TechChip 99 Dec 28, 2022
Extract the songs from your osu! libary into proper mp3 form, complete with metadata and album art!

osu-Extract Extract the songs from your osu! libary into proper mp3 form, complete with metadata and album art! Requirements python3 mutagen pillow Us

William Carter 2 Mar 9, 2022
A small project where I identify notes and key harmonies in a piece of music and use them further to recreate and generate the same piece of music through Python

A small project where I identify notes and key harmonies in a piece of music and use them further to recreate and generate the same piece of music through Python

null 5 Oct 7, 2022
We built this fully functioning Music player in Python. The music player allows you to play/pause and switch to different songs easily.

We built this fully functioning Music player in Python. The music player allows you to play/pause and switch to different songs easily.

null 1 Nov 19, 2021