123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- = 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/uncensored">
- <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]
|