2

I have a bunch of MP3 files (a few hundred) that have embedded lyrics. These lyrics show up when the files are played on an iPod touch, or in Windows Media Player with captions turned on.

What I'd like to do is somehow batch-export the lyrics data from these MP3 files into plain text files. I know I can open the tag editor in Windows Media Player and manually copy-and-paste the data into notepad, but doing that hundreds of times would be very tedious. Any idea how this could be easily done in batch?

2 Answers2

2

MP3Tag is one of the best MP3 tag editors available for Windows currently. Since lyrics are stored in the file's ID3 tags, you can use this software to export out the data to a text file.

alt text

Gareth
  • 19,080
caliban
  • 20,411
1

Here's a messy zsh solution, which worked for me on >50,000 songs, where some are mp3 and some are ogg, and about 1000 have embedded lyrics.

#!/usr/bin/zsh
## Extract lyrics from mp3/ogg tags to txt files (suitable for plex media server)
# I couldn't find a tool that worked on both mp3 and ogg, so there are two script sections.  Best to run them one at a time
# Both have a commentedout line which actually writes the file.  Best to test the scripts on a few different albums before you make a mess of your filesystem
# Both output as follows:
# If there is no lyrics tag, there is no output
# if there is a lyrics tag but it is empty (or almost empty), the output is like this - filename, 0 characters found, and an empty line
#Music/David Rovics/Big Red Sessions/10 - Song for Mavi Mamara.txt
#0
#
# if there are lyrics, the output is like this - filename, large number of characters found, and the complete lyrics as they will be written 
#Music/David Rovics/All the News Thats Fit to Sing/16. Sachin.txt
#1421
#Norway is known for many things  One of them most surely is not Cricket
#When Norway plays international matches
#They often end up in a sticky wicket
#But VĂ¥lerenga was once one of Norway's best teams
#Until it became one of the worst
#Eighteen games played, sixteen lost  It seemed that the team was cursed
#But the men of VĂ¥lerenga have come up with a plan
#And now the course is clear
#Our hope lies now in convincing Sachin  That he should fly up here...
#
#
# first section does mp3s, requires eyeD3 : https://eyed3.readthedocs.io/en/latest/
# the eyeD3 plugin which allows you to extract a single tag was removed in 2022
# my messy workaround is to search for the three tags most likely to follow a "Lyrics" tag and ignore the output from there on.
for file in Music/**/*mp3(.); do 
if (eyeD3 $file| grep -s -q Lyrics); then 
    lyrics=$(eyeD3 $file| grep -A999 Lyrics|grep -v FRONT_COVER|grep -v 'Description: cover' |tail -n +2)
    if (echo $lyrics| grep -s -q 'UserTextFrame:'); then 
    lyrics=$(echo $lyrics | head -n+$(echo $lyrics|grep -m1 -n -h UserTextFrame|cut -d: -f1))
    fi
    if (echo $lyrics| grep -s -q 'OTHER Image:'); then 
    lyrics=$(echo $lyrics | head -n+$(echo $lyrics|grep -m1 -n -h 'OTHER Image:'|cut -d: -f1))
    fi
    if (echo $lyrics| grep -s -q 'Description:'); then 
    lyrics=$(echo $lyrics | head -n+$(echo $lyrics|grep -m1 -n -h 'Description:'|cut -d: -f1))
    fi
    lyrics=$(echo $lyrics|head -n-1)
    echo ${file//mp3/txt}  # file name of text file to write lyrics to
    echo ${#lyrics}  # number of characters in the lyric tag (if its only one or two characters we ignore it)
    echo $lyrics  # the lyrics which will be written to the file
    ## if you've tested this on at least a sample of your library, uncomment the next line to write the files
    # (( ${#lyrics} > 3 )) && echo $lyrics > ${file//mp3/txt}; 
fi; 
done

second section does oggs, requires tagutil https://github.com/kaworu/tagutil

tagutil can read ogg tags and some mp3 tags.. but not the mp3 lyric tag,

again there is no way to extract a single tag. In my collection the most likely tag to follow the lyrics was either "album artist" or "originaldate"

for file in Music/*/ogg(.); do if (tagutil $file| grep -q lyrics); then lyrics=$(tagutil $file|grep -A999 lyrics) if [[ "$(echo $lyrics)" == "album artist" ]]; then lyrics=$(echo $lyrics | head -n+$(echo $lyrics|grep -m1 -n -h "album artist"|cut -d: -f1)|head -n-1); elif [[ "$(echo $lyrics)" == "originaldate" ]]; then lyrics=$(echo $lyrics | head -n+$(echo $lyrics|grep -m1 -n -h originaldate|cut -d: -f1)|head -n-1); else lyrics=${$(tagutil $file|grep -A999 lyrics)//unsyncedlyrics:/}; # if the lyrics are the last tag, this output deals with carriage returns better fi lyrics=${lyrics//- lyrics:/} echo ${file//ogg/txt}; # file name of text file to write lyrics to echo ${#lyrics} # number of characters in the lyric tag (if its only one or two characters we ignore it) echo $lyrics # the lyrics which will be written to the file ## if you've tested this on at least a sample of your library, uncomment the next line to write the files # (( ${#lyrics} > 3 )) && echo $lyrics > ${file//ogg/txt}; fi; done