对于mp3的HTML5音频持续时间永远是无限的 [英] HTML5 audio duration for mp3 is always Infinity
问题描述
我正在玩我的宠物项目,并尝试用PHP流式传输,我总是得到音频持续时间返回 Infinity
。我试图在很多地方进行搜索,不幸的是,我似乎无法找到根本问题。
请注意,我必须搁置一段时间的项目,之前一切正常。当我重新开始工作时,我做了一些UI重构,并发现了这个bug。任何人都可以发现我的代码有问题吗?
上下文:这是一个控制器(ZF2)动作,其中 $ media
是 POPO 模型。
$ file = $ basePath。 $媒体 - >的getFileName();
$ fileSize = filesize($ file);
$ fileHandle = fopen($ file,'r');
$ etag = md5(serialize(fstat($ fileHandle)));
$ cacheExpires = new \DateTime();
// TODO:执行范围...
if(isset($ _ SERVER ['HTTP_RANGE'])){
//找到请求的范围
//这可能太简单了,显然客户端可以请求
//多个范围,这可能会变得非常复杂,所以现在忽略它
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); //尝试禁用时间限制
$ response = new Stream();
$ response-> setStream($ fileHandle);
$ response-> setStatusCode($ statusCode);
$ response-> setStreamName(basename($ file));
$ headers = new Headers();
$ headers-> addHeaders(数组(
'Pragma'=>'public',
'Expires'=> $ cacheExpires->格式('Y / m / d H:i:s'),
'Cache-Control'=>'no-cache',
'Accept-Ranges'=>'bytes',
'Content-Description '=>'文件传输',
'Content-Transfer-Encoding'=>'binary',
'Content-Disposition'=>'attachment; filename =''。basename($文件)''',
'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'=>'避免浏览器错误',
));
$ response-> setHeaders($ headers);
返回$ response;
我尝试过玩几乎所有HEADER字段(甚至删除范围),但浏览器总是得到 isFinite(audio.duration)=== false
。一切似乎都起作用,包括播放,完美无瑕。
我终于找到了我的解决方案here 。我不得不稍微更改代码,以下是更改。现在,如果我可以完全支持多个范围,它就会完整。
(我正在分享这个,因为我看到的都是不完整的答案。希望它也会)
$ file = $ basePath。 $媒体 - >的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; ($ _ $ SERVER ['HTTP_RANGE'],6));
foreach($ ranges为$ range){
$ parts = explode(' - ',$ range);
$ rangeFrom = intval($ parts [0]); //如果这是空的,这应该是0.
$ rangeTo = intval($ parts [1]); //如果这是空的或大于filelength - 1,这应该是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请求的范围不满足
$ response-> addHeaderLine('Content-Range',bytes * / {$ fileSize}); //必须在416.
} else {
fseek($ fileHandle,$ rangeFrom);
set_time_limit(0); //尝试禁用时间限制
$ response = new Stream();
$ response-> setStream($ fileHandle);
$ response-> setStatusCode($ statusCode);
$ response-> setStreamName(basename($ file));
$ headers = new Headers();
$ headers-> addHeaders(数组(
'Pragma'=>'public',
'Expires'=> $ cacheExpires->格式('Y / m / d H:i:s'),
'Cache-Control'=>'no-cache',
'Accept-Ranges'=>'bytes',
'Content-Description '=>'文件传输',
'Content-Transfer-Encoding'=>'binary',
'Content-Disposition'=>'attachment; filename =''。basename($文件)''',
'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'=>'避免浏览器错误',
));
if($ statusCode == 206){
$ headers-> addHeaderLine('Content-Range',bytes {$ rangeFrom} - {$ rangeTo} / {$ fileSize} );
}
$ response-> setHeaders($ headers);
}
返回$ response;
I'm playing with my pet project and, experimenting with mp3 "streaming" with PHP, I always get the audio duration to return Infinity
. I've try to search in many places, unfortunately, I can't seem to find the root problem.
Note that I had to put that project aside for a while, and everything worked fine before. When I restarted working on the project, I did some UI refactor and found out about this "bug". Can anyone spot something wrong with my code?
Context : this is in a controller (ZF2) action, where $media
is a POPO model.
$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;
I have tried playing with almost every HEADER fields (even removing the ranges), but the browser always gets isFinite(audio.duration) === false
. Everything else seems to work, including playback, flawlessly.
I finally found my solution here. I had to slightly change the code, and here are the changes. Now, if I can fully support multiple ranges, it'll be complete.
(I'm sharing this because all I see are incomplete answers. Hopefully, it will also help someone too.)
$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的HTML5音频持续时间永远是无限的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!