Mac 和 IOS 14 上的 Safari 无法播放 HTML 5 MP4 视频

如何解决Mac 和 IOS 14 上的 Safari 无法播放 HTML 5 MP4 视频

所以我开发了一个使用节点作为后端的聊天应用程序。当用户在他们的 iphone 上选择一个视频时,它通常是 .mov 格式,所以当它被发送到节点服务器时,它会使用 ffmpeg 转换为 mp4。一切正常,然后如果我在 Mac 上的 Chrome 中再次加载我的聊天,视频会像 mp4 一样播放。

enter image description here

此屏幕截图显示视频嵌入在那里,设置为 mp4 但它不会在我的 Mac 或我的手机上的 Safari 中播放,实际上它只是将视频显示为 0 秒长,但我可以在 chrome 中播放它,也可以直接访问嵌入网址下载mp4文件。

有什么想法吗?我已将其转换为 mp4 以防止出现此类情况,但 safari 似乎甚至不喜欢 mp4 文件。

服务私有文件的后端部分在 Symfony 4 (PHP) 中:

/**
     * @Route("/private/files/download/{base64Path}",name="downloadFile")
     * @param string $base64Path
     * @param Request $request
     * @return Response
     */
    public function downloadFile(string $base64Path,Request $request) : Response
    {


        // get token
        if(!$token = $request->query->get('token')){
            return new Response('Access Denied',403);
        }



        /** @var UserRepository $userRepo */
        $userRepo = $this->getDoctrine()->getRepository(User::class);

        /** @var User $user */
        if(!$user = $userRepo->findOneBy(['deleted'=>false,'active'=>true,'systemUser'=>false,'apiKey'=>$token])){
            return new Response('Access Denied',403);
        }



        // get path
        if($path = base64_decode($base64Path)){

            // make sure the folder we need exists
            $fullPath = $this->getParameter('private_upload_folder') . '/' . $path;



            if(!file_exists($fullPath)){
                return new Response('File Not Found',404);
            }

        

            $response = new Response();
            $response->headers->set('Content-Type',mime_content_type($fullPath));
            $response->headers->set('Content-Disposition','inline; filename="' . basename($fullPath) . '"');
            $response->headers->set('Content-Length',filesize($fullPath));
            $response->headers->set('Pragma',"no-cache");
            $response->headers->set('Expires',"0");
            $response->headers->set('Content-Transfer-Encoding',"binary");

            $response->sendHeaders();

            $response->setContent(readfile($fullPath));

            return $response;
        }

        return new Response('Invalid Path',404);
    }

在尝试嵌入视频时,除了 safari 之外,这在任何地方都可以正常工作。这样做是因为视频不是公开的,需要访问令牌。

更新:这是一个 mp4 的测试链接,您必须允许不安全的证书,因为它位于快速测试子域中。如果你用 chrome 打开它,你会看到我的 3d 打印机固化站的 3 秒视频,如果你在 safari 中加载相同的链接,你会看到它不起作用

https://tester.nibbrstaging.com/private/files/download/Y2hhdC83Nzk1Y2U2MC04MDFmLTExZWItYjkzYy1lZjI4ZGYwMDhkOTMubXA0?token=6ab1720bfe922d44208c25f655d61032

服务器在带有 Apache 的 cPanel 上运行,我认为这可能与视频需要流式传输有关?

在 SAFARI 中有效但现在在 Chrome 中损坏的更新代码:

Chrome 现在提供 Content-Length: 0 但它在 safari 中运行良好。

public function downloadFile(string $base64Path,Request $request) : ?Response
    {

        ob_clean();

        // get token
        if(!$token = $request->query->get('token')){
            return new Response('Access Denied',403);
        }


        

        /** @var UserRepository $userRepo */
        $userRepo = $this->getDoctrine()->getRepository(User::class);

        /** @var User $user */
        if(!$user = $userRepo->findOneBy(['deleted'=>false,404);
            }


            $filesize = filesize($fullPath);
            $mime = mime_content_type($fullPath);

            header('Content-Type: ' . $mime);

            if(isset($_SERVER['HTTP_RANGE'])){

                // Parse the range header to get the byte offset
                $ranges = array_map(
                    'intval',// Parse the parts into integer
                    explode(
                        '-',// The range separator
                        substr($_SERVER['HTTP_RANGE'],6) // Skip the `bytes=` part of the header
                    )
                );



                // If the last range param is empty,it means the EOF (End of File)
                if(!$ranges[1]){
                    $ranges[1] = $filesize - 1;
                }

                header('HTTP/1.1 206 Partial Content');
                header('Accept-Ranges: bytes');
                header('Content-Length: ' . ($ranges[1] - $ranges[0])); // The size of the range

                // Send the ranges we offered
                header(
                    sprintf(
                        'Content-Range: bytes %d-%d/%d',// The header format
                        $ranges[0],// The start range
                        $ranges[1],// The end range
                        $filesize // Total size of the file
                    )
                );

                // It's time to output the file
                $f = fopen($fullPath,'rb'); // Open the file in binary mode
                $chunkSize = 8192; // The size of each chunk to output

                // Seek to the requested start range
                fseek($f,$ranges[0]);

                // Start outputting the data
                while(true){
                    // Check if we have outputted all the data requested
                    if(ftell($f) >= $ranges[1]){
                        break;
                    }

                    // Output the data
                    echo fread($f,$chunkSize);

                    // Flush the buffer immediately
                    @ob_flush();
                    flush();
                }
            }else{

                // It's not a range request,output the file anyway
                header('Content-Length: ' . $filesize);

                // Read the file
                @readfile($filesize);

                // and flush the buffer
                @ob_flush();
                flush();



            }

        }else {

            return new Response('Invalid Path',404);
        }
    }

我在 chrome 中注意到它正在发送这样的范围标头:

范围:字节=611609-

Safari 发送到哪里

范围:字节=611609-61160

因此,出于某种原因,chrome 缺少第二个范围数量,这显然意味着我的代码无法找到第二个的范围编号。

不管我做什么,我都无法在 chrome 和 safari 中使用它。 Safari 需要字节范围部分,chrome 似乎请求它然后发送对完整文件的新请求,但即使代码的完整文件部分也会出现 500 错误。如果我取出字节范围位,那么它在 chrome 中可以正常工作,但在 safari 中不能正常工作。

更新:

Chrome 中发生了一些奇怪的事情:

对于我正在测试的视频,它发出了 3 个范围请求:

REQUEST 1 HEADERS - 请求字节 0-(到文件末尾)

GET /private/files/download/Y2hhdC83Nzk1Y2U2MC04MDFmLTExZWItYjkzYy1lZjI4ZGYwMDhkOTMubXA0?token=6ab1720bfe922d44208c25f655d61032 HTTP/1.1

Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/88.0.4324.192 Safari/537.36
Accept-Encoding: identity;q=1,*;q=0
Accept: */*
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: video
Referer: https://gofollow.vip/
Accept-Language: en-US,en;q=0.9
Range: bytes=0-

响应会返回文件中的所有字节,这正是 Chrome 所要求的:

HTTP/1.1 206 Partial Content
Date: Wed,10 Mar 2021 12:35:54 GMT
Server: Apache
Accept-Ranges: bytes
Content-Length: 611609
Content-Range: bytes 0-611609/611610
Vary: User-Agent
Keep-Alive: timeout=5,max=100
Connection: Keep-Alive
Content-Type: video/mp4

第二个请求头:现在要求 589824 到文件末尾:

Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML,en;q=0.9
Range: bytes=589824-

响应义务:

HTTP/1.1 206 Partial Content
Date: Wed,10 Mar 2021 12:35:55 GMT
Server: Apache
Accept-Ranges: bytes
Content-Length: 21785
Content-Range: bytes 589824-611609/611610
Vary: User-Agent
Keep-Alive: timeout=5,max=99
Connection: Keep-Alive
Content-Type: video/mp4

然后它发出的第 3 个请求会导致内部服务器出错,这一次实际上是在请求最后一个字节:

GET /private/files/download/Y2hhdC83Nzk1Y2U2MC04MDFmLTExZWItYjkzYy1lZjI4ZGYwMDhkOTMubXA0?token=6ab1720bfe922d44208c25f655d61032 HTTP/1.1

Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML,en;q=0.9
Range: bytes=611609-

响应 - 内容长度为 0,因为请求的字节数和返回的字节数没有区别:

HTTP/1.1 500 Internal Server Error
Date: Wed,10 Mar 2021 12:35:56 GMT
Server: Apache
Accept-Ranges: bytes
Cache-Control: max-age=0,must-revalidate,private
X-Frame-Options: DENY
X-XSS-Protection: 1
X-Content-Type-Options: nosniff
Referrer-Policy: origin
Strict-Transport-Security: max-age=31536000; includeSubDomains
Expires: Wed,10 Mar 2021 12:35:56 GMT
Content-Length: 0
Content-Range: bytes 611609-611609/611610
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8

解决方法

毕竟我终于找到了问题所在。它要求第三个请求中的最后一个字节和以下代码来计算发回内容的大小:

header('Content-Length: ' . ($ranges[1] - $ranges[0])); // The size of the range

生成的长度为 0 作为最后一个字节,直到文件末尾变为 0。所以我将其更改为加 1 到末尾:

header('Content-Length: ' . (($ranges[1] - $ranges[0])+1)); // The size of the range

我以为我可能会遇到这个问题,但事实证明它适用于两种浏览器

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res