I’ve looked around the web for an automated way of getting lyrics for the songs in my iTunes library. There are some widgets and some programs fetching lyrics, but they all seem to just do the currently playing song. I wanted something to take care of all my songs at once, so I whipped together a little Ruby script to do the work. This is an updated version with more error checking and verbosity.
Note: This works only for OSX, the Windows guys want to check out bep’s great script instead.
The script works thanks to the magnificent ruby gem rb-appscript , which takes care of the bindings to iTunes, and also the soap api at lyricwiki.org.
How to make the script run (thanks to KDN):
Here’s the script:
require 'rubygems'
require 'appscript'
require 'soap/wsdlDriver'
include Appscript
begin
driver = SOAP::WSDLDriverFactory.new("http://lyricwiki.org/server.php?wsdl").create_rpc_driver
rescue
raise "Could not connect to LyricWiki"
end
it = app('iTunes')
skipped = updated = errors = missing = 0
it.selection.get.each do |track|
song = "%s - %s" % [track.artist.get, track.name.get]
if track.lyrics.get == :missing_value
puts "Skipped, not a song: %s" % song
skipped += 1
next
end
unless track.lyrics.get == "Not found" or track.lyrics.get.empty?
puts "Skipped, already has lyrics: %s" % song
skipped += 1
next
end
begin
lyrics = driver.getSong(track.artist.get,track.name.get).lyrics
rescue
puts "Lookup error: %s" % song
puts "Error message: %s" % $!
errors += 1
next
end
if lyrics == "Not found"
puts "Found nothing for: %s" % song
missing += 1
next
end
begin
track.lyrics.set(lyrics)
track.refresh
rescue
puts "Error, could not set lyrics for: %s" % song
error +=1
next
end
puts "Updated: %s" % song
updated += 1
end
puts
puts "Summary"
puts "-------"
puts "Skipped: %i" % skipped
puts "Errors: %i" % errors
puts "Missing: %i" % missing
puts "Updated: %i" % updated
The script still has some issues with encoding, much of it is due to a variety of encodings used on the LyricWiki site, but I’ll try to find a fix sometime today or tomorrow.
As before: Feel free to alter and improve the program, and if you have suggestions I’d love to hear them. Also: If you find it useful I’d be very grateful if you said so in the comments.
Great improvement.
But I do not understand:
track.lyrics.get == :missing_value
If the OSX interface is anything like the Windows one, this one would create an exception in some cases, not?
This is awesome! Thanks for sharing the script.
Beautiful!! Thanks so much!
Quick tip for power users (because I'm not going to give a mini-CLI tutorial here) that helped me:
1. Move lyrics.rb to your home directory or other place where it's not likely to be in the way or accidentally deleted.
2. In Terminal, use pico or your editor of choice to add this line to your .tcshrc file (or similar if you're using a different default shell):
alias lyrics ruby ~/lyrics.rb
Make sure the last string points to the actual path where you put lyrics.rb.
3. Close the Terminal window and open a new one so the alias takes effect. Alternatively, it's jut as easy to type this at the command prompt:
source ~/.tcshrc
After doing the above, you can simply type 'lyrics' (no quotes) at the command prompt whenever you want to run the script.
Fantastic script!
If you add a Ruby shebang as line1, and set the permissions of the file to executable, people can execute this without needing to say "ruby lyrics.rb", just "lyrics.rb"
#!/usr/bin/env ruby -wKU
Also, if people add the folder containing this (and other unix scripts) to their path, they don't need to be in the script's container to execute it. So…
in the terminal, say:
pico .profile
and ensure that the line beginning "export PATH=$PATH:"
contains the path to the folder where you have placed the script.
/Users/tim/Applications/bin/
Useful tricks, thanks!
Thanks for the feedback, and for the great tip. Very useful for people who want to run this script regularly!
You're welcome :)
No, actually in my tests, all files missing the lyrics property will be skipped. I've tested with both radio stations and audio and video podcasts. It looks like the Windows api is somewhat different from the OSX one, something that shouldn't be too surprising… I'm sure you know this already, but :missing_value is just a ruby symbol, one that the api returns whenever it can't get the lyrics for a media file.
This doesn't work, I just come up with this error when I try running the script: lyrics.rb:9: syntax error, unexpected tCONSTANT, expecting ')' raise "Could not connect to LyricWiki" ^ lyrics.rb:19: syntax error, unexpected tCONSTANT, expecting kEND puts "Skipped, not a song: %s" % song ^ lyrics.rb:19: syntax error, unexpected ':', expecting kEND puts "Skipped, not a song: %s" % song ^ lyrics.rb:23: syntax error, unexpected tCONSTANT, expecting kEND unless track.lyrics.get == "Not found" or track.lyrics.get.empty? ^ lyrics.rb:24: syntax error, unexpected tCONSTANT, expecting kEND puts "Skipped, already has lyrics: %s" % song ^ lyrics.rb:24: syntax error, unexpected tIDENTIFIER, expecting kDO or '{' or '(' puts "Skipped, already has lyrics: %s" % song ^ lyrics.rb:31: syntax error, unexpected tCONSTANT, expecting kEND puts "Lookup error: %s" % song ^ lyrics.rb:32: syntax error, unexpected tCONSTANT, expecting kEND puts "Error message: %s" % $! ^ lyrics.rb:36: syntax error, unexpected tCONSTANT, expecting kEND if lyrics == "Not found" ^ lyrics.rb:37: syntax error, unexpected tCONSTANT, expecting kEND puts "Found nothing for: %s" % song ^ lyrics.rb:37: syntax error, unexpected ':' puts "Found nothing for: %s" % song ^ lyrics.rb:45: syntax error, unexpected tCONSTANT, expecting kEND puts "Error, could not set lyrics for: %s" % song ^ lyrics.rb:45: syntax error, unexpected kNOT, expecting '=' puts "Error, could not set lyrics for: %s" % song ^ lyrics.rb:45: syntax error, unexpected ':' puts "Error, could not set lyrics for: %s" % song ^ lyrics.rb:49: syntax error, unexpected tCONSTANT, expecting kEND puts "Updated: %s" % song ^ lyrics.rb:54: syntax error, unexpected tCONSTANT, expecting kEND puts "Summary" ^ lyrics.rb:56: syntax error, unexpected tCONSTANT, expecting kEND puts "Skipped: %i" % skipped ^ lyrics.rb:56: unknown type of %string puts "Skipped: %i" % skipped ^ I am pretty certain i followed all of the directions; I installed darwinports and rubygems, and I installed rb-appscript correctly, I think… (I'm pretty sure I did install these correctly, but I may not have. Can you possibly help?) I then copied and pasted the code you gave me in the black box into a new Xcode file, saved as .rb. When I run the file, this is the error I get. What's wrong, and how do I fix it? Please contact me at my email, or in this comment. Thanks, Iambob
If you have the error: "Could not connect to LyricWiki" you have to replace "http://lyricwiki.org/server.php?wsdl" in the script with "http://lyrics.wikia.com/server.php?wsdl". The Web service was moved to another adress :-)