spec.asciidoc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. = Radiomanifest specification
  2. CiurmaPirata
  3. :url-repo: https://git.lattuga.net/boyska/radiomanifest-spec
  4. :revnumber: v0.2
  5. :revdate: 2022
  6. :description: A format to allow a radio to expose structured metadata about itself - allowing clients to have rich listening experience
  7. Un formato per fare sì che il sito di una radio possa esporre in maniera strutturata alcune informazioni sul
  8. suo sito.
  9. Tali informazioni sono, brevemente:
  10. * il palinsesto
  11. * l'elenco delle trasmissioni che vanno in onda in modo regolare, e per ciascuna di esse i principali feed
  12. * gli indirizzi di streaming
  13. Per permettere un'implementazione più semplice, ciascuna di queste informazioni segue una sua specifica, possibilmente appoggiandosi a specifiche già esistenti.
  14. == RadioManifest
  15. 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``.
  16. Ecco un esempio di xml:
  17. <?xml version="1.0" encoding="UTF-8" ?>
  18. <radio-manifest>
  19. <schedule src="https://www.radioexample.org/palinsesto.ics" />
  20. <streaming>
  21. <source name="hi-quality" priority="100" src="https://www.radioexample.org/stream.m3u" />
  22. <source name="lo-quality" priority="50" src="https://www.radioexample.org/stream-low.m3u" />
  23. </streaming>
  24. <shows src="https://www.radioexample.org/shows.xml" />
  25. <feed src="https://www.radioexample.org/all.xml" />
  26. </radio-manifest>
  27. (link:radio-manifest.xsd[Schema XSD])
  28. Ovvero:
  29. * 0 o 1 ``schedule``. Gli schedule sono definiti in link:https://icalendar.org/RFC-Specifications/iCalendar-RFC-5545/[formato iCalendar]
  30. * 0 o 1 oggetti ``streaming``; contengono un qualsiasi numero (almeno 1) di source, le quali
  31. ** *POSSONO* avere un campo ``name``. Il campo ``name`` è fortemente
  32. raccomandato se viene fornito più di un oggetto ``streaming``
  33. ** *DEVONO* avere un campo ``src``, il quale deve puntare ad una risorsa di tipo M3U.
  34. ** *POSSONO* avere un campo ``priority``, contenente un valore intero; se omesso, si assume il valore "1". Un numero più grande indica una
  35. maggiore importanza. Il campo ``priority`` serve a definire l'ordinamento con cui i client *DOVREBBERO*
  36. mostrare le playlist agli utenti, o a definire quale playlist vada usata, se il client sceglie automaticamente
  37. senza proporrere all'utente. Il valore della priority è relativo alle altre source, non si riferisce ad altre
  38. radio. Valori di priority minori di zero indicano che la source non dovrebbe essere resa visibile all'utente
  39. in condizioni normali.
  40. * 0 o 1 oggetti ``shows``. Il campo ``src`` *DEVE* puntare ad una risorsa di formato _shows_ (vedi di
  41. seguito).
  42. * 0 o 1 ``feed``. Il campo ``src`` *DEVE* puntare ad una risorsa di tipo feed.
  43. ### Implementazione client
  44. Un client dovrebbe chiedere all'utente di fornire l'indirizzo base di un sito. Il manifest dovrebbe essere
  45. rintracciabile andando all'indirizzo ``radiomanifest.xml`` relativo all'indirizzo di un sito.
  46. Ad esempio, se l'utente inserisce "http://hosting.com/myradio/" il manifest *DEVE* essere cercato all'indirizzo
  47. "http://hosting.com/myradio/radiomanifest.xml"
  48. Quando un client vuole suonare lo streaming associato ad un radiomanifest, esso potrebbe voler mostrare
  49. all'utente la scelta tra le varie source, oppure decidere automaticamente.
  50. Se il client sceglie automaticamente:
  51. * *DEVE* rispettare l'ordinamento delle priority.
  52. * *DEVE* escludere le source con priority minore di zero.
  53. * Qualora la riproduzione della source dovesse avere problemi, *DOVREBBE* passare alla successiva
  54. * Se alcune source hanno uguale priority, *DOVREBBE* scegliere casualmente tra di esse
  55. Se il client fa scegliere l'utente:
  56. * *DEVE* rispettare l'ordinamento delle priority
  57. * *DOVREBBE* omettere le source con priority minore di zero.
  58. == Schedule
  59. 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``.
  60. The schedule *SHOULD* include at least events up until 1 week
  61. The schedule *SHOULD* use recurrency rule where appropriate, so that the user is informed of this.
  62. == Shows
  63. The goal of the shows file is to:
  64. * list shows
  65. * provide useful metadata for each show, such as:
  66. ** dedicated feed
  67. ** link to specialized page for the show
  68. The syntax tries to be compatible with link:http://pyxml.sourceforge.net/topics/xbel/[XBEL], a bookmark
  69. format. While this format has not seen extensive usage in the latest years, it's still valuable to reuse
  70. someone else work instead of reinventing the wheel.
  71. Here is an example:
  72. <?xml version="1.0" encoding="UTF-8"?>
  73. <xbel version="1.0"
  74. xmlns:show="https://radiomanifest.degenerazione.xyz/shows/"
  75. >
  76. <bookmark href="http://radioexample.com/shows/learn-cook">
  77. <title>Learn to cook in C++</title>
  78. <info>
  79. <metadata owner="https://radiomanifest.degenerazione.xyz/">
  80. <show:name>Learn to cook in C++</show:name>
  81. <show:id>learn-C++</show:id>
  82. <show:description>A podcast about C++, templates, and nouvelle cuisine</show:description>
  83. <show:website>http://radioexample.com/shows/learn-cook</show:website>
  84. <show:feed>http://radioexample.com/shows/learn-cook/feed</show:feed>
  85. <show:schedule>http://radioexample.com/shows/learn-cook.ics</show:schedule>
  86. </metadata>
  87. </info>
  88. </bookmark>
  89. <folder>
  90. <title>Information</title>
  91. <bookmark href="http://radioexample.com/shows/uncensored">
  92. <title>Uncensored information</title>
  93. <info>
  94. <metadata owner="https://radiomanifest.degenerazione.xyz/">
  95. <show:name>Uncensored information</show:name>
  96. <show:id>uncensored</show:id>
  97. <show:description>News, news &amp; more news</show:description>
  98. <show:website>http://radioexample.com/shows/uncensored</show:website>
  99. <show:feed type="application/rss+xml">http://radioexample.com/shows/uncensored/feed</show:feed>
  100. <show:schedule type="text/calendar">http://radioexample.com/shows/uncensored.ics</show:schedule>
  101. <show:schedule type="application/calendar+json">http://radioexample.com/shows/uncensored.json</show:schedule>
  102. </metadata>
  103. </info>
  104. </bookmark>
  105. </folder>
  106. </xbel>
  107. Only ``show:name`` is required, though parsers are invited to apply the Postel law and read the parent
  108. ``title`` element.
  109. The ``type`` attribute is available for ``show:feed`` and ``show:schedule``; it defines the mime type of the
  110. resource, so that in the future different formats can be used. Right now, the default is
  111. ``application/rss+xml`` for ``show:feed`` and ``text/calendar`` for ``show:schedule``.
  112. ``show:feed`` and ``show:schedule`` can be present multiple times; When this happens, the semantic is that
  113. those files are equivalent, and can be considered different formats for the same data. The example shows
  114. exactly this: here, the producer is providing the same calendar in both ICS and
  115. link:https://tools.ietf.org/id/draft-kewisch-et-al-icalendar-in-json-00.html#RFC6321[jCal].
  116. XBEL supports folders, and we want to be XBEL-compatible. However, the parser is free to flatten the folder
  117. structure if they so prefer. In this case, they should use depth-first order when presenting the content to
  118. the user. We encourage producers not to rely on the fact that the user will be able to use a tree-like
  119. navigation.
  120. === Relationship with schedule
  121. It's pretty clear that in many cases ``shows.xml`` and ``schedule.ics`` will benefit from being linked. How to
  122. do that? For every event in the schedule, apply this rules:
  123. 1. If the VEVENT has a ``X-SHOW-ID`` field, see if a show with the same ``<show:id>`` exists
  124. 2. If the VEVENT has a ``CATEGORIES`` field, see, for all categories, if a show has the same ``<show:id>``
  125. 3. If the VEVENT has a ``SUMMARY``, see if there is a show with the same ``<show:name>``
  126. If any of this rule has a match, the event in the calendar belongs to that show.
  127. == Implementation details
  128. === HTTP Implementation
  129. Clients:
  130. - *MUST* provide an ``Accept`` header in every HTTP request. This will enable maximum flexibility in the
  131. future, allowing clients and servers to smoothly move to new file formats
  132. Servers:
  133. - *MUST* implement CORS adequately. Every file related to this specification must be retrievable by a browser
  134. on a different domain via a `GET`.
  135. == Casi d'uso
  136. === Player
  137. Supponiamo di voler realizzare un player di radio con feature avanzate, che sia però portabile su molte radio.
  138. Data una lista di URL di siti web, è possibile fare un player che:
  139. * supporti vari indirizzi di streaming in modo trasparente per l'utente
  140. * permetta all'utente di scegliere il tipo di streaming, ad esempio se la radio fornisce streaming di diversa
  141. qualità
  142. * possa dire all'utente informazioni utili sul palinsesto della radio che sta ascoltando
  143. * permetta di puntare allo storico, o di andare rapidamente alla pagina della trasmissione che sta
  144. ascoltando.
  145. 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.)
  146. === Radio automation
  147. Se un radio automation (della radio A) vuole importare contenuti da un'altra radio B, esso può facilmente
  148. fornire all'utente della radio A utili informazioni. Ad esempio, permette di vedere il palinsesto in forma
  149. grafica, selezionare uno show, vedere un'anteprima del feed corrispondente, quindi importarlo in una specifica
  150. fascia oraria.
  151. === radio-browser++
  152. https://www.radio-browser.info/ fornisce molte info utili su delle radio. Grazie a radio-manifest, sarebbe più semplice:
  153. * 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
  154. * più informazioni; radio-browser potrebbe includere le informazioni dettagliate disponibili tramite ``<schedule>`` e ``<shows>`` per fornire informazioni aggiuntive.
  155. === RadioDroid++
  156. RadioDroid is a fine Android app to listen to stream. We'd like to have an improved version of RadioDroid that
  157. also includes features that RadioManifest provide. See the _Player_ use case.
  158. == Why it is like this
  159. Of course, similar goals to the one achieved by RadioManifest could have been achieved in different ways. So
  160. let me try to answer to some frequently answered question. More in general, we tried to adhere to
  161. link:http://scripting.com/2017/05/09/rulesForStandardsmakers.html[Rules for Standards makers]
  162. === Why XML? Why not JSON?
  163. I understand why XML is fading out. Believe me, this choice is not about the technical merit of XML in itself!
  164. Feeds are still very important. While JsonFeed may look promising for the future, RSS is the present.
  165. Since any reasonable RadioManifest client would also need to implement feed parsing, they need a XML parser
  166. anyway. So, let's stick with this.
  167. === Why are ``shows`` based on XBEL, instead of OPML?
  168. Good question. OPML are heavily used in the RSS-world, so it would have made sense to base our ``shows.xml``
  169. format on OPML. However, OPML looks not so easy to extend. XBEL is much easier on this front. We want our
  170. format to be easy to extend in the future.
  171. === Why not add some more field here and there?
  172. Good point. It's pretty hard to define a threshold: should we add a ``slogan`` for a radio? Image? Logo?
  173. Gallery? Frequency of broadcasting? We applied the principle of _Fewer format features are better_, knowing
  174. that the standard is easily extendable, so future needs can be accomodated.
  175. === Why not extend RSS itself? We could add more info to the ``<channel>`` tag
  176. That's a nice idea. However, we think this would make the adoption harder.
  177. Let's say that you are using a CMS for your radio right now. Let's say Drupal (but it could be anything else
  178. of course). You should teach Drupal to put this nice information into the ``<channel>`` section of its feeds.
  179. How easy is it? I don't think this is *so* easy.
  180. With the current setup, the radiomanifest.xml can be used as a very simple static file. Most web servers can be
  181. told to serve this from a directory on the server, without passing through your CMS code at all.
  182. This static file is also changing very rarely: it's totally reasonable to write it once, and forget about it
  183. for years, so you don't even need a special software to keep it working.
  184. Of course, nothing prevents a CMS to generate this file dynamically, making this way simpler for users. But we
  185. wanted RadioManifest to be deployable as _"just a bunch of static files"_, as a way to increase early adoption.
  186. === The `<streaming>` section overlaps too much with /streaminfo.json ===
  187. Almost. While `/streaminfo.json` is clearly valuable data, we wanted to account for more usecases:
  188. * A radio should be able to list more than one URL for streaming. This can be for load balancing reasons, for
  189. example. M3U are a simple way to achieve this.
  190. * A radio can (and probably should) have not only more URLs for streaming, but actually stream different
  191. versions: different qualities, different codecs, etc. It is reasonable that, as a user, you don't really
  192. care about all those details: «Just gimme the audio!». However, your client could select the best codec for
  193. your usecase. Or, it may let the user explicitly select "low quality, low bandwidth" for users that want to
  194. save bandwidth. This is possible with radiomanifest adding multiple `<source>` elements, and is
  195. unfortunately not with `/streaminfo.json`
  196. == Meta
  197. This specification is versioned on {url-repo}[Git]