这篇文章主要为大家展示了“怎么在Html5使用数据流播放视频”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“怎么在Html5使用数据流播放视频”这篇文章吧。

H5页面可以通过<video> 标签来播放视频。一般的方式如下:

<!DOCTYPEHTML><html><body><videosrc="/i/movie.mp4"controls="controls">yourbrowserdoesnotsupportthevideotag</video></body></html>

src中指定了要播放的视频的URL,为具体的视频文件路径。当将访问请求变为getVideo.do?fileId=xxx 这种形式,服务端返回字节流的时候后端实现需要一些更改。

一般的方式是读本地文件然后写到response中,代码实现如下:

publicvoiddownFile(FiledownloadFile,HttpServletResponseresponse,HttpServletRequestrequest)throwsException{response.reset();response.setContentType("video/mp4;charset=UTF-8");InputStreamin=null;ServletOutputStreamout=null;try{out=response.getOutputStream();in=newFileInputStream(downloadFile);if(in!=null){byte[]b=newbyte[1024];inti=0;while((i=in.read(b))>0){out.write(b,0,i);}out.flush();in.close();}}catch(Exceptione){e.printStackTrace();}finally{if(in!=null){try{in.close();}catch(IOExceptione){}in=null;}if(out!=null){try{out.close();}catch(IOExceptione){}out=null;}}}

这种方式在PC端和Android手机上都能正常显示,但在IOS手机上通过Safari浏览器就不能播放。ios目前获取视频的时候请求头会带一个与断点续传有关的信息。对于ios来说,他不是一次性请求全部文件的,一般首先会请求0-1字节,这个会写在request header的"range"字段中:range:‘bytes=0-1’。
而服务端必须满足range的要求:解析range字段,然后按照range字段的要求返回对应的数据。

在响应头中response header至少要包含三个字段:

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

Content-Range:格式是 “bytes <start>-<end>/<total>”,其中start和end必需对应request header里的range字段,total是文件总大小。

Content-Length:返回的二进制长度。

断点续传实现如下:

publicvoiddownRangeFile(FiledownloadFile,HttpServletResponseresponse,HttpServletRequestrequest)throwsException{if(!downloadFile.exists()){response.sendError(HttpServletResponse.SC_NOT_FOUND);return;}longfileLength=downloadFile.length();//记录文件大小longpastLength=0;//记录已下载文件大小intrangeSwitch=0;//0:从头开始的全文下载;1:从某字节开始的下载(bytes=27000-);2:从某字节开始到某字节结束的下载(bytes=27000-39000)longcontentLength=0;//客户端请求的字节总量StringrangeBytes="";//记录客户端传来的形如“bytes=27000-”或者“bytes=27000-39000”的内容RandomAccessFileraf=null;//负责读取数据OutputStreamos=null;//写出数据OutputStreamout=null;//缓冲intbsize=1024;//缓冲区大小byteb[]=newbyte[bsize];//暂存容器Stringrange=request.getHeader("Range");intresponseStatus=206;if(range!=null&&range.trim().length()>0&&!"null".equals(range)){//客户端请求的下载的文件块的开始字节responseStatus=javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT;System.out.println("request.getHeader("Range")="+range);rangeBytes=range.replaceAll("bytes=","");if(rangeBytes.endsWith("-")){rangeSwitch=1;rangeBytes=rangeBytes.substring(0,rangeBytes.indexOf('-'));pastLength=Long.parseLong(rangeBytes.trim());contentLength=fileLength-pastLength;}else{rangeSwitch=2;Stringtemp0=rangeBytes.substring(0,rangeBytes.indexOf('-'));Stringtemp2=rangeBytes.substring(rangeBytes.indexOf('-')+1,rangeBytes.length());pastLength=Long.parseLong(temp0.trim());}}else{contentLength=fileLength;//客户端要求全文下载}//清除首部的空白行response.reset();//告诉客户端允许断点续传多线程连接下载,响应的格式是:Accept-Ranges:bytesresponse.setHeader("Accept-Ranges","bytes");//如果是第一次下,还没有断点续传,状态是默认的200,无需显式设置;响应的格式是:HTTP/1.1if(rangeSwitch!=0){response.setStatus(responseStatus);//不是从最开始下载,断点下载响应号为206//响应的格式是://Content-Range:bytes[文件块的开始字节]-[文件的总大小-1]/[文件的总大小]switch(rangeSwitch){case1:{StringcontentRange=newStringBuffer("bytes").append(newLong(pastLength).toString()).append("-").append(newLong(fileLength-1).toString()).append("/").append(newLong(fileLength).toString()).toString();response.setHeader("Content-Range",contentRange);break;}case2:{StringcontentRange=range.replace("=","")+"/"+newLong(fileLength).toString();response.setHeader("Content-Range",contentRange);break;}default:{break;}}}else{StringcontentRange=newStringBuffer("bytes").append("0-").append(fileLength-1).append("/").append(fileLength).toString();response.setHeader("Content-Range",contentRange);}try{response.setContentType("video/mp4;charset=UTF-8");response.setHeader("Content-Length",String.valueOf(contentLength));os=response.getOutputStream();out=newBufferedOutputStream(os);raf=newRandomAccessFile(downloadFile,"r");try{longoutLength=0;//实际输出字节数switch(rangeSwitch){case0:{}case1:{raf.seek(pastLength);intn=0;while((n=raf.read(b))!=-1){out.write(b,0,n);outLength+=n;}break;}case2:{raf.seek(pastLength);intn=0;longreadLength=0;//记录已读字节数while(readLength<=contentLength-bsize){//大部分字节在这里读取n=raf.read(b);readLength+=n;out.write(b,0,n);outLength+=n;}if(readLength<=contentLength){//余下的不足1024个字节在这里读取n=raf.read(b,0,(int)(contentLength-readLength));out.write(b,0,n);outLength+=n;}break;}default:{break;}}System.out.println("Content-Length为:"+contentLength+";实际输出字节数:"+outLength);out.flush();}catch(IOExceptionie){//ignore}}catch(Exceptione){e.printStackTrace();}finally{if(out!=null){try{out.close();}catch(IOExceptione){e.printStackTrace();}}if(raf!=null){try{raf.close();}catch(IOExceptione){e.printStackTrace();}}}}

H5页面:

<!DOCTYPEHTML><html><body><videowidth="100%"height="200"rel="preload"x5-video-player-type="h6"playsinline="true"webkit-playsinline="true"controls="controls"><sourcesrc="http://127.0.0.1:8080/XXX/getVideo.do?fileId=16"type="video/mp4"></video></script></body></html>

通过上述断点续传方式H5可正常播放视频数据流,并且支持各种平台。

以上是“怎么在Html5使用数据流播放视频”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!