For some reason in Safari (and no other major browser), when I serve an MP3 via PHP through an Audio
context in JavaScript, the duration of the MP3 is always returned as infinity
.
This problem has stumped me for the last few days and after reading a few links (including this one) in search for a solution, I have not progressed at all.
$path = "path/to/file.mp3";
$file = [
"path" => $path,
"size" => filesize($path),
"bitrate" => $bitrate
];
header("Accept-Ranges: bytes", false);
header("Content-Length: " . $file["size"], false);
header("Content-Type: audio/mpeg", false);
echo file_get_contents($file["path"]);
exit;
var audio = new Audio(url);
// returns infinite on Safari
// returns 312.27311 on Chrome and Firefox (which is correct)
console.log(audio.duration);
I'm still yet to figure out why this problem is only in Safari and what is causing it in the first place, so if anyone has a solution it would be much appreciated!
Cheers.
After much investigation like yourself I finally figured it out.
The first request Safari sends has the header:
Range: bytes=0-1
It's your job to respond "correctly" so that Safari will send additional requests to fetch the rest of the file.
Here is my example of the "correct" headers:
Content-Length: 2
Accept-Ranges: bytes
Content-Range: bytes 0-1/8469
(Make sure you set response status to 206!)
(8469 is the Content-Length of the entire file)
What happens after that is somewhat magical - Safari sends a follow up request that has this header:
Range: bytes=0-8468
And you should respond "correctly" like with these headers:
Content-Length: 8469
Accept-Ranges: bytes
Content-Range: bytes 0-8468/8469
(Again, status 206!)
I hope this solves it for you, since I spent many hours searching to no avail. I eventually realized I needed to adjust my server to handle requests where the Range header is present.
I used this commit to help me understand what the "correct" response is: https://github.com/jooby-project/jooby/commit/142a933a31b9d8742714ecd38475d90e563314f7
As this thread is popping up first in google, allow me to share my experience.
Like many, I'm generating the mp3 through a php page, mostly in order to "hide" the real link of the mp3. And for this, Safari is quite annoying. To make it short, Safari considers the sound as a "live broadcast", ending up having this "infinite" duration. For the details, this post explained quite well why.
So what to do ? You have to put conditions on the headers of your php page that generate the sound (as mentioned by @brianarpie). Here is my php-generating-mp3 page :
<?php
// first, you need this function :
function serveFilePartial($fileName, $fileTitle = null, $contentType = 'application/octet-stream'){
// the code of this can be found here : https://github.com/pomle/php-serveFilePartial/blob/master/ServeFilePartial.inc.php
}
$link_of_your_mp3 = "var/my_folder/my_music.mp3"; // this is not an URL, but an absolute path
// and we call the function :
serveFilePartial($link_of_your_mp3, null, 'audio/mpeg');
?>
.. and that's it ! this function will generate the right headers depending on what the web-browser is asking for.
Of course you've done all your checking on link, vars, etc to protect the page. Note that my example is mp3, so I have to call the function with 'audio/mpeg'. If you output a different fileformat, you will have to adapt the content Type of the function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With