Safari浏览器下使用H5视频播放问题的解决

         我们的项目,由于先做的安卓APP的开发,在安卓上测试视频播放通过以后。同样的接口放到IOS上是不能播放的。后来查了相关资料了解到其中的差别,总的来说,安卓上是请求一个视频链接,返回一整个视频文件。但是在IOS上,不是一次性请求全部文件的,一般首先会请求0-1字节,然后多次分段请求视频数据。

        所以首先要解析Request Headers里面的Range字段,获取本次请求的数据的初始位置、末端位置以及请求的数据大小,然然后需要在Response Headers中设置"Content-Type", "Content-Range", "Content-Length" 和"Accept-Range"这个几个参数的格式如下图所示。

 

 

"Content-Type"必需明确指定视频格式,有"video/mp4", "video/ogg", "video/mov"等等。

"Content-Range"格式是 "bytes <start>-<end>/<total>",其中start和end必需对应request header里的range字段,total是文件总大小,不是返回的数据长度。end是指inclusive end,像上图total=20472584 意味着文件长度是20472584 ,而end最大数值为20472583。

"Content-Length"指定返回的二进制长度,图中请求的是0-1字节,但是返回的2个字节,即0、1两个字节数据。Content-Length:(end-start+1)。

"Accept-Ranges"设置为bytes。

ios之所以分多次请求也有深层次原因。比方说先请求0-1字节(其实是2个字节),返回的时候数据并不多,但是可以通过分析"Content-Range"来获取文件总长度。然后分段请求。这样做有个好处就是,只有当用户点击播放了才请求完整文件,对于PC还好,对于手机这类数据传输需要收费的设备来说,必须要节省流量。另外在iphone上chrome也用的是apple提供的内核,导致他们的行为基本上一致。(这是苹果的规定)

另外,在response中最好始终设置StatusCode为206,之前设想视频是按照顺序依次请求,最后一次请求的响应信息想要设置为200,浏览器如果检测到StatusCode=200,则不会再发送下次数据请求。事实上视频请求是没有按照顺序请求的,如下图所示,最后一次是请求的第二部分数据,在最后一次的response中会返回416,整个视频是不能播放的。这是因为按照原先顺序请求的设想,设置第四部分视频请求响应信息StatusCode=200,之后的视频没有被请求,视频不完整,所以返回了416。

下面是代码部分,为.net上运行的代码,大家可以参考一下,自行改动

解析Range字段,获取请求数据的起始和终止位置

  var range = Request.Headers.Get("Range");
  var indexs = range != null ? range.Split('=')[1].Split('-') : null;
  var startIndex = indexs != null ? int.Parse(indexs[0]) : 0;
  var endIndex = indexs != null ? int.Parse(indexs[1]) : 0;

获取对应部分的数据数据

var fileMemoryStream = new MemoryStream(); //
fileMemoryStream = nb.ReadFromBufferStream(fileCode);//获取数据流,这里本文使用第三方网盘提供的接口获取的,大家可以根据各自的平台特点获取数据流
byte[] fileByte = new byte[fileByteLength] //这里的fileByteLength是返回数据的长度,fileByteLength=endIndex-startIndex+1
fileMemoryStream.Position = startIndex;
fileMemoryStream.Read(fileByte, 0, fileByte.Length);
fileMemoryStream.Flush();
fileMemoryStream.Close();

设置Response字段属性

Response.Headers.Add("Accept-Ranges", "bytes");
Response.Headers.Set("Content-Range", "bytes " + starIndex + "-" + endIndex + "/" + streamLength);
//streamLength 为整个数据的长度
Response.Headers.Set("Content-Length", fileByte.Length.ToString());

返回数据,本文场景中使用MVC,控制器继承了Controller。这里是接口要返回的数据,类型为ActionResult。

FileContentResult ret = File(fileByte, "video/mp4", fileCode);//这里的第二个参数相当于设置了Content-Type
return ret;

参考链接:

https://blog.csdn.net/bangbDIV/article/details/81912892

https://blog.csdn.net/zhengbin6072/article/details/78235004

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值