Skip to content

Instantly share code, notes, and snippets.

@vadyua
Last active March 20, 2016 19:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vadyua/2ea3bee17b039331a392 to your computer and use it in GitHub Desktop.
Save vadyua/2ea3bee17b039331a392 to your computer and use it in GitHub Desktop.
<#
----------------
Powershell script to search and update lyrics for MP3 Id3v2 tags | ©2016 by (v)
----------------
Uses Library: http://download.banshee.fm/taglib-sharp/2.1.0.0/taglib-sharp-2.1.0.0-windows.zip
Id3v2 Tag: USLT (Id3v2::UnsynchronizedLyricsFrame)
Cmd to Use: .\simple-mp3-lyrics-parser.ps1 C:\mp3s 0
#>
Param (
[Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true,HelpMessage="Provide a full path to files")]
[alias("p")]
[System.String]$path,
[Parameter(Position=1,ValueFromPipeline=$true)]
[alias("t")]
[int]$tofile = 1,
[Parameter(Position=2,ValueFromPipeline=$true)]
[alias("a")]
[int]$altservers = 1
)
# TODO: Replace-Diacritics http://stackoverflow.com/a/7840951
function FindMetroLyrics ([System.String]$artist, [System.String]$title) {
$request = $title.ToLower()+'-lyrics-'+($artist.ToLower() -replace "^the\s?") -replace '[^a-z0-9 -]+','' -replace "[ ]+",'-' -replace "[-]{2,}",'-'
$wc = New-Object System.Net.WebClient
$wc.Headers.Add("User-Agent", "Opera/9.80 (Windows NT 6.1) Presto/2.12.388 Version/12.18")
try {
$data = $wc.DownloadString("http://www.metrolyrics.com/{0}.html" -f $request)
} catch [System.Net.WebException] {
#Write-Host $_.Exception.ToString()
}
$words = ([regex]::Matches($data -Split "`n", '<div id="lyrics-body-text" class="js-lyric-text">.*<div class="lyrics-bottom">') | %{$_.value})
if($words) {
$words = $words -replace '<div id="lyrics-body-text"[^>]*>' -replace '</div> </div>' -replace '<div[^>]+>.*</div>' -replace "<br[^>]?>","`r`n" -replace "</p>","`r`n`r`n" -replace "<.*?>" -replace '[\s\r\n]+$','' -split '\r\n' -replace '(^\s+|\s+$)' | out-string #-replace '(?m)(^\s+|\s+$)'
return [System.Web.HttpUtility]::HtmlDecode($words)
} else {
Write-Host " 2. MetroLyrics: Not Found!"
}
}
function FindLyricWiki ([System.String]$artist, [System.String]$title) {
$request = 'http://lyrics.wikia.com/wiki/{0}:{1}' -f (LyricWikiCase $artist), (LyricWikiCase $title)
$wc = New-Object System.Net.WebClient
try {
$data = $wc.DownloadString($request)
} catch [System.Net.WebException] {
#Write-Host $_.Exception.ToString()
}
$words = ([regex]::Matches($data, "<div class='lyricbox'>.*<!--") | %{$_.value}) # <div class='lyricsbreak'></div>
if($words) {
$words = $words -replace '<!--.*' -replace "<div class='lyricbox'>.*</script>" -replace "<br[^>]*>","`r`n"
return [System.Web.HttpUtility]::HtmlDecode($words) -replace "<.*?>"
} else {
Write-Host " 1. LyricWiki: Not Found!"
}
}
# Return a string in LyricWiki case. Substitutions are performed as described at <http://lyrics.wikia.com/LyricWiki:Page_Names>
function LyricWikiCase {
param(
[string]$s = [String]::Empty
)
$s = ([System.Threading.Thread]::CurrentThread.CurrentCulture.TextInfo).ToTitleCase($s -replace '[:/]+') -replace "\s+",'_' -replace '<','Less_Than' -replace '>','Greater_Than' -replace '#','Number_' -replace '(\[|\{)+','(' -replace '(\]|\})+',')' -replace '[«»]+','"' -replace '[\|¦]+','/' -replace "¶",'P'
return [System.Web.HttpUtility]::UrlEncode($s)
}
Add-Type -AssemblyName System.Web
# CHANGE PATH!
[Reflection.Assembly]::LoadFrom("C:\..path_to..\taglib-sharp-2.1.0.0\taglib-sharp.dll") | Out-Null
[TagLib.Id3v2.Tag]::Language = 'eng'
[TagLib.Id3v2.Tag]::DefaultEncoding = 'UTF16' #[System.Text.Encoding]::Unicode
# Loop thought MP3's
Get-ChildItem -LiteralPath $path -Recurse -Force -Filter "*.mp3" | %{
$m = [TagLib.File]::Create($_.Fullname)
if(!$m.Tag.Lyrics) {
$d = ($m.Properties.Duration -replace "\.[0-9]+",' ')+$m.Properties.AudioBitrate +'k/'+ $m.Properties.AudioSampleRate
if($m.Tag.AlbumArtists -ne $m.Tag.Performers) {
$aa = [string]$m.Tag.AlbumArtists +'/'
} else {
$aa = ''
}
Write-Host ("+ Find Missing Lyrics for: {0} > {1}{2} - {3} - {4} ({5}) {6}" -f $_.Fullname, $aa, $m.Tag.FirstArtist, $m.Tag.Title, $m.Tag.Album, $m.Tag.Year, $d) -ForegroundColor "DarkGray"
# Find LyricsWiki
$result = FindLyricWiki $m.Tag.FirstArtist $m.Tag.Title
if(!$result -and $altservers -eq 1) {
# Find metrolyrics.com overwise
$result = FindMetroLyrics $m.Tag.FirstArtist $m.Tag.Title
}
# Process only if no blank results
if($result -and $result -notmatch "^[\s\r\n]+$") {
Write-Host " -OK--- Updating Lyrics:" -ForegroundColor "Green"
if($tofile -eq 1) {
[IO.File]::WriteAllLines(($_.Fullname -replace 'mp3$','txt'), $result) # UTF8 w/BOM $result | Out-file -Encoding "UTF8"
}
$m.Tag.Lyrics = [string] $result
$m.Save()
} else {
Write-Host " -><--- Not found any Lyrics!" -ForegroundColor "Red"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment