HTML5音频mp3文件的持续时间总是无限。

3
我正在玩我的宠物项目,并尝试使用PHP进行mp3“流媒体”实验,但总是返回音频持续时间为Infinity。我已经尝试在许多地方搜索,但不幸的是,我似乎找不到根本问题所在。
请注意,我不得不暂时放下那个项目,之前一切都正常。当我重新开始工作该项目时,我进行了一些UI重构,并发现了这个“错误”。有人能看出我的代码有什么问题吗?
上下文:这是在一个控制器(ZF2)操作中,其中$media是一个POPO模型。
$file = $basePath . $media->getFileName();
$fileSize = filesize($file);
$fileHandle = fopen($file, 'r');

$etag = md5(serialize(fstat($fileHandle)));
$cacheExpires = new \DateTime();

// TODO : implement ranges...
if ( isset($_SERVER['HTTP_RANGE']) ) {

    // find the requested range
    // this might be too simplistic, apparently the client can request
    // multiple ranges, which can become pretty complex, so ignore it for now
    preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);

    $rangeFrom = intval($matches[1]);
    $rangeTo = intval($matches[2]);

    $statusCode = 206;
} else {
    $rangeFrom = 0;
    $rangeTo = $fileSize;
    $statusCode = 200;
}

fseek($fileHandle, $rangeFrom);

set_time_limit(0); // try to disable time limit

$response = new Stream();
$response->setStream($fileHandle);
$response->setStatusCode($statusCode);
$response->setStreamName(basename($file));

$headers = new Headers();
$headers->addHeaders(array(
    'Pragma' => 'public',
    'Expires' => $cacheExpires->format('Y/m/d H:i:s'),
    'Cache-Control' => 'no-cache',
    'Accept-Ranges' => 'bytes',
    'Content-Description' => 'File Transfer',
    'Content-Transfer-Encoding' => 'binary',
    'Content-Disposition' => 'attachment; filename="' . basename($file) .'"',
    'Content-Type' => 'audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3',  // $media->getFileType(),
    'Content-Range' => "bytes {$rangeFrom}-{$rangeTo}/{$fileSize}",
    'Content-Length' => $fileSize,
    'Etag' => $etag,
    'X-Pad' => 'avoid browser bug',
));
$response->setHeaders($headers);
return $response;

我尝试了几乎所有的HEADER字段(甚至删除了范围),但浏览器始终显示isFinite(audio.duration) === false。其它一切似乎都能正常工作,包括播放。
1个回答

3

我终于在这里找到了我的解决方案。我不得不稍微修改一下代码,以下是具体更改的内容。现在,如果我能完全支持多个范围,它就会完成。

(我分享这些信息是因为我看到的所有答案都不完整。希望它也能帮助其他人。)

$file = $basePath . $media->getFileName();
$fileSize = filesize($file);
$fileTime = date('r', filemtime($file));
$fileHandle = fopen($file, 'r');

$rangeFrom = 0;
$rangeTo = $fileSize - 1;
$etag = md5(serialize(fstat($fileHandle)));
$cacheExpires = new \DateTime();


if (isset($_SERVER['HTTP_RANGE'])) {
    if (!preg_match('/^bytes=\d*-\d*(,\d*-\d*)*$/i', $_SERVER['HTTP_RANGE'])) {
        $statusCode = 416;
    } else {
        $ranges = explode(',', substr($_SERVER['HTTP_RANGE'], 6));
        foreach ($ranges as $range) {
            $parts = explode('-', $range);

            $rangeFrom = intval($parts[0]); // If this is empty, this should be 0.
            $rangeTo = intval($parts[1]); // If this is empty or greater than than filelength - 1, this should be filelength - 1.

            if (empty($rangeTo)) $rangeTo = $fileSize - 1;

            if (($rangeFrom > $rangeTo) || ($rangeTo > $fileSize - 1)) {
                $statusCode = 416;
            } else {
                $statusCode = 206;
            }
        }
    }
} else {
    $statusCode = 200;
}

if ($statusCode == 416) {
    $response = $this->getResponse();

    $response->setStatusCode(416);  // HTTP/1.1 416 Requested Range Not Satisfiable
    $response->addHeaderLine('Content-Range', "bytes */{$fileSize}");  // Required in 416.

} else {

    fseek($fileHandle, $rangeFrom);

    set_time_limit(0); // try to disable time limit

    $response = new Stream();
    $response->setStream($fileHandle);
    $response->setStatusCode($statusCode);
    $response->setStreamName(basename($file));

    $headers = new Headers();
    $headers->addHeaders(array(
        'Pragma' => 'public',
        'Expires' => $cacheExpires->format('Y/m/d H:i:s'),
        'Cache-Control' => 'no-cache',
        'Accept-Ranges' => 'bytes',
        'Content-Description' => 'File Transfer',
        'Content-Transfer-Encoding' => 'binary',
        'Content-Disposition' => 'attachment; filename="' . basename($file) .'"',
        'Content-Type' => 'audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3',  // $media->getFileType(),
        'Content-Length' => $fileSize,
        'Last-Modified' => $fileTime,
        'Etag' => $etag,
        'X-Pad' => 'avoid browser bug',
    ));

    if ($statusCode == 206) {
        $headers->addHeaderLine('Content-Range', "bytes {$rangeFrom}-{$rangeTo}/{$fileSize}");
    }

    $response->setHeaders($headers);
}

return $response;

你好, 我遇到了和你一样的问题(媒体无限时长)。 所以我尝试了你的解决方案。实际上,这对于mp3是有效的,但不适用于OGG格式。 我发现,只有当浏览器仅发送一个请求(而不是2或3个)时,它才有效。因此这不是纯流媒体。你能帮忙吗? - vekah
我已经避免在$rangeTo变量上使用-1。流媒体和音乐工作正常,但音乐没有持续时间...我很困惑! - vekah
请访问以下链接以获取有关HTTP范围流式传输音乐和音频的代码和更多解释:http://stackoverflow.com/questions/41013889/http-range-streaming-music-and-audio - vekah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接