H5 Video播放视频iOS 断点下载处理
关于<video>标签所⽀持的视频格式和编码:
MP4 = MPEG 4⽂件使⽤ H264 视频编解码器和AAC⾳频编解码器
WebM = WebM ⽂件使⽤ VP8 视频编解码器和 Vorbis ⾳频编解码器
Ogg = Ogg ⽂件使⽤ Theora 视频编解码器和 Vorbis⾳频编解码器
所以在使用<video>前请确保文件格式和编码。
一:现象
在使用<video>播放视频时发现在iOS中无法播放,后台输出二进制流,ContentType = "video/mp4"。
但是直接返回一个.mp4的视频是可以播放的。说明视频格式没问题。
二:查找问题
查看客户端请求发现请求头中:
第一次请求时:Range:bytes=0-1。这是范围请求,相当于一个嗅探。要求后台必须有相应格式的返回信息。
Range:分段请求头,bytes=0-1 表示获取0-1的位置的2个字节。
这就要求服务器返回:
Accept-Ranges: bytes 接收字节请求
Content-Length: 2 相应长度
Content-Range: bytes 0-1/18494715 bytes后面的空格不能少,0开始位置,1结束位置。“/”后面的是文件总大小长度
HttpResponse
Status Code: 206 Partial Content 指示请求已成功并且主体包含所请求的数据范围
三:决解问题
知道了问题的所在
直接上代码
const bool allowMax = true; const long maxWriteLength = 3 * 1024 * 1024; //3M public void ProcessRequest(HttpContext context) { var Request = context.Request; var Response = context.Response; string sPath = Path.GetDirectoryName(Request.PhysicalPath); var reqRange = Request.Headers["Range"]; long fileLength = 0; string[] reqBlockRange = null; if (!string.IsNullOrWhiteSpace(reqRange)) { reqBlockRange = reqRange.Replace("bytes=", "").Split(new[] { "-" }, StringSplitOptions.RemoveEmptyEntries); Response.StatusCode = 206; } string fileName = "ShowVideo.mp4"; string filePath = Path.Combine(sPath, fileName); using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var reader = new BinaryReader(stream)) { fileLength = stream.Length; long startPosition = 0; long partialSize = fileLength; if (reqBlockRange != null) { startPosition = Convert.ToInt64(reqBlockRange[0]); if (reqBlockRange.Length > 1) { long endPosition = fileLength; if (long.TryParse(reqBlockRange[1], out endPosition)) { partialSize = endPosition - startPosition + 1; } } else { partialSize = fileLength - startPosition; } } if (allowMax && partialSize > maxWriteLength) { partialSize = maxWriteLength; } byte[] buffer = new byte[(int)partialSize]; reader.BaseStream.Seek(startPosition, SeekOrigin.Begin); reader.Read(buffer, 0, (int)partialSize); Response.AddHeader("Accept-Ranges", "bytes"); Response.ContentType = "video/mp4"; Response.AddHeader("Content-Range", $"bytes {startPosition}-{startPosition + partialSize - 1 }/{fileLength}"); Response.AddHeader("Content-Length", $"{partialSize}"); Response.BinaryWrite(buffer); } } Response.End(); }
四:扩展一下前端
使用腾讯的video插件:
<script src="https://web.sdk.qcloud.com/player/tcplayerlite/release/v2.4.1/TcPlayer-2.4.1.js" charset="utf-8"></script> <div id="id_test_video" style="width:100%; height:320px; "> </div> var playUrl = "/ShowVideo.ashx?SNID=" + SNID; var player = new TcPlayer('id_test_video', { "m3u8": playUrl, //"flv": "<%=""%>", //增加了一个 flv 的播放地址,用于PC平台的播放 请替换成实际可用的播放地址 "autoplay": true, //iOS 下 safari 浏览器,以及大部分移动端浏览器是不开放视频自动播放这个能力的 "poster": "../../../Images/Site/play.png", //封面 //"width" : '320',//视频的显示宽度,请尽量使用视频分辨率宽度 "height" : '320'//视频的显示高度,请尽量使用视频分辨率高度 });