通过PHP流式传输时,Safari中的音频持续时间始终返回无穷大

时间:2019-04-07 09:59:39

标签: javascript php

出于某种原因(在Safari中,并且没有其他主流浏览器),当我通过 PHP 通过 JavaScript 中的Audio上下文提供MP3时,持续时间总是以infinity的形式返回MP3。

这个问题困扰了我最近几天,在阅读了一些链接(包括this个链接)以寻找解决方案之后,我根本没有进步。


我的代码

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中以及首先是什么原因引起的,因此,如果有人有解决方案,将不胜感激!

干杯。

2 个答案:

答案 0 :(得分:3)

经过像你这样的大量调查,我终于弄清楚了。

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

答案 1 :(得分:1)

此线程首先在Google中弹出,请允许我分享我的经验。

和许多人一样,我通过php页面生成mp3,主要是为了“隐藏” mp3的真实链接。为此,Safari非常令人讨厌。简而言之,Safari将声音视为“实时广播”,最终具有“无限”的持续时间。有关详细信息,this post很好地解释了原因。

那该怎么办?您必须在生成声音的php页面标题上放置条件(如@brianarpie所述)。这是我的php-generating-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”调用该函数。如果输出其他文件格式,则必须调整该函数的内容类型。