Safari 音频 HTML5 问题

Posted

技术标签:

【中文标题】Safari 音频 HTML5 问题【英文标题】:Safari audio HTML5 issue 【发布时间】:2022-01-08 05:03:09 【问题描述】:

我正在处理 ios/MacOS 问题。

我正在尝试通过 html5 音频元素播放一个简单的音频文件,除 iOS/MacOS 外,一切正常。

我的应用基于 Symfony 构建,使用 nginx 和自定义 php 控制器来提供音频资源。音频元素的给定源是指向处理流的路由的链接。

我的逻辑如下:

从 url ID 获取文件 读取请求标头以查找预期范围和长度 设置好的标题以强制 206 部分内容行为 正在写入预期的文件块并返回 206 响应。

下面是代码:

public function getAudio(Request $request, $audioId)
    
            /*
             * Getting the file
             */
            $em = $this->getDoctrine()->getManager();
            $voice = $em->getRepository("CoreBundle:Audio")->findOneById($audioId);
            $media = $audio->getFile();
            $path = $this->container->get('sonata.media.twig.extension')->path($media, 'reference');
            $file = $this->get('kernel')->getRootDir() . "/../web$path";

            /*
             * Setting length and offset for serving the right chunk
             */
            $offset = 0;
            $requestedRange = $request->headers->get("Range");
            $size = $media->getSize();
            $length = $size;

            if($requestedRange)
                preg_match('/bytes=(\d+)-(\d+)?/', $requestedRange, $matches);
                $offset = intval($matches[1]);
                if(count($matches) > 2)
                    $length = intval($matches[2]) - $offset + 1;
                
                else
                    $length = ($size) - $offset;
                
            

            if(file_exists($file) && $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 中没有记录任何错误,我现在完全卡住了。

first-request

second-request

【问题讨论】:

【参考方案1】:

逻辑很好,但响应的管理不是。

在阅读了有关 Response 的 Symfony 文档后,我只是将每个 header() 函数更改为:

$response->setHeaders()

每个print($data) 到:

$response = new Response($data);

返回完整的 Response 对象完成了这项工作。

【讨论】:

以上是关于Safari 音频 HTML5 问题的主要内容,如果未能解决你的问题,请参考以下文章

在 Safari 中使用 html5/js 音频时出现问题(Windows)

在 Safari 中多次播放 HTML5 音频时出现问题

Safari 11 对 HTML5 音频的新自动播放限制

HTML5 音频播放器适用于 safari/Chrome,但不适用于 iPhone

在 SAFARI 中使用带有表单身份验证的 HTML5 音频

移动 safari 似乎在导航后卸载 html5 音频/视频