项目需要,使用了video.js做视频播放

import Video from ‘video.js’

import ‘video.js/dist/video-js.css’

前端代码

muted autoplay preload loop

poster="../assets/images/video.jpg"

>

其中source中的src为视频地址,这里用本地连接代替。

开始一切OK,非常顺利,本地模拟,现场测试都能正常播放,用一段时间发现苹果浏览器无法正常播放视频,因此查找原因:

1、首先充前端入手,看能否通过参数配置解决,解决办法如下:

muted autoplay preload loop

x5-video-player-fullscreen="true"

x5-playsinline

playsinline

webkit-playsinline

poster="../assets/images/video.jpg"

>

在video标准中加入如下代码:

x5-video-player-fullscreen="true"

x5-playsinline

playsinline

webkit-playsinline

测试结果不太满意,ios还是无法播放。

2、经多次查找网上信息,发现使用后台能解决该问题,解决点在HTTP协议的响应头里面(Accept-Ranges)。

3.safari浏览器,在打开视频的时候,先是发送一个请求探测文件的大小,之后再多次发送请求分段获取数据流的数据(个人理解大概是分段下载,Accept-Ranges)。

4、考虑方法1

a.需要根据请求内容的不同做出不同的响应,第一次探测请求需要返回200,后面的请求需要返回206和具体数据

b.contentType必须设置为video/mp4

5、具体视频地址代码

private void sendVideo(HttpServletRequest request, HttpServletResponse response, File file, String fileName) throws FileNotFoundException, IOException {

RandomAccessFile randomFile = new RandomAccessFile(file, "r");//只读模式

long contentLength = randomFile.length();

String range = request.getHeader("Range");

int start = 0, end = 0;

if(range != null && range.startsWith("bytes=")){

String[] values = range.split("=")[1].split("-");

start = Integer.parseInt(values[0]);

if(values.length > 1){

end = Integer.parseInt(values[1]);

}

}

int requestSize = 0;

if(end != 0 && end > start){

requestSize = end - start + 1;

} else {

requestSize = Integer.MAX_VALUE;

}

response.setContentType("video/mp4");

response.setHeader("Accept-Ranges", "bytes");

response.setHeader("ETag", fileName);

response.setHeader("Last-Modified", new Date().toString());

//第一次请求只返回content length来让客户端请求多次实际数据

if(range == null){

response.setHeader("Content-length", contentLength + "");

}else{

//以后的多次以断点续传的方式来返回视频数据

response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206

long requestStart = 0, requestEnd = 0;

String[] ranges = range.split("=");

if(ranges.length > 1){

String[] rangeDatas = ranges[1].split("-");

requestStart = Integer.parseInt(rangeDatas[0]);

if(rangeDatas.length > 1){

requestEnd = Integer.parseInt(rangeDatas[1]);

}

}

long length = 0;

if(requestEnd > 0){

length = requestEnd - requestStart + 1;

response.setHeader("Content-length", "" + length);

response.setHeader("Content-Range", "bytes " + requestStart + "-" + requestEnd + "/" + contentLength);

}else{

length = contentLength - requestStart;

response.setHeader("Content-length", "" + length);

response.setHeader("Content-Range", "bytes "+ requestStart + "-" + (contentLength - 1) + "/" + contentLength);

}

}

ServletOutputStream out = response.getOutputStream();

int needSize = requestSize;

randomFile.seek(start);

while(needSize > 0){

byte[] buffer = new byte[4096];

int len = randomFile.read(buffer);

if(needSize < buffer.length){

out.write(buffer, 0, needSize);

} else {

out.write(buffer, 0, len);

if(len < buffer.length){

break;

}

}

needSize -= buffer.length;

}

randomFile.close();

out.close();

}

6、source中的视频地址用次接口的视频地址,解决问题。