如何从 MP3 文件中批量提取 ID3 歌词元数据?

如何从 MP3 文件中批量提取 ID3 歌词元数据?

我有一堆 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

相关内容