Capture Track Info
SUCCESS!!! In a prior post I talked about re-discovering Internet streaming radio. I am enjoying listening to TheEL.US and I love their variety of Rock, Blues, and Metal. Their library spans decades and they play stuff you’d never hear on a corporate station.
What does this have to do with code & scripting?
Well, I use the mpv CLI tool to stream the station from a terminal. Each time the song (track) changes I get a message with the artist / title. I decided I wanted to start capturing the song info, as it’s played, to review later and get ideas for music to purchase.
I could have done a clunky, but workable, bash shell script capturing output from redirection off the command line. However, I would have to do a lot of parsing and formatting. I knew there were better, more efficient ways…
mpv has a built-in API that works with C, Lua and other languages. What I wanted was just a simple capture of tags (also called properties). I decided a full C program was overkill and too much overhead since I wasn’t doing anything other than capturing an artist name and song title. mpv also has a simple mechanism to load and run scripts while it is running. This is where Lua comes in.
I have no experience with Lua other than seeing it used as a configuration language for some other Linux/Unix tools. The syntax is similar to many other languages, so I figured I could hack something out. I started with an example script I found on GitHub.
function on_pause_change(name, value)
if value == true then
file = io.open("/directory/to/store/titles.txt", "a")
file:write(mp.get_property("media-title"),"\n")
file:close()
end
end
mp.observe_property("pause", "bool", on_pause_change)
--local msg = require 'mp.msg'
--local utils = require 'mp.utils'
function dump_info()
file = io.open("/directory/to/store/titles.txt", "a")
file:write(mp.get_property("media-title"), "\n")
file:close()
end
mp.add_key_binding("n", "dump_2_txt", dump_info)
--key binding letter n on keyboard
This code will write the media-title property to a file of your choosing, anytime the mpv stream is paused or when the user presses the ’n’ key.
That’s a great start, and works well. However, it requires manual intervention for every song you wish to capture. I wanted something that would capture everything while the stream is paying. This way, if I needed to walk away from the computer or was busy with another task, the info would be captured without having to press a key. So I started trying to write my own little script that would do what I needed, and would be automatic.
It took me longer than it should have, but without a clear understanding of Lua or the mpv API, I was sort of flying blind. After several mistakes and trying to decipher error messages I was unfamiliar with, I studied a little more of the Lua basics and was able to debug and troubleshoot my code. I came up with a workable solution in a handful of lines of code. I should go back and add some comments, especially around why I chose the if/then logic I did. There are more efficient ways to write this, but it will do for now.
function on_track_change(name, value)
local startmsg
if value ~= nil then
if value == "a71722" then
startmsg = "Start of stream for "..value.." "os.date("%x")
print("value of startmsg", startmsg)
else
file = io.open("/directory/to/store/tracks.txt", "a")
file:write(value,"\n")
file:close()
end
end
-- file = io.open("/directory/to/store/tracks.txt", "a")
-- file:write(value,"\n")
-- file:close()
end
mp.observe_property("media-title", "string", on_track_change)
Basically, when I start the mpv stream, the first two instances of the property are a nil value as it starts, and then the stream identifier for TheEL.US (a71722). After that, each value will be a track title of the format:
Seether - Fine Again
The mp.observe_property does all the hard work of identifying when the track changes, and then calls the on_track_change function. The function just validates the value of the string, and if valid writes it to the file. I can then use the file for any purpose I need.
It’s been a fun (sometimes frustrating) learning process, and I enjoy combining various tools to solve little problems or tasks I need done.
Caveat :: This is not a full tutorial as I have left out various details and descriptions of mpv, Lua, etc. I will add that if writing a script for mpv, it should be stored in the user’s home folder under the .config/mpv/scripts directory.