views:

1346

answers:

3

I'm attempting to embed an HTML5 audio element pointing to MP3 or OGG data served by a PHP file . When I view the page in Safari, the controls appear, but the UI says "Live Broadcast." When I click play, the audio starts as expected. Once it ends, however, I can't start it playing again by clicking play. Even using the JS API on the audio element and setting currentTime to 0 fails with an index error exception.

I suspected the headers from the PHP script were the problem, particularly missing a content length. But that's not the case. The response headers include a proper Content- Length to indicate the audio has finite size. Furthermore, everything works as expected in Firefox 3.5+. I can click play on the audio element multiple times to hear the sound replay.

If I remove the PHP script from the equation and serve up a static copy of the MP3 file, everything works fine in Safari.

Does this mean Safari is treating audio src URLs with query parameters differently than URLs that don't have them? Anyone have any luck getting this to work?

My simple example page is:

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <audio controls autobuffer>
      <source src="say.php?text=this%20is%20a%20test&format=.ogg" />
      <source src="say.php?text=this%20is%20a%20test&format=.mp3" />
    </audio>
  </body>
</html>

HTTP Headers from PHP script:

HTTP/1.x 200 OK
Date: Sun, 03 Jan 2010 15:39:34 GMT
Server: Apache
X-Powered-By: PHP/5.2.10
Content-Length: 8993
Keep-Alive: timeout=2, max=98
Connection: Keep-Alive
Content-Type: audio/mpeg

HTTP Headers from direct file access:

HTTP/1.x 200 OK
Date: Sun, 03 Jan 2010 20:06:59 GMT
Server: Apache
Last-Modified: Sun, 03 Jan 2010 03:20:02 GMT
Etag: "a404b-c3f-47c3a14937c80"
Accept-Ranges: bytes
Content-Length: 8993
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: audio/mpeg

I tried hard-coding the Accept-Ranges header into the script too, but no luck.

+1  A: 
Brian Campbell
Added the headers to the original question as they wouldn't fit in a comment. I had type specified originally, but took it out in case it was causing a problem. Adding them back for good measure, but with no change to the broken behavior in Safari.
Peter Parente
Your example works for me. So the only factor seems to be the PHP script. Interesting.I posted a demo of my code at http://tts.mindtrove.info/test.html. The source of PHP file is visible at http://tts.mindtrove.info/say.php.txt. The static audio files are at http://tts.mindtrove.info/cache.The only thing I see in the PHP script that might be troublesome now is the use of passthru("cat $fn"). But with a Content-Length and forced exit() at the end of the script, I'm not sure why Safari / WebKit would treat the audio as a never ending stream.
Peter Parente
Excellent help. Thanks for taking the time to work through this with me. Your findings might be ripe for a bug report, though I'm sure Apple will simply say the PHP script needs Range handling. It might be nice if they documented it somewhere though.
Peter Parente
A: 

I got the same problem. The key point is the Content-Range header. Everything works fine after I add it to the mp3-output php.

Pochang
A: 

Pochang is correct. Including a Content-Range header in the PHP response will cause Safari to behave properly. It also allows seeking (media.currentTime = 0;) without the dreaded INDEX_SIZE_ERR in Safari, though not in Chrome.

The PHP code for the header is:

$len = strlen( $data );
$shortlen = $length - 1;
header( 'Content-Range: bytes 0-'.$shortlen.'/'.$len);
Chris Snyder