Passing duration when streaming mp3 from server to html5 audio
I have a node.js server converting and streaming mp3's on the fly. I am using an HTML5 audio tag to consume this stream, and the issue I'm having is the audio element doesn't know the duration of the mp3 until it has finished playing the whole thing (obviously). Is there any way, since my server knows the duration of the mp3 before sending it, that I can include the duration in the header of the response from the server or something, so the client consuming it knows the duration?
Thanks
I think for the time-being, in terms of a widely-supported solution, you're stuck sending that stuff through a separate request (or otherwise within some sort of manifest of your links -- included in the playlist you use to point at appropriate URIs, for example). This, of course, could be generated by your server, dynamically, when the songs are first added, and then served statically from then, on.
In a media-player which I'm building, I'm doing something similar to this -- downloading a json file which contains what would typically be within .mp3 metadata (which will also support non-mp3 versions, et cetera).
This is far from ideal, but again is one of those things that html5 audio/video wasn't meant to solve in its first iteration.
Year an a half old, but I just ran into this last week so...
Add 206 Partial Content support to your http server implementation, and this problem goes away. Seeking within the content starts working too..
The audio and video html5 tags are making Range requests:
Range: bytes=0- or..
Range: bytes=0-12345
The important bits of the proper response from the spec:
HTTP/1.1 206 PARTIAL CONTENT
Accept-Ranges: bytes
Content-Range: bytes 0-12345
Without the 206 response code, you will get the behavior you are experiencing.
I do this in Perl like so, where $request contains the request headers from the client, normalized. For example, SERVER_PROTOCOL in most cases contains 'HTTP/1.1'
my $crlf = " 12";
if ( $request->{RANGE} && $request->{RANGE} =~ /bytes=(d*)-(.*)$/ ) {
$offset = $1;
$end = $2 || $size; # end is optional in the spec. Default to size.
$header = $request->{SERVER_PROTOCOL} . ' 206 PARTIAL CONTENT' . $crlf .
'Content-Range: bytes ' . $offset . '-' . $end . '/' . $size . $crlf;
} else {
$header = $request->{SERVER_PROTOCOL} . ' 200 OK' . $crlf;
}
my $left = $end - $offset;
$header .= 'Server: ' . $SERVER_NAME . $crlf .
'Accept-Ranges: bytes' . $crlf .
'Date: ' . $http_date . $crlf .
'Content-Type: ' . ($self->simplemime($raw_path) || magic($fh)) . $crlf .
'Last-Modified: ' . $http_date . $crlf .
'Content-Length: ' . $size . $crlf .
'Connection: Keep-Alive' . $crlf .
'Cache-Control: max-age=' . $EXPIRE . $crlf . $crlf;
You then of course must honor the request by delivering the appropriate range of bytes for the requested content.
The client will often also 'stall' the download to match the speed of playback, so a proper event driven server such as Mojolicious, AnyEvent or Node.js will scale, whereas a 1 thread per connection model such as PHP does not. (well I suppose Ratchet would with some hacking, or using Xsendfile)
Incidentally, most Range requests end up being just:
Range: bytes=0-
That translates to as long as they can't seek and caching is disabled (and the browser actually honors it..), you can actually get away with just rewriting the header of a normal HTTP/1.1 200 response to the important bits of the HTTP/1.1 206 response and it works for some content. Specifically, this seems to work for content that does not have required metadata at the end of the file. For those file-types I've seen Range requests which seek to the end, and then restart at the beginning of the file. For this reason, it is better to just implement the actual seeking, but the above does work... Use at your own peril.
Take a look over here : Similar question
I think this is what you are looking for.
链接地址: http://www.djcxy.com/p/60734.html上一篇: 在html5中的音频标签安全