Длительность аудио в Safari всегда возвращает бесконечность при потоковой передаче через PHP

По какой-то причине в Safari (и не в других крупных браузерах), когда я работаю с MP3 через PHP через Audio контекст в JavaScript, длительность MP3 всегда возвращается как infinity,

Эта проблема ставила меня в тупик в течение последних нескольких дней, и после прочтения нескольких ссылок (включая эту) в поисках решения я совсем не прогрессировал.


Мой код

PHP:

$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;

JavaScript:

var audio = new Audio(url);
// returns infinite on Safari
// returns 312.27311 on Chrome and Firefox (which is correct)
console.log(audio.duration);

Мне еще предстоит выяснить, почему эта проблема существует только в Safari и в чем ее причина, поэтому, если у кого-то есть решение, оно будет высоко оценено!

Приветствия.

1 ответ

После долгих исследований, как ты, я наконец-то понял это.

Первый запрос, отправляемый Safari, имеет заголовок:

Range: bytes=0-1

Ваша задача - отвечать "правильно", чтобы Safari отправлял дополнительные запросы для извлечения остальной части файла.

Вот мой пример "правильных" заголовков:

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)

То, что происходит после этого, несколько волшебно - Safari отправляет последующий запрос с таким заголовком:

Range: bytes=0-8468

И вы должны ответить "правильно", как с этими заголовками:

Content-Length: 8469
Accept-Ranges: bytes
Content-Range: bytes 0-8468/8469
(Again, status 206!)

Я надеюсь, что это решит это для вас, так как я провел много часов в поисках безрезультатно. В конце концов я понял, что мне нужно настроить свой сервер для обработки запросов, где присутствует заголовок Range.

Я использовал этот коммит, чтобы помочь мне понять, что такое "правильный" ответ: https://github.com/jooby-project/jooby/commit/142a933a31b9d8742714ecd38475d90e563314f7

Поскольку эта ветка появляется сначала в Google, позвольте мне поделиться своим опытом.

Как и многие, я генерирую mp3 через страницу php, в основном для того, чтобы "скрыть" настоящую ссылку на mp3. И для этого Safari сильно напрягает. Короче говоря, Safari рассматривает звук как "прямую трансляцию", и в итоге имеет эту "бесконечную" продолжительность. Что касается деталей, этот пост довольно хорошо объяснил, почему.

Так что делать? Вы должны поставить условия в заголовки вашей php-страницы, которые генерируют звук (как упомянуто @brianarpie). Вот моя страница php-generate-mp3:

<?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');

?>

.. и это все! эта функция будет генерировать правильные заголовки в зависимости от того, что запрашивает веб-браузер.

Конечно, вы проверили ссылки, вары и т. Д., Чтобы защитить страницу. Обратите внимание, что мой пример - mp3, поэтому мне нужно вызвать функцию с помощью audio/mpeg. Если вы выводите файл другого формата, вам придется адаптировать Тип содержимого функции.

Другие вопросы по тегам