[whatwg] <audio> metadata

What follows is a first pass at addressing a missing ability
when dealing with Internet streams, usually radio ones.
Comments and suggestions are quite welcome; as my first
attempt--ever--at submitting to this group, apologies if
I've made any mistakes in how I've proceeded.

Thanks,
Andy Valencia
Contact: https://vsta.org/contact/andy

========================
Proposal for enhancement to HTML5 <audio> element to better support
metadata provided by streams.

# Background

Browsers have an <audio> element which can directly play streaming
URL's.  When the stream is an Internet radio station, the stream
almost certainly offers metadata; typically, the artist and track,
and often an album cover URL as well.  While modern browsers can
play these streams, there is no way to access this metadata.

Media elements in modern browsers _do_ have the notion of metadata,
but in current standards this is limited to static characteristics
such as duration.  When listening to a radio stream, the metadata will
change as successive tracks are played.

# Stream Delivery of Dynamic Metadata

A moderately detailed description of current practices in providing
metadata is provided at:

    http://www.smackfu.com/stuff/programming/shoutcast.html

(One detail glossed over in this page is that older streaming servers
start their GET response with "ICY 200 OK" rather than a standard
HTTP response.  This technically means the response is HTTP 0.9
without headers; the headers are present, but must be processed by
the application and trimmed from the start of the media stream
in the GET response.  Apple Safari already declines to play 0.9
media elements within a post-0.9 page, and there are signs that
Chrome will follow suit.  Thus, accomodating this older mode should
be considered optional.)

Newer streaming server versions use a proper HTTP response, with
the documented elements in the HTTP response header.

Because the metadata is encoded in a general attribute=value
format, a wide variety of metadata may be encoded.  By convention,
at least the attributes "StreamTitle" and "StreamUrl" will be
included in the response.  Also by convention, StreamTitle is
structured as "Artist - Track Name".

# API Considerations

While listening to streams with metadata is a compelling application
of web technology, it is probably a tiny percentage of the use
of <audio> elements.  Thus, this proposal describes a mechanism
which leaves the default browser behavior unchanged.  It also
gracefully degrades when presented to a non-implementing
browser, still permitting stream play while in the existing
non-metadata fashion.

This proposal is designed with the current state of streaming,
currently depending on the HTTP Icy-MetaData header element.  However,
this specific detail is abstracted, in recognition that streaming
technology could evolve in the future.  The intention is that this API
will remain stable even if the details of metadata request and
delivery change.

As noted, current HTML5 media elements do have some metadata support.
This API is also structured to permit these existing elements to
participate in this API if desired.

# <audio> element changes

These enhancements are activated when the <audio> element has the
new attribute "dynamicmetadata" present.  Without this attribute,
no metadata request header is added to the stream HTTP request, and no
other attributes of this proposal will be acted upon even if present.

If the server response indicates support for dynamic metadata,
on each metadata update, the <audio> element's attributes are changed
to reflect the latest received metadata.  For each "Attribute=Value"
in the metadata update, an attribute "metaAttribute" with value "Value" will
be added to the <audio> element.  Previous metadata attributes which
are not present in the latest update are left untouched.  The browser
must verify well-formed identifier names for each Attribute, and
quietly reject ill-formed names.  It can also apply checks on the
Value.  (Implementors are reminded that the Value, because it encodes
information such as names, might contain a wide range of character
encodings.)

The <audio> element adds the hook "onmetadatachange", connecting to
a function which is called on each update of metadata.  This
function is called with an event, which includes the attribute
"changed" with a value which is a list of Attribute names which
are present in the update.

# Example code

<code>
function new_meta(ev) {
    const changes = ev.changed;
    if (changes.indexOf("StreamTitle") >= 0) {
	const title = player.metaStreamTitle;
	const idx = title.indexOf(" - ");
	if (idx == -1) {
	    // "Just a plain old piece of text"
	    artist.textContent = title;
	    track.textContent = "";
	} else {
	    // <artist> - <title>
	    artist.textContent = title.slice(0, idx);
	    track.textContent = title.slice(idx+3);
	}
    }
    if (changes.indexOf("StreamUrl") >= 0) {
	// Display album art
	art.src = player.metaStreamUrl;
    } else {
	art.src = "";
    }
}
</code>

Artist: <span id="artist"></span><br>
Track: <span id="track"></span><br>
Album Art:<br>
<img id="art">

<audio src="http://an-internet-radio-station.whatever" id="player"
    dynamicmetadata onmetadatachange="new_meta(ev)">

</audio>

Received on Monday, 10 April 2017 01:38:47 UTC