2013-05-31 2 views
2

Я играю с моим любимым проектом и, экспериментируя с mp3-потоком с PHP, я всегда получаю продолжительность звука для возврата Infinity. Я пытаюсь искать во многих местах, к сожалению, я не могу найти корневую проблему.HTML5 длительность аудио для mp3 всегда Бесконечность

Обратите внимание, что я должен был отложить этот проект на некоторое время, и все прошло хорошо. Когда я возобновил работу над проектом, я сделал некоторый рефактор 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. Все остальное, похоже, работает, включая воспроизведение, безупречно.

ответ

3

Я наконец нашел свое решение here. Мне пришлось слегка изменить код, и вот изменения. Теперь, если я могу полностью поддерживать несколько диапазонов, это будет полным.

(я делю это потому, что все что я вижу, неполные ответы. Будем надеяться, что это также поможет кому-то тоже.)

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

Здравствуйте, я получил ту же проблему, чем вы (продолжительность пейзажный для средств массовой информации) , Итак, я попробую ваше решение. Это фактически работает с mp3, но не OGG. Что я нашел, это то, что он работает, если браузер выполняет только один запрос (а не 2 или 3). Так что это не чистое потоковое вещание. Не могли бы вы помочь? – vekah

+0

Я избегал -1 на $ rangeTo var. Потоковая передача и музыка хорошо работают, но не больше продолжительности в музыке ... Я смущен! – vekah

+0

вопрос находится здесь: http://stackoverflow.com/questions/41013889/http-range-streaming-music-and-audio для кода и более подробного объяснения – vekah

Смежные вопросы