我有一堆 MP3 文件(几百个),其中嵌入了歌词。在 iPod touch 上播放这些文件时,或在打开字幕的 Windows Media Player 中播放时,会显示这些歌词。
我想做的是以某种方式将这些 MP3 文件中的歌词数据批量导出到纯文本文件中。我知道我可以在 Windows Media Player 中打开标签编辑器,然后手动将数据复制粘贴到记事本中,但这样做数百次会非常繁琐。有没有什么想法可以轻松地批量完成此操作?
答案1
MP3标签是目前 Windows 上最好的 MP3 标签编辑器之一。由于歌词存储在文件的 ID3 标签中,因此您可以使用此软件将数据导出到文本文件。
答案2
这是一个混乱的 zsh 解决方案,对我而言,它适用于超过 50,000 首歌曲,其中一些是 mp3,一些是 ogg,大约 1000 首嵌入了歌词。
#!/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