#ios #networking #safari #html5-audio
#iOS #сетевой #сафари #html5-аудио
Вопрос:
Я работаю над проблемой iOS/macOS.
Я пытаюсь воспроизвести простой аудиофайл с помощью аудиоэлемента HTML5, и все работает так, как ожидалось, за исключением iOS/macOS.
Мое приложение построено на Symfony, используя Nginx и пользовательские контроллеры PHP для обслуживания аудиоресурса. Указанный источник аудиоэлемента является ссылкой на маршрут, который обрабатывает потоковую передачу.
Моя логика заключается в следующем :
- Получить файл по идентификатору URL
- Прочитайте заголовки запросов, чтобы найти ожидаемый диапазон и длину
- Настройка хороших заголовков для принудительного 206 частичного поведения содержимого
- Запись ожидаемых фрагментов файлов и возврат ответа 206.
Вот код для этого:
public function getAudio(Request $request, $audioId) { /* * Getting the file */ $em = $this-gt;getDoctrine()-gt;getManager(); $voice = $em-gt;getRepository("CoreBundle:Audio")-gt;findOneById($audioId); $media = $audio-gt;getFile(); $path = $this-gt;container-gt;get('sonata.media.twig.extension')-gt;path($media, 'reference'); $file = $this-gt;get('kernel')-gt;getRootDir() . "/../web$path"; /* * Setting length and offset for serving the right chunk */ $offset = 0; $requestedRange = $request-gt;headers-gt;get("Range"); $size = $media-gt;getSize(); $length = $size; if($requestedRange){ preg_match('/bytes=(d )-(d )?/', $requestedRange, $matches); $offset = intval($matches[1]); if(count($matches) gt; 2){ $length = intval($matches[2]) - $offset 1; } else{ $length = ($size) - $offset; } } if(file_exists($file) amp;amp; $length) { $file = fopen($file, 'r'); fseek($file, $offset); $data = fread($file, $length); fclose($file); if($requestedRange){ header('Content-Range: bytes ' . $offset . '-' . ($offset $length-1) . '/' . $size); } else{ header('Content-Range: bytes 0-'.($size-1).'/'.$size); } /* * Forcing some headers in the response to fit request attempts */ header("Pragma: public"); header("Expires: 0"); header('Content-type: audio/mpeg'); header('Content-Disposition: inline'); header('Accept-Ranges: bytes'); header('Content-Length: '.$length); header('X-Pad: avoid browser bug'); header('Cache-Control: no-cache'); print($data); return new Response("",206); } else{ return new Response("",200); } }
Опять же, в Firefox и Chrome все работает нормально, файл передается в потоковом режиме и воспроизводится идеально. Но когда дело доходит до IOS и macOS, файл просто не воспроизводится. Беглый взгляд на сетевую консоль показывает два последующих запроса, последний из которых содержит ошибку (см. Следующие ссылки).
Однако в PHP не регистрируется никаких ошибок, и теперь я полностью застрял.
Ответ №1:
Логика была прекрасной, но управление ответом-нет.
Прочитав документацию по Symfony Response
, я просто изменил все header()
функции на:
$response-gt;setHeaders()
И каждый print($data)
, чтобы:
$response = new Response($data);
Возврат полного Response
объекта выполнил свою работу.