Difference between revisions of "Metadata Scripts"

From SOUND4wiki
 
(15 intermediate revisions by the same user not shown)
Line 4: Line 4:
 
The source data has to be coded in '''UTF-8'''. (Since Server 4.1.75/Stream 2.4.12, UTF16 and UTF32 are also accepted).
 
The source data has to be coded in '''UTF-8'''. (Since Server 4.1.75/Stream 2.4.12, UTF16 and UTF32 are also accepted).
  
===There are 3 modes:===
+
===There are 4 modes:===
  
 
*Char parsing: a callback is called for each char received
 
*Char parsing: a callback is called for each char received
 
*Line parsing: a callback is called for each line received
 
*Line parsing: a callback is called for each line received
 
*XML parsing: different callbacks might be called, see below.
 
*XML parsing: different callbacks might be called, see below.
 +
*JSON parsing: a callback is called after JSON has been parsed ''(Since Stream 3.0.4)''
  
The script MUST call one of this function depending of the parsing method choose (outside of any function).
+
The script MUST call one of this function depending on the parsing method choose (outside any function).
  
 
*<code>UseCharParser()</code>
 
*<code>UseCharParser()</code>
 
*<code>UseLineParser()</code>
 
*<code>UseLineParser()</code>
 
*<code>UseXmlParser()</code>
 
*<code>UseXmlParser()</code>
 +
*<code>UseJsonParser()</code> ''(Since Stream 3.0.4)''
  
 
===Tool functions===
 
===Tool functions===
  
 
====LogInfo====
 
====LogInfo====
Output to the sound4stream log.
+
Output to the sound4stream log for Stream metadata, or the sound4server log for RDS metadata.
  
 
       Ex: <code>LogInfo("The value is ", value,"... Continuing.")</code>
 
       Ex: <code>LogInfo("The value is ", value,"... Continuing.")</code>
  
 
====SendMetaDataSong [Deprecated] [Stream Only]====
 
====SendMetaDataSong [Deprecated] [Stream Only]====
is used to send the metadata to the remote server. Only first parameter is used (title)
+
This set the <code>compact_song</code> and <code>url</code> element in the metadata.
  
      [NOTE: this is a deprecated function: see XML Metadata below for more powerfull settings]
+
'''WARNING''': this does not send the metadata immediately, only when the source is disconnected. Use <code>SendMetaNow()</code> to send.
 +
 
 +
Since version 2.4.17, this sends the metadata immediately to be compatible with Telos implementations.
 +
 
 +
      [NOTE: this is a deprecated function: see XML Metadata below for more powerful settings]
  
 
       Ex: <code>SendMetaDataSong(title,"")</code>
 
       Ex: <code>SendMetaDataSong(title,"")</code>
Line 48: Line 54:
  
 
====iconv====
 
====iconv====
NOTE: Since Server 4.1.75/Stream 2.4.12, the software will try guess the encoding before applying the script. It will always work for UTF8/16/32 encoding, so those are the recommended encodings. In those cases, iconv is useless.
+
NOTE: Since Server 4.1.75/Stream 2.4.12, the software will try guess the encoding before applying the script. It will always work for UTF8/16/32 encoding, so those are the recommended encodings. In those cases, iconv is useless, unless to convert to ASCII for RDS.
  
 
module has been added in Stream 2.4.4 for Linux (and boxes 1.56) and for windows version 2.4.7. You can use it like this:<syntaxhighlight lang="lua">
 
module has been added in Stream 2.4.4 for Linux (and boxes 1.56) and for windows version 2.4.7. You can use it like this:<syntaxhighlight lang="lua">
Line 57: Line 63:
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
====SendMetaNow====
 +
Since server 4.1.77 and Stream 2.4.14, you can call <code>SendMetaNow()</code> at any time to send the current metadata.
 +
 +
In Stream, before 2.4.17 it does not compute compact_song automatically.
 +
 +
====DoNotSendMeta====
 +
Since server 4.1.83 and Stream 2.4.18, you can call <code>DoNotSendMeta()</code> to cancel metadata update without error.
 +
 +
Before, not setting the metadata was not sending it, but reported an error.
  
 
===Callbacks===
 
===Callbacks===
Line 80: Line 96:
  
 
====OnXMLParsed [XML Mode]====
 
====OnXMLParsed [XML Mode]====
NB: In both Char Mode and Line Mode, it is possible to use the XML parser.
+
In XML mode, the callback OnXMLParsed is called when the XML has been successfully parsed.
 +
 
 +
Usually XPath is used to retreive XML data.
 +
 
 +
Ex:<syntaxhighlight lang="lua">
 +
UseXmlParser()
 +
function OnXMLParsed()
 +
    local descr=XPath('/MyRootNode/MyList/MyElement[1]/@Description')
 +
    meta:Add("title", descr);
 +
end
 +
</syntaxhighlight>NB: In both Char Mode and Line Mode, it is possible to use the XML parser.
  
 
For that, call the function ParseXML with the XML content as parameter. Ex: <code>ParseXML(mycontent)</code>
 
For that, call the function ParseXML with the XML content as parameter. Ex: <code>ParseXML(mycontent)</code>
Line 87: Line 113:
  
 
So, it is possible to parse encapsulated XML.
 
So, it is possible to parse encapsulated XML.
 +
====OnJSONParsed [JSON Mode]====
 +
In JSON mode, the callback OnJSONParsed is called when the JSON has been successfully parsed, with the data as a table as parameter.
  
 
Ex:<syntaxhighlight lang="lua">
 
Ex:<syntaxhighlight lang="lua">
UseXmlParser()
+
UseJsonParser()
function OnXMLParsed()
+
function OnJSONParsed(js)
     descr=XPath('/MyRootNode/MyList/MyElement[1]/@Description')
+
     local artist=js['artist']
     meta:Add("title", descr);
+
    local title=js['title']
 +
    meta:Add("title", title)
 +
     meta:Add("artist", artist)
 
end
 
end
</syntaxhighlight>
+
</syntaxhighlight>NB: In both Char Mode and Line Mode, it is possible to use the JSON parser.
 +
 
 +
For that, call the function ParseJSON with the JSON content as parameter. Ex: <code>ParseJSON(mycontent)</code>
 +
 
 +
This will act exactly the same way as if the JSON content had been received directly.
  
 +
So, it is possible to parse encapsulated JSON.
 
===Metadata===
 
===Metadata===
 
Metadata is internally stored as XML.
 
Metadata is internally stored as XML.
Line 102: Line 137:
  
 
The main metadata node is called 'meta'.
 
The main metadata node is called 'meta'.
 +
 +
The metadata is sent when the source disconnects or when  <code>SendMetaNow()</code> is called.
  
 
Functions on nodes are:
 
Functions on nodes are:
  
*node:Add("name", "content") : add a node, with the specified optional content. returns the new node
+
*node:Add("name", "content") : add a node, with the specified optional content. Returns the new node
*node:AddAttribute("name", "value") : add an attribute to the node. returns the node.
+
*node:AddAttribute("name", "value") : add an attribute to the node. Returns the node.
 +
*node:Set("name", "content") : add or replace a node, with the specified optional content. Returns the new node ''(Since Stream 2.4.17/Server 4.1.82)''
  
 
Ex: <code>meta:add("title", mytitle)</code>
 
Ex: <code>meta:add("title", mytitle)</code>
 +
 +
The usual metadata keys (handled automatically when the protocol allows it) are:
 +
 +
*<code>title</code> : the title of the song
 +
*<code>artist</code> : the artist of the song
 +
*<code>compact_song</code> : a combination of artist and title, generated automatically if missing as <code>artist - title</code>
 +
*<code>url</code> : the album art cover
  
 
=Streaming=
 
=Streaming=
 
Some protocols have their own XML metadata:
 
Some protocols have their own XML metadata:
  
*Icecast2 metadata can be set within special node '_ice'
+
*Icecast2 metadata can be set within special node ''''_ice'''<nowiki/>'
*Shoutcast V2 metadata can be set within special node '_shout'
+
*Shoutcast V2 metadata can be set within special node ''''_shout'''<nowiki/>'
*RTMP metadata can be set within special node '_rtmp'
+
*RTMP metadata can be set within special node ''''_rtmp'''<nowiki/>'
  
 
In these cases, all specific data will be added or replace the default generated data.
 
In these cases, all specific data will be added or replace the default generated data.
  
 +
===All streams: meta===
 +
For the 'meta' node, used (depends on protocol support) automatic items are:
  
   For the 'meta' node, used (depends on protocol support) automatic items are:
+
*"artist"
 +
*"title"
 +
*"album"
 +
*<nowiki>"compact_song"    : automatically set to "[artist] - [title]" if is not specified. Used by protocols that do not allow separate title/artist and for display in software.</nowiki>
 +
*"next_song" : sub-node for metadata of next playing song.
 +
**"artist"
 +
**"title"
  
       + "artist"
+
BUG: before 2.4.17, meta node is cleared only after a disconnect, so using meta:Add will add nodes which will be ignored.
  
       + "title"
+
Example:<syntaxhighlight lang="lua">
 +
meta:Add("title",title)
 +
meta:Add("artist",artist)
 +
</syntaxhighlight>
  
       + "album"
+
===Icecast: _ice===
 +
For the '_ice' node, you can add directly tags.
  
<nowiki>       + "compact_song"    : automatically set to "[artist] - [title]" if is not specified. Used by protocols that do not allow separate title/artist</nowiki>
+
They will be put on the <code>updinfo</code> line, replacing the default song=XXX
  
       > "next_song" : sub-node for metadata of next playing song.
+
Example: To set the artist title only, use:<syntaxhighlight lang="lua">
 +
local ice=meta:Add("_ice")
 +
ice:Add("title",title)
 +
ice:Add("artist",artist)
 +
</syntaxhighlight>
  
           + "artist"
+
===Shoutcast V2: _shout===
 +
For the '_shout' node, you can add directly tags.
  
           + "title"
+
Default is to use TPE1 for artist, TIT2 for title, TABL for album and to set next_song in <extension> <soon> tag.
  
   For the '_ice' node:
+
Example: To set the content type ID3V1 genre code, you can use<syntaxhighlight lang="lua">
 +
local shout=meta:Add("_shout")
 +
shout:Add("TCON","Subgenre"):AddAttribute("v1","24")
 +
</syntaxhighlight>will add: <TCON v1="24">Subgenre</TCON>
  
       + You can add directly tags.
+
===MPEG-TS: _id3===
 +
For the '_id3' node, you can add directly tags.
  
       They will be put on the updinfo line, replacing the default song=XXX
+
Those tags will be embed in MPEG-TS as an ID3 PES metadata stream .
  
       Ex: To set the artist title only, use:
+
Default is to use TPE1 for artist, TIT2 for title.
  
             local ice=meta:Add("_ice")
+
Example: To set the content type ID3V1 genre code, you can use<syntaxhighlight lang="lua">
 
+
local id3=meta:Add("_id3")
               ice:Add("title",title)
+
id3:Add("TPE1","Billie Holiday")
 
+
id3:Add("TIT2","Strange Fruit")
               ice:Add("artist",artist)
+
</syntaxhighlight>
 
+
===RTMP: _rtmp===
   For the '_shout' node:
+
For the '_rtmp' node, all primary level nodes will be added to the <code>onMetadata</code>, using the node name as key, and the node content as value.
 
 
       + You can add directly tags.
 
 
 
       Default is to use TPE1 for artist, TIT2 for title, TABL for album
 
 
 
       and to set next_song in <extension> <soon> tag
 
 
 
       Ex: To set the content type ID3V1 genre code, you can use
 
  
             local shout=meta:Add("_shout")
+
The top level metadata is ignored if _rtmp exists, but if title is not given in it, it will be set to the top level metadata compact_song (computed automatically from title/artist if missing).
  
             shout:Add("TCON","Subgenre"):AddAttribute("v1","24")
+
If no _rtmp node is created, then rtmp send all the top level metadata (since 2.4.17).
  
           will add: <TCON v1="24">Subgenre</TCON>
+
Example:<syntaxhighlight lang="lua">
 +
local rtmp=meta:Add("_rtmp")
 +
rtmp:Add("mycommand", "This is my command")
  
   For the '_rtmp' node:
+
</syntaxhighlight>will add a field with key "<code>mycommand</code>" in the <code>onMetadata</code> notify AMF block.         
  
       All primary level nodes will be added to the onMetadata, using the node name as key, and the node content as value.
+
===SetAlbumArtURL===
 +
You can also invoke function SetAlbumArtURL(url) with an url or path to the album art image.
  
       Ex:   local rtmp=meta:Add("_rtmp")
+
Protocols that support it (currently shoutcast V2) will send the album art to the server.
  
             rtmp::Add("mycommand", "This is my command")
+
=RDS=
 +
For RDS, you can set the variables you want and then use them in Dynamic RT or Dynamic Labels by putting them between {}.
  
           will add a field with key "mycommand" in the onMetadata notify AMF block.
+
For instance, if your script uses <code>meta:Add("title", myvalue)</code> then you can use <code>{title}</code> which will be replaced by the set value, like <code>You are listening to {title}</code>.
  
           
+
There is a special variable <code>DURATION</code> which can be set to limit the display time of the new data. It can be in <code>seconds</code>, or in <code>[hours:]minutes:seconds</code>.
  
   You can also invoke function SetAlbumArtURL(url) with an url or path to the album art image.
+
For instance, you can limit the display to 10 seconds with <code>meta:Add("DURATION", 10)</code>.
  
   Protocols that support it (currently shoutcast V2) will send the album art to the server.
+
=Standalone processors=
 +
When using sharing to put a source file in Public, it can be accessed locally in <code>/public/</code>.
 +
[[Category:Metadata]]
 +
[[Category:Streaming]]
 +
[[Category:RDS]]

Latest revision as of 13:41, 15 November 2024

Common to all

Metadata scripts use LUA as primary language (see http://www.lua.org/).

The source data has to be coded in UTF-8. (Since Server 4.1.75/Stream 2.4.12, UTF16 and UTF32 are also accepted).

There are 4 modes:

  • Char parsing: a callback is called for each char received
  • Line parsing: a callback is called for each line received
  • XML parsing: different callbacks might be called, see below.
  • JSON parsing: a callback is called after JSON has been parsed (Since Stream 3.0.4)

The script MUST call one of this function depending on the parsing method choose (outside any function).

  • UseCharParser()
  • UseLineParser()
  • UseXmlParser()
  • UseJsonParser() (Since Stream 3.0.4)

Tool functions

LogInfo

Output to the sound4stream log for Stream metadata, or the sound4server log for RDS metadata.

       Ex: LogInfo("The value is ", value,"... Continuing.")

SendMetaDataSong [Deprecated] [Stream Only]

This set the compact_song and url element in the metadata.

WARNING: this does not send the metadata immediately, only when the source is disconnected. Use SendMetaNow() to send.

Since version 2.4.17, this sends the metadata immediately to be compatible with Telos implementations.

      [NOTE: this is a deprecated function: see XML Metadata below for more powerful settings]

       Ex: SendMetaDataSong(title,"")

print

can be used to answer if in TCP Server mode. Does nothing in other modes.

       Ex: print("HTTP/1.1 200 OK\r\n")

XPath

is an XPath parser (see http://en.wikipedia.org/wiki/XPath) to extract XML data. It can be used only in an XML callback.

     If an XPath fails, it returns an empty string

       Ex: title=XPath("/Output/Current/@Title")

CheckMinVersion

can be used to check is the SOUND4Stream version is enough.

       Ex: if CheckMinVersion("1.0.15") then

iconv

NOTE: Since Server 4.1.75/Stream 2.4.12, the software will try guess the encoding before applying the script. It will always work for UTF8/16/32 encoding, so those are the recommended encodings. In those cases, iconv is useless, unless to convert to ASCII for RDS.

module has been added in Stream 2.4.4 for Linux (and boxes 1.56) and for windows version 2.4.7. You can use it like this:

-- convert the title from iso-8859-1 (Windows latin-1) to utf-8
if iconv ~= nil then  -- test, so if not implemented will not crash
    local cd = iconv.new("utf-8//TRANSLIT//IGNORE", "iso-8859-1")
    title = cd:iconv(title)
end

SendMetaNow

Since server 4.1.77 and Stream 2.4.14, you can call SendMetaNow() at any time to send the current metadata.

In Stream, before 2.4.17 it does not compute compact_song automatically.

DoNotSendMeta

Since server 4.1.83 and Stream 2.4.18, you can call DoNotSendMeta() to cancel metadata update without error.

Before, not setting the metadata was not sending it, but reported an error.

Callbacks

Any callback function might be defined or not, depending on the wanted use.

OnConnect

When new metadata arrives (wherever it comes from), the script is created.

The callback OnConnect is called with a string parameter indicating the source of connection (might be incomplete)

OnDisconnect

OnDisconnect callback is called at end of metadata arriving (either end of file, or end of connection in TCP server mode).

This happens just before metadata is sent.

OnCharacterReceived [Char Mode]

  In char mode, the callback OnCharacterReceived is called with the signed number of the byte received as parameter.

OnLineReceived [Line Mode]

  in line mode, the callback OnLineReceived is called with the line received as parameter.

  This is called only when received a CR or LF or end of transmission

OnXMLParsed [XML Mode]

In XML mode, the callback OnXMLParsed is called when the XML has been successfully parsed.

Usually XPath is used to retreive XML data.

Ex:

UseXmlParser()
function OnXMLParsed()
    local descr=XPath('/MyRootNode/MyList/MyElement[1]/@Description')
    meta:Add("title", descr);
end

NB: In both Char Mode and Line Mode, it is possible to use the XML parser.

For that, call the function ParseXML with the XML content as parameter. Ex: ParseXML(mycontent)

This will act exactly the same way as if the XML content had been received directly.

So, it is possible to parse encapsulated XML.

OnJSONParsed [JSON Mode]

In JSON mode, the callback OnJSONParsed is called when the JSON has been successfully parsed, with the data as a table as parameter.

Ex:

UseJsonParser()
function OnJSONParsed(js)
    local artist=js['artist']
    local title=js['title']
    meta:Add("title", title)
    meta:Add("artist", artist)
end

NB: In both Char Mode and Line Mode, it is possible to use the JSON parser.

For that, call the function ParseJSON with the JSON content as parameter. Ex: ParseJSON(mycontent)

This will act exactly the same way as if the JSON content had been received directly.

So, it is possible to parse encapsulated JSON.

Metadata

Metadata is internally stored as XML.

So, it is possible to edit it to add some custom properties.

The main metadata node is called 'meta'.

The metadata is sent when the source disconnects or when SendMetaNow() is called.

Functions on nodes are:

  • node:Add("name", "content") : add a node, with the specified optional content. Returns the new node
  • node:AddAttribute("name", "value") : add an attribute to the node. Returns the node.
  • node:Set("name", "content") : add or replace a node, with the specified optional content. Returns the new node (Since Stream 2.4.17/Server 4.1.82)

Ex: meta:add("title", mytitle)

The usual metadata keys (handled automatically when the protocol allows it) are:

  • title : the title of the song
  • artist : the artist of the song
  • compact_song : a combination of artist and title, generated automatically if missing as artist - title
  • url : the album art cover

Streaming

Some protocols have their own XML metadata:

  • Icecast2 metadata can be set within special node '_ice'
  • Shoutcast V2 metadata can be set within special node '_shout'
  • RTMP metadata can be set within special node '_rtmp'

In these cases, all specific data will be added or replace the default generated data.

All streams: meta

For the 'meta' node, used (depends on protocol support) automatic items are:

  • "artist"
  • "title"
  • "album"
  • "compact_song"    : automatically set to "[artist] - [title]" if is not specified. Used by protocols that do not allow separate title/artist and for display in software.
  • "next_song" : sub-node for metadata of next playing song.
    • "artist"
    • "title"

BUG: before 2.4.17, meta node is cleared only after a disconnect, so using meta:Add will add nodes which will be ignored.

Example:

meta:Add("title",title)
meta:Add("artist",artist)

Icecast: _ice

For the '_ice' node, you can add directly tags.

They will be put on the updinfo line, replacing the default song=XXX

Example: To set the artist title only, use:

local ice=meta:Add("_ice")
ice:Add("title",title)
ice:Add("artist",artist)

Shoutcast V2: _shout

For the '_shout' node, you can add directly tags.

Default is to use TPE1 for artist, TIT2 for title, TABL for album and to set next_song in <extension> <soon> tag.

Example: To set the content type ID3V1 genre code, you can use

local shout=meta:Add("_shout")
shout:Add("TCON","Subgenre"):AddAttribute("v1","24")

will add: <TCON v1="24">Subgenre</TCON>

MPEG-TS: _id3

For the '_id3' node, you can add directly tags.

Those tags will be embed in MPEG-TS as an ID3 PES metadata stream .

Default is to use TPE1 for artist, TIT2 for title.

Example: To set the content type ID3V1 genre code, you can use

local id3=meta:Add("_id3")
id3:Add("TPE1","Billie Holiday")
id3:Add("TIT2","Strange Fruit")

RTMP: _rtmp

For the '_rtmp' node, all primary level nodes will be added to the onMetadata, using the node name as key, and the node content as value.

The top level metadata is ignored if _rtmp exists, but if title is not given in it, it will be set to the top level metadata compact_song (computed automatically from title/artist if missing).

If no _rtmp node is created, then rtmp send all the top level metadata (since 2.4.17).

Example:

local rtmp=meta:Add("_rtmp")
rtmp:Add("mycommand", "This is my command")

will add a field with key "mycommand" in the onMetadata notify AMF block.         

SetAlbumArtURL

You can also invoke function SetAlbumArtURL(url) with an url or path to the album art image.

Protocols that support it (currently shoutcast V2) will send the album art to the server.

RDS

For RDS, you can set the variables you want and then use them in Dynamic RT or Dynamic Labels by putting them between {}.

For instance, if your script uses meta:Add("title", myvalue) then you can use {title} which will be replaced by the set value, like You are listening to {title}.

There is a special variable DURATION which can be set to limit the display time of the new data. It can be in seconds, or in [hours:]minutes:seconds.

For instance, you can limit the display to 10 seconds with meta:Add("DURATION", 10).

Standalone processors

When using sharing to put a source file in Public, it can be accessed locally in /public/.