272 lines
14 KiB
Text
272 lines
14 KiB
Text
= Radiomanifest specification
|
|
CiurmaPirata
|
|
:url-repo: https://git.lattuga.net/boyska/radiomanifest-spec
|
|
:revnumber: v0.2
|
|
:revdate: 2022
|
|
:description: A format to allow a radio to expose structured metadata about itself - allowing clients to have rich listening experience
|
|
|
|
Un formato per fare sì che il sito di una radio possa esporre in maniera strutturata alcune informazioni sul
|
|
suo sito.
|
|
|
|
Tali informazioni sono, brevemente:
|
|
|
|
* il palinsesto
|
|
* l'elenco delle trasmissioni che vanno in onda in modo regolare, e per ciascuna di esse i principali feed
|
|
* gli indirizzi di streaming
|
|
|
|
|
|
Per permettere un'implementazione più semplice, ciascuna di queste informazioni segue una sua specifica, possibilmente appoggiandosi a specifiche già esistenti.
|
|
|
|
== RadioManifest
|
|
|
|
Al fine di avere un singolo punto in cui "esporre" le funzionalità supportate dal sito web, un sito può creare un manifest. Esso *DOVREBBE* (*SHOULD*) chiamarsi sempre ``${BASEURL}/radiomanifest.xml``.
|
|
|
|
Ecco un esempio di xml:
|
|
|
|
<?xml version="1.0" encoding="UTF-8" ?>
|
|
<radio-manifest>
|
|
<schedule src="https://www.radioexample.org/palinsesto.ics" />
|
|
<streaming>
|
|
<source name="hi-quality" priority="100" src="https://www.radioexample.org/stream.m3u" />
|
|
<source name="lo-quality" priority="50" src="https://www.radioexample.org/stream-low.m3u" />
|
|
</streaming>
|
|
<shows src="https://www.radioexample.org/shows.xml" />
|
|
<feed src="https://www.radioexample.org/all.xml" />
|
|
</radio-manifest>
|
|
|
|
(link:radio-manifest.xsd[Schema XSD])
|
|
|
|
Ovvero:
|
|
|
|
* 0 o 1 ``schedule``. Gli schedule sono definiti in link:https://icalendar.org/RFC-Specifications/iCalendar-RFC-5545/[formato iCalendar]
|
|
* 0 o 1 oggetti ``streaming``; contengono un qualsiasi numero (almeno 1) di source, le quali
|
|
** *POSSONO* avere un campo ``name``. Il campo ``name`` è fortemente
|
|
raccomandato se viene fornito più di un oggetto ``streaming``
|
|
** *DEVONO* avere un campo ``src``, il quale deve puntare ad una risorsa di tipo M3U.
|
|
** *POSSONO* avere un campo ``priority``, contenente un valore intero; se omesso, si assume il valore "1". Un numero più grande indica una
|
|
maggiore importanza. Il campo ``priority`` serve a definire l'ordinamento con cui i client *DOVREBBERO*
|
|
mostrare le playlist agli utenti, o a definire quale playlist vada usata, se il client sceglie automaticamente
|
|
senza proporrere all'utente. Il valore della priority è relativo alle altre source, non si riferisce ad altre
|
|
radio. Valori di priority minori di zero indicano che la source non dovrebbe essere resa visibile all'utente
|
|
in condizioni normali.
|
|
* 0 o 1 oggetti ``shows``. Il campo ``src`` *DEVE* puntare ad una risorsa di formato _shows_ (vedi di
|
|
seguito).
|
|
* 0 o 1 ``feed``. Il campo ``src`` *DEVE* puntare ad una risorsa di tipo feed.
|
|
|
|
### Implementazione client
|
|
|
|
Un client dovrebbe chiedere all'utente di fornire l'indirizzo base di un sito. Il manifest dovrebbe essere
|
|
rintracciabile andando all'indirizzo ``radiomanifest.xml`` relativo all'indirizzo di un sito.
|
|
Ad esempio, se l'utente inserisce "http://hosting.com/myradio/" il manifest *DEVE* essere cercato all'indirizzo
|
|
"http://hosting.com/myradio/radiomanifest.xml"
|
|
|
|
Quando un client vuole suonare lo streaming associato ad un radiomanifest, esso potrebbe voler mostrare
|
|
all'utente la scelta tra le varie source, oppure decidere automaticamente.
|
|
Se il client sceglie automaticamente:
|
|
|
|
* *DEVE* rispettare l'ordinamento delle priority.
|
|
* *DEVE* escludere le source con priority minore di zero.
|
|
* Qualora la riproduzione della source dovesse avere problemi, *DOVREBBE* passare alla successiva
|
|
* Se alcune source hanno uguale priority, *DOVREBBE* scegliere casualmente tra di esse
|
|
|
|
Se il client fa scegliere l'utente:
|
|
|
|
* *DEVE* rispettare l'ordinamento delle priority
|
|
* *DOVREBBE* omettere le source con priority minore di zero.
|
|
|
|
== Schedule
|
|
|
|
The goal of the schedule is to express the typical weekly table that is commonly found in radio websites. It is an iCalendar file. Each show should be a distinct ``VEVENT``.
|
|
|
|
The schedule *SHOULD* include at least events up until 1 week
|
|
The schedule *SHOULD* use recurrency rule where appropriate, so that the user is informed of this.
|
|
|
|
== Shows
|
|
|
|
The goal of the shows file is to:
|
|
|
|
* list shows
|
|
* provide useful metadata for each show, such as:
|
|
** dedicated feed
|
|
** link to specialized page for the show
|
|
|
|
The syntax tries to be compatible with link:http://pyxml.sourceforge.net/topics/xbel/[XBEL], a bookmark
|
|
format. While this format has not seen extensive usage in the latest years, it's still valuable to reuse
|
|
someone else work instead of reinventing the wheel.
|
|
|
|
Here is an example:
|
|
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<xbel version="1.0"
|
|
xmlns:show="https://radiomanifest.degenerazione.xyz/shows/"
|
|
>
|
|
<bookmark href="http://radioexample.com/shows/learn-cook">
|
|
<title>Learn to cook in C++</title>
|
|
<info>
|
|
<metadata owner="https://radiomanifest.degenerazione.xyz/">
|
|
<show:name>Learn to cook in C++</show:name>
|
|
<show:id>learn-C++</show:id>
|
|
<show:description>A podcast about C++, templates, and nouvelle cuisine</show:description>
|
|
<show:website>http://radioexample.com/shows/learn-cook</show:website>
|
|
<show:feed>http://radioexample.com/shows/learn-cook/feed</show:feed>
|
|
<show:schedule>http://radioexample.com/shows/learn-cook.ics</show:schedule>
|
|
</metadata>
|
|
</info>
|
|
</bookmark>
|
|
<folder>
|
|
<title>Information</title>
|
|
<bookmark href="http://radioexample.com/shows/learn-cook">
|
|
<title>Uncensored information</title>
|
|
<info>
|
|
<metadata owner="https://radiomanifest.degenerazione.xyz/">
|
|
<show:name>Uncensored information</show:name>
|
|
<show:id>uncensored</show:id>
|
|
<show:description>News, news & more news</show:description>
|
|
<show:website>http://radioexample.com/shows/uncensored</show:website>
|
|
<show:feed type="application/rss+xml">http://radioexample.com/shows/uncensored/feed</show:feed>
|
|
<show:schedule type="text/calendar">http://radioexample.com/shows/uncensored.ics</show:schedule>
|
|
<show:schedule type="application/calendar+json">http://radioexample.com/shows/uncensored.json</show:schedule>
|
|
</metadata>
|
|
</info>
|
|
</bookmark>
|
|
</folder>
|
|
</xbel>
|
|
|
|
Only ``show:name`` is required, though parsers are invited to apply the Postel law and read the parent
|
|
``title`` element.
|
|
|
|
The ``type`` attribute is available for ``show:feed`` and ``show:schedule``; it defines the mime type of the
|
|
resource, so that in the future different formats can be used. Right now, the default is
|
|
``application/rss+xml`` for ``show:feed`` and ``text/calendar`` for ``show:schedule``.
|
|
|
|
``show:feed`` and ``show:schedule`` can be present multiple times; When this happens, the semantic is that
|
|
those files are equivalent, and can be considered different formats for the same data. The example shows
|
|
exactly this: here, the producer is providing the same calendar in both ICS and
|
|
link:https://tools.ietf.org/id/draft-kewisch-et-al-icalendar-in-json-00.html#RFC6321[jCal].
|
|
|
|
XBEL supports folders, and we want to be XBEL-compatible. However, the parser is free to flatten the folder
|
|
structure if they so prefer. In this case, they should use depth-first order when presenting the content to
|
|
the user. We encourage producers not to rely on the fact that the user will be able to use a tree-like
|
|
navigation.
|
|
|
|
|
|
=== Relationship with schedule
|
|
|
|
It's pretty clear that in many cases ``shows.xml`` and ``schedule.ics`` will benefit from being linked. How to
|
|
do that? For every event in the schedule, apply this rules:
|
|
|
|
1. If the VEVENT has a ``X-SHOW-ID`` field, see if a show with the same ``<show:id>`` exists
|
|
2. If the VEVENT has a ``CATEGORIES`` field, see, for all categories, if a show has the same ``<show:id>``
|
|
3. If the VEVENT has a ``SUMMARY``, see if there is a show with the same ``<show:name>``
|
|
|
|
If any of this rule has a match, the event in the calendar belongs to that show.
|
|
|
|
== Implementation details
|
|
|
|
=== HTTP Implementation
|
|
|
|
Clients:
|
|
|
|
- *MUST* provide an ``Accept`` header in every HTTP request. This will enable maximum flexibility in the
|
|
future, allowing clients and servers to smoothly move to new file formats
|
|
|
|
Servers:
|
|
|
|
- *MUST* implement CORS adequately. Every file related to this specification must be retrievable by a browser
|
|
on a different domain via a `GET`.
|
|
|
|
|
|
== Casi d'uso
|
|
|
|
=== Player
|
|
|
|
Supponiamo di voler realizzare un player di radio con feature avanzate, che sia però portabile su molte radio.
|
|
Data una lista di URL di siti web, è possibile fare un player che:
|
|
|
|
* supporti vari indirizzi di streaming in modo trasparente per l'utente
|
|
* permetta all'utente di scegliere il tipo di streaming, ad esempio se la radio fornisce streaming di diversa
|
|
qualità
|
|
* possa dire all'utente informazioni utili sul palinsesto della radio che sta ascoltando
|
|
* permetta di puntare allo storico, o di andare rapidamente alla pagina della trasmissione che sta
|
|
ascoltando.
|
|
|
|
Come capita spesso, questo può essere applicato anche alla scrittura di app che supportino molte radio, senza che però esse debbano essere limitate al solo streaming come è il caso attualmente (vedi le varie Transistor, RadioDroid, ecc.)
|
|
|
|
=== Radio automation
|
|
|
|
Se un radio automation (della radio A) vuole importare contenuti da un'altra radio B, esso può facilmente
|
|
fornire all'utente della radio A utili informazioni. Ad esempio, permette di vedere il palinsesto in forma
|
|
grafica, selezionare uno show, vedere un'anteprima del feed corrispondente, quindi importarlo in una specifica
|
|
fascia oraria.
|
|
|
|
=== radio-browser++
|
|
|
|
https://www.radio-browser.info/ fornisce molte info utili su delle radio. Grazie a radio-manifest, sarebbe più semplice:
|
|
|
|
* mantenere le informazioni in modo più semplice; finché una radio mantiene lo stesso sito web, può aggiornare la lista di url di streaming in modo automatico
|
|
* più informazioni; radio-browser potrebbe includere le informazioni dettagliate disponibili tramite ``<schedule>`` e ``<shows>`` per fornire informazioni aggiuntive.
|
|
|
|
=== RadioDroid++
|
|
|
|
RadioDroid is a fine Android app to listen to stream. We'd like to have an improved version of RadioDroid that
|
|
also includes features that RadioManifest provide. See the _Player_ use case.
|
|
|
|
== Why it is like this
|
|
|
|
Of course, similar goals to the one achieved by RadioManifest could have been achieved in different ways. So
|
|
let me try to answer to some frequently answered question. More in general, we tried to adhere to
|
|
link:http://scripting.com/2017/05/09/rulesForStandardsmakers.html[Rules for Standards makers]
|
|
|
|
=== Why XML? Why not JSON?
|
|
|
|
I understand why XML is fading out. Believe me, this choice is not about the technical merit of XML in itself!
|
|
|
|
Feeds are still very important. While JsonFeed may look promising for the future, RSS is the present.
|
|
Since any reasonable RadioManifest client would also need to implement feed parsing, they need a XML parser
|
|
anyway. So, let's stick with this.
|
|
|
|
=== Why are ``shows`` based on XBEL, instead of OPML?
|
|
|
|
Good question. OPML are heavily used in the RSS-world, so it would have made sense to base our ``shows.xml``
|
|
format on OPML. However, OPML looks not so easy to extend. XBEL is much easier on this front. We want our
|
|
format to be easy to extend in the future.
|
|
|
|
=== Why not add some more field here and there?
|
|
|
|
Good point. It's pretty hard to define a threshold: should we add a ``slogan`` for a radio? Image? Logo?
|
|
Gallery? Frequency of broadcasting? We applied the principle of _Fewer format features are better_, knowing
|
|
that the standard is easily extendable, so future needs can be accomodated.
|
|
|
|
=== Why not extend RSS itself? We could add more info to the ``<channel>`` tag
|
|
|
|
That's a nice idea. However, we think this would make the adoption harder.
|
|
|
|
Let's say that you are using a CMS for your radio right now. Let's say Drupal (but it could be anything else
|
|
of course). You should teach Drupal to put this nice information into the ``<channel>`` section of its feeds.
|
|
How easy is it? I don't think this is *so* easy.
|
|
|
|
With the current setup, the radiomanifest.xml can be used as a very simple static file. Most web servers can be
|
|
told to serve this from a directory on the server, without passing through your CMS code at all.
|
|
This static file is also changing very rarely: it's totally reasonable to write it once, and forget about it
|
|
for years, so you don't even need a special software to keep it working.
|
|
|
|
Of course, nothing prevents a CMS to generate this file dynamically, making this way simpler for users. But we
|
|
wanted RadioManifest to be deployable as _"just a bunch of static files"_, as a way to increase early adoption.
|
|
|
|
=== The `<streaming>` section overlaps too much with /streaminfo.json ===
|
|
|
|
Almost. While `/streaminfo.json` is clearly valuable data, we wanted to account for more usecases:
|
|
- A radio should be able to list more than one URL for streaming. This can be for load balancing reasons, for
|
|
example. M3U are a simple way to achieve this.
|
|
- A radio can (and probably should) have not only more URLs for streaming, but actually stream different
|
|
versions: different qualities, different codecs, etc. It is reasonable that, as a user, you don't really
|
|
care about all those details: «Just gimme the audio!». However, your client could select the best codec for
|
|
your usecase. Or, it may let the user explicitly select "low quality, low bandwidth" for users that want to
|
|
save bandwidth. This is possible with radiomanifest adding multiple `<source>` elements, and is
|
|
unfortunately not with `/streaminfo.json`
|
|
|
|
|
|
== Meta
|
|
|
|
This specification is versioned on {url-repo}[Git]
|