Metadata push guide

In this article

Spinitron can send messages to remote systems over the Internet using a variety of protocols and message formats. The feature is designed to update now-playing displays by sending a message when a new song starts playing, or as close to as possible. It’s most often used to send to stream servers to update the embedded song metadata, RDS and HD Radio Program Info encoders, to TuneIn and to Twitter. It is used also for a variety of other custom applications such as web integration and mobile apps.

Metadata push is a different kind of technology from the Spinitron API. In the API, the remote system is the client and it requests (pulls) data from the server (Spinitron) when it chooses. In metadata push, Spinitron behaves as a client and it chooses when to send (push) out a message. The remote system behaves as a server and stands ready to receive a message from Spinitron at any time. Another difference is that metadata push is not reliable because Spinitron doesn’t push if spins are entered a long time after their timestamp.

MetaRadio

This metadata push feature has a number of limitations. MetaRadio is an alternative commercial software solution from Media Realm. It has many more and different features. See this forum topic and Media Realm’s MetaRadio/Spinitron web page.

Metadata push channels

You can set up a number of push channels in Spinitron, for example you might configure one channel for each stream, one for RDS, one for TuneIn, and one for Twitter.

Channel settings

  • Name - Any name meaningful to you that helps identify the channels in a list.
  • Template - A specially encoded string that specifies to Spinitron how it should format a push message and send it out over the network. This is the most critical part and it can be confusing. It is described in detail below.
  • Default duration - If Spinitron doesn’t know a spin’s actual duration, it assumes this many seconds.
  • Max duration - Spinitron won’t push a spin more than this many seconds after its timestamp.
  • Username and password - strings that can be encoded into the message using the %un% and %pw% tags. These are not required and you often don’t need them.
  • Enabled checkbox - allows you to disable a channel without deleting it.

The timing of push messages depends on the timestamp of the spin and on when the Spin is entered into Spinitron’s database. Default and max duration are used in the algorithm. See Metadata push: Default and Max Duration for full details.

Username and password form fields

DO NOT USE Username or Password if you don’t really need to. ONLY USE these fields to encode username or password in a URL, i.e. if you are using %un% and %pw% and you want Spinitron to URL-encoded your user name and password strings.

DO NOT set your Twitter login here.

The username and password fields of the push channel form set the value of the %un% and %pw% template tokens respectively. The token values are URL-encoded. For example, if you enter p@$5w0&D for password then %pw% will have the value p%40%245w0%26D.

Template specification

Templates are like URLs but with tokens (tags) for variable substitution. For most uses of metadata push there is a general form for the template that you can adapt to your situation. They are for

  • Icecast and SHOUTcast stream servers
  • TuneIn
  • Twitter
  • RDS and HD Radio Program Info

For more specialized applications Spinitron provides a flexible template editor allowing you access to a variety of protocols.

In all cases you are free to design the message to send with push using the template variables.

Tags, tokens and variables

You design the text of the message to send using template variable substitution tokens or tags for short. A tag is a short code between a pair of percent character, e.g. %an% expands to the artist name and %sn% is for the song name. You can combine these with text of your own design, e.g. %sn% by %an%. In some contexts such as in a URL you may need to encode your text, for example a space in a URL is encoded as %20 or +, but you do not encode the tags.

Icecast v. SHOUTcast

SHOUTcast is proprietary software including Shoutcast server (SHOUTcast Distributed Network Audio Server or DNAS). Shoutcast defined a network protocol for streaming audio and video over HTTP that won the streaming audio war of the early 00s. Most stations using Spinitron stream with the Shoutcast protocol using either Shoutcast or Icecast software.

Shoutcast server is available for download if you register an account. It is used by some streaming service providers. It is not open source software and the free version has a number of features limited or disabled. In Jan 2019 it is at version 2.6 but version 1.9.8 (2007) is still used because of the differences between SHOUTcast 1 and 2.

Icecast is a free, open-source server. It is compatible with most Shoutcast sources and clients. It is an open-source alternative to Shoutcast server.

Configuration of Icecast is different from that of Shoutcast. There are also significant differences between Shoutcast 1 and 2.

Icecast

Metadata push to Icecast requires this information about your stream

  • HOST – the host name or IP address of the server, e.g. 203.0.113.12 or example.org
  • PORT – the port number the server runs on, a number usually in the thousands, e.g. 8000
  • MOUNTPOINT – An Icecast server can host multiple streams and each has a “mount point” to identify it. It starts with a slash character, e.g. /live
  • USER – user name, usually the admin user name
  • PASS – password corresponding to the user name

HOST and PORT are part of the stream URL. MOUNTPOINT is often in the URL too. For example, if the stream URL were

  • http://203.0.113.12:8000/live

then

  • HOST = 203.0.113.12
  • PORT = 8000
  • MOUNTPOINT = /live

Icecast servers usually have a management web page. The URL is the same as the stream but with status.xsl instead of the MOUNTPOINT, e.g. http://203.0.113.12:8000/status.xsl. The page lists all the server’ mount points. For example this server has one mount point named /foo.

Icecast management page

The user name and password is usually the Icecast server’s admin user name and password configured on the server. In the management page shown above, when you click the Administration link, it demands the admin user/pass, and if you can authenticate then the same user/pass will probably work for metadata push.

The general template for an Icecast metadata push channel

http://USER:PASS@HOST:PORT/admin/metadata?mount=MOUNTPOINT&mode=updinfo&song=%an%%20-%20%sn%

For example

http://admin:hackme@203.0.113.12:8000/admin/metadata?mount=/foo&mode=updinfo&song=%an%%20-%20%sn%

Do not use the username or password fields of the push channel form.

Note the mount param includes the slash / character.

Change the song parameter to whatever you need using Spinitron’s Template variable substitution tokens.

SHOUTcast

Metadata push to Shoutcast is similar to Icecast. You need to know HOST, PORT, and PASS for the stream (see the Icecast section above) but not USER or MOUNT.

If you visit http://HOST:PORT/index.html (e.g. http://209.222.145.148:8000/index.html) then you should see an management page with information about the stream and a link to log in as admin. In Shoutcast 1.9.8 the link is Admin Login and in 2.6 it is Server Login. It demands authentication. The username is admin and the password you need for PASS in push is the same as the one that works for admin login.

The general template for a SHOUTcast server is

http://HOST:PORT/admin.cgi?mode=updinfo&pass=PASS&song=%an%%20-%20%sn%

For example

http://203.0.113.12:8000/admin.cgi?mode=updinfo&pass=%pw%&song=%an%%20-%20%sn%

Enter PASS in the password field of the push channel form.

You can change the song parameter to whatever you need using Spinitron’s Template variable substitution tokens.

You can also set a url parameter to set the StreamUrl stream metadata. It must be URL-encoded, for example

http://203.0.113.12:8000/admin.cgi?mode=updinfo&pass=%pw%&song=%an%%20-%20%dn%&url=http%3A%2F%2Fspinitron.com%2FWZBC%2F

With Shoutcast 1.9.8 use %20 for spaces in the song param. In Shoutcast 2.6 or Icecast + also works.

TuneIn

Spinitron can push to TuneIn’s AIR API.

To push to TineIn, you need

  • STREAMID - Your TuneIn stream ID, the letter s followed by some digits, e.g. s24321
  • PARTNERID - AIR API user ID
  • PARTNERKEY - AIR API key

Your stream ID is in the URL for your stream’s page in TuneIn. For example, WZBC’s page in TuneIn is

https://tunein.com/radio/WZBC-903-s24321/

And their stream ID is s24321.

If you don’t yet have an ID and key to access the AIR API then email broadcaster-support@tunein.com to request access, identifying your station and mentioning that you use Spinitron.

The push channel template is

http://air.radiotime.com/Playing.ashx?partnerId=PARTNERID&partnerKey=PARTNERKEY&id=STREAMID&title=%sn%&artist=%an%&album=%dn%

Twitter

First you have to connect Spinitron with Twitter, which means telling Twitter that you grant Spinitron permission to send status updates to your Twitter account. While logged in to Spinitron as an admin, navigate to Admin▸Station Settings▸Integrations. In the Twitter box it will say if your station is already connected. To connect (or reconnect) Spinitron to Twitter, click the bird button and follow the instructions.

Then in set up a metadata push channel with something like

twitter:%an% - %sn%

Change the part after the colon to whatever you need using Spinitron’s Template variable substitution tokens. You can include URLs.

You may prefer to dedicate one Twitter account exclusively to Now Playing updates rather than mixing it with your general social media statuses.

RDS and HD Radio Program Information

To push a display text update to an RDS or HD Radio encoder, you need to send a message using the exact protocol and format that your equipment expects. Find the make and model of your equipment and try to find its documentation too. It may take some trial-and-error to get the settings right.

Some encoders expect a text command sent over UDP or over a TCP connection. In this case you need to know

  • PROTOCOL - Either udp or tcp.
  • HOST - The host name or IP address of the encoder, e.g. 203.0.113.12 or rds1.example.org
  • PORT - The port number of the encoder, a number usually in the thousands, e.g. 9000
  • COMMAND - The commands that precedes a display text update

The commands we have seen most often are DPS and TEXT but there are several others, it all depends on your specific equipment.

Assuming you want to send both a DPS and a TEXT command, the template might be for example

udp://203.0.113.12:9000
TEXT=%an% - %sn%
DPS=%an% - %sn%

Change the text to whatever you need using Spinitron’s Template variable substitution tokens.

NOTE: There needs to be a newline after each command, including after the last one. Be sure to include that. Some users have found that putting X on a line by itself after the last command can force Spinitron to send a newline but this may not be needed.

Network connectivity and security for RDS

RDS encoders and similar broadcast equipment network interfaces present some networking and security concerns:

  • They are usually not reachable from the Internet.
  • They usually don’t use secure protocols.
  • Their network interfaces are not usually hardened, typically not even with a password.
  • If you can access the command to update the text, you can probably access any command and can therefore take complete control of the device.

Such equipment is designed to be attached only to a secure private LAN and that’s usually how they are deployed, i.e. behind firewalls.

For Spinitron to be able to send the commands that update RDS or HD Radio Program Info texts, you must

  • open a pinhole in the firewall(s)
  • trust Spinitron to not send anything dangerous through the pinhole
  • trust that Spinitron won’t be hacked to launch attacks on your system
  • trust that an attacker won’t spoof being Spinitron to attack your system

It’s up to you to model and assess the risks.

Secure reverse proxy for RDS encoders and similar equipment

As an alternative to opening a pinhole in your firewall(s), you may be able to set up a custom secure reverse proxy. For example, if you have a web server in the Internet running on a computer that has an interface to your private LAN over which it can reach the RDS encoder, then you could write a script (e.g. PHP, Python, Perl etc.) that runs on the web server to function as reverse proxy. The reverse proxy script accepts HTTPS requests from Spinitron, authenticates the client’s shared secret, accepts a text message (e.g. in a query parameter), runs some checks and if all is OK sends a command to the RDS encoder. For more ideas, review this skeleton example written in PHP.



General template specifications

Templates are structured like URLs with these parts:

  1. protocol part
  2. optional authentication part (username, password) for HTTP and FTP protocols
  3. host part (except for twitter)
  4. URI path part for HTTP and FTP protocols
  5. message data part

Editor

Spinitron’s channel specification form allows you to compose the template and preview it either with the variable tokens or with example data substituted into the variables.

Escape sequences for special characters into the template

  • \r for the CARRIAGE RETURN (CR) control character ASCII 13, U+000D
  • \n for the LINE FEED (LF) control character ASCII 10, U+000A
  • \t for TAB control character ASCII 9, U+0009
  • \x00…\x1F for the control characters ASCII 0…31, U+0000…U+001F
  • \x7F for the DELETE (DEL) control character ASCII 127, U+007F

For everything else, enter characters directly as in any other app that supports Unicode. Spinitron usually encodes characters outside the ASCII range in UTF-8 for transmission.

In the preview

  • substitution tokens (tags) and example substituted values are red
  • control characters are teal in color and
    • SPACE is represented by the OPEN BOX U+2423 character ␣
    • TAB is represented by the RIGHTWARDS ARROW TO BAR U+2423 character ⇥
    • Other control characters \x00…\x08, \x09…\x1F and \x7F are represented by control pictures, e.g. ␀ ␊ ␍ ␥
  • a line break follows LF, a CRLF sequence, and CR, this is just for display in the preview and does not imply Spinitron transmits an extra newline.

The following contrived example demonstrates most of these editor features.

  • Messages are sent with UDP to port 9000 on the host 203.0.113.12.
  • A TEXT= command is the first line of the message, terminated by CRLF.
  • Its argument is the spin’s artist name and song name separated by SPACE EM-DASH SPACE, followed a TAB and a ❤️ red heart emoji.
  • (Note: It’s not shown in the editor but, thanks to UTF-8 encoding, the EM-DASH is sent on the network as E2 80 94 and the red heart as E2 9D A4 EF.)
  • A DPS= command is the next line of the message and it is terminated by a CR.
  • Its argument is the ANSI term control escape sequence for foreground color green, SPACE, artist name and song name separated by RECORD SEPARATOR
  • After the DPS line comes EOT ending the datagram body.

Protocols

Metadata push provides the following protocols with these protocol tags

  • twitter: - Send to Twitter using their API
  • http:// - HTTP GET request
  • https:// - Secure HTTP GET request
  • POST http:// - HTTP POST request with application/x-www-form-urlencoded body
  • POST https:// - Secure HTTP POST request with application/x-www-form-urlencoded body
  • FILE http:// - HTTP POST request with multipart/form-data body for file upload
  • FILE https:// - Secure HTTP POST request with multipart/form-data body for file upload
  • ftp:// - Send a message as a file using FTP
  • ftps:// - Send a message as a file using FTP over SSL/TLS
  • tcp:// - Send a message over a raw TCP connection
  • udp:// - Send a message in a raw UDP datagram

Twitter

Begin the template with twitter: as protocol tag followed on the same line with your message template, e.g.

twitter:%an% - %sn%

Spinitron must be authorized to use Twitter for this to work. See above.

HTTP and HTTPS GET

Use the http:// or https:// protocol tag to form a URL, e.g.

https://example.org/form/path?artist=%an%&title=%sn%

Query parameters are sent in the request URL.

POST HTTP and HTTPS

Prefix a http:// or https:// URL with POST to send a post request with application/x-www-form-urlencoded data, e.g.

POST https://example.org/form/path?artist=%an%&title=%sn%

Would send a POST request with the URL https://example.org/form/path. Data in the query params are encoded into a form with fields artist and title.

(Relative to a GET request, the POST prefix moves data from the URL query params into a form, so to speak.)

FILE HTTP and HTTPS

Prefix a http:// or https:// URL with FILE to send a post request with multipart/form-data body. On the lines following the URL put a template message to send as a file upload, e.g.

FILE https://example.org/form/path?action=xmlupload&file=nowplaying.xml
<?xml version="1.0" encoding="utf-8" ?>
<nowplaying>
    <artist>%an%</artist>
    <title>%sn%</title>
    <album>%dn%</album>
</nowplaying>

FTP and FTPS

Form an FTP or FTPS URL as in the following example, followed by the template text of the message to send as a file upload.

ftp://%un%:%pw%@ftp.example.org/path/to/nowplaying.xml
<?xml version="1.0" encoding="utf-8" ?>
<nowplaying>
    <artist>%an%</artist>
    <title>%sn%</title>
    <album>%dn%</album>
</nowplaying>

TCP and UDP

Use protocol tags tcp:// or udp:// followed on the same line by HOST:PORT. Put the template text of the message to send on the following lines, e.g.

tcp://foo.example.org:54412
<?xml version="1.0" encoding="utf-8" ?>
<nowplaying>
    <artist>%an%</artist>
    <title>%sn%</title>
    <album>%dn%</album>
</nowplaying>


Template variable substitution tokens

The following template variables are used in Metadata Push and in Twitter link text.

Variable Description
%now% Current time in W3C format, e.g. 2010-04-15T13:42:32-05:00
%now[format]% Current time formatted using the PHP date() function, e.g. %now[g:ia]% is 1:42pm
%an% Artist
%sn% Song name
%sc% Song composer
%sp% Spin timestamp in W3C format, e.g. 2010-04-15T13:42:32-05:00
%sp\[format]% Spin timestamp formatted using the PHP date() function, e.g. %sp[g:ia]% is 1:42pm
%se% Spin note
%sd% Duration in seconds
%dur% Duration in M:SS format
%dn% Release (album) title
%df% Release medium (format) e.g. LP, CD
%dr% Release year
%da% Add date
%dl% Genre
%ne% New
%rq% Request
%lo% Local
%ua% Cover art URL
%ln% Label name (publiher)
%wn% Playlist title
%pi% Playlist ID
%si% Spin ID
%wc% Playlist category
%ww% Show weekdays, e.g. “Mon, Wed, Fri”
%wo% Playlist start time in HH:MM:SS format
%wf% Playlist end time in HH:MM:SS format
%ws% Playlist since (year)
%wd% Playlist description
%dj% DJ name
%st% Station title
%tpl% Playlist URL
%tdj% DJ page URL
%tsh% Show page URL (if any)
%tst% Station URL
%tsp% Spin URL


Default and Max Duration

Here we descrbe Spinitron’s timing of metadata push events and cancellation policy, in which the Default Duration and Max Duration configurations play their part.

Spinitron’s metadata push feature sends now-playing song updates to things such as stream servers, RDS encoders and the like. We assume that the receiver of a push message updates its display to users when it receives the message. So the timing of when Spinitron sends the message is important.

If Spinitron has advance knowledge of a spin, schedules the spin’s push messages at the spin’s timestamp. But if is told about the spin late, which can easily happen with manual playlist entry, then it will either push the message immediately, if the information is not too old, or not at all.

Spinitron’s rules for pushing spins

  • If the spin is in the future, push when it starts.
  • Push the spin immediately if it didn’t start too long ago and it has not already ended. MAX DURATION seconds would be too long. Use DEFAULT DURATION to figure if the spin has ended if we don’t have an explicit spin duration.
  • Otherwise cancel the push.

Choosing values

  • DEFAULT DURATION and MAX DURATION are configurations you assign on a per-channel basis. If you set them too small and a DJ is slow to enter spins into a manual playlist, they may not be pushed.
  • DEFAULT DURATION has no effect if the spin’s duration is set.
  • MAX DURATION is like a cutoff meaning: Don’t push if the spin is entered more than this many seconds late.
  • DEFAULT DURATION = 300 and MAX DURATION = 600 might be reasonable values.

Formal spec

In technical terms, with respect to a given spin, define

  • NOW is the moment Spinitron receives the spin
  • TIMESTAMP is the spin’s explicit timestamp.
  • DURATION is the spin’s explicit duration, if known, otherwise DEFAULT DURATION
  • AGE ≡ NOW - TIMESTAMP

Then, if AGE

  • ≤ 0 then schedule the push for TIMESTAMP,
  • ≥ DURATION then cancel the push,
  • ≥ MAX DURATION then cancel the push;

otherwise push immediately.

1 Like

Hi, I recently wrote a Nautel RDS text “injector” that accepts Spinitron Metadata Push data. I have tested it only with a Nautel VS2.5 using the “ASCII over IP” setting. It’s a simple PHP script based on Tom’s example from the Spinitron github gist. I adapted it to use the Nautel TCP port 7005. Comments in the script also show how to test it before pointing it to your transmitter. You can get the script in my gist.

Setting up a reverse proxy with authentication, and configuring firewall rules to limit the source IP addresses are left as exercises for the reader…

I’d love to see what other people have done in this area!

1 Like

Hi David @dklann

Thanks for sharing that!

It looks like your script has another function besides receiving from Spinitron metadata push, converting and sending to Nautel. And it looks like a web-based UI with a form that a person could use with a browser to type RDS text, click a submit button and send to the Nautel. Do I read that right?

Yes, exactly. It also has some “quickie” buttons with pre-programmed text for moments when there’s no content from Spinitron or elsewhere.

I am new to Spinitron - however I am developing an app that will allow a DJ to export a Spotify playlist into whatever format Spinitron will take. Can someone point me in the right direction maybe REST of CSV file etc… I would like to know what fields are required etc… I am doing this in conjunction with Boise,ID Radio. Thanks Joe

Hey Joe! Thanks for joining the forum.

Once this feature is done, would you like to share it with everyone here?

Hi Tom, I will be test driving the app in the next three weeks - I have my first on air show on 17th May. I am also working on a version that could be used by anyone with Internet and a Browser using AWS Lambda. Will share asap regards Joe.

1 Like