最近在做一个微信企业号的项目,其中有一个需求是在企业号的页面中播放视频,最开始是使用video标签直接加载视频地址,结果在android手机中能正常播放,但在ios手机中无法播放。
在ios中的症状是视频一直是加载状态,但就是加载不进来。
在此感谢同事帮我找到一篇文章,
地址是 https://www.zhihu.com/question/41818719,
我的视频加载不进来的原因比较符合这一篇文章:
https://blog.csdn.net/zhengbin6072/article/details/78235004
下面是我的解决方法:
router.all('/video-play', async (ctx: Context, next: Function) => {
let { url } = ctx.query; //接收视频地址
let list = url.split('uploads');
let path = '/public/uploads' + list[1]; //组合出视频在本地的地址
if (!path.startsWith('/uploads') && !path.toLocaleLowerCase().endsWith('.mp4')) {
await next();
return;
}
// 对视频请求长度的处理
function getRange(range: string, stats: any) {
let r = range.match(/=(\d+)-(\d+)?/);
let start = r[1];
let end = r[2] || stats.size - 1;
return [parseInt(String(start)) || 0, parseInt(String(end))];
}
let stats = fs.statSync(process.cwd() + path); // fs获取视频文件的状态
let [start, end] = getRange(ctx.headers['range'], stats);
ctx.set('Content-Range', `bytes ${start}-${end}/${stats.size}`); //设置返回头
ctx.set('Content-Type', 'video/mp4');
ctx.set('Content-Length', String(end === start ? 0 : end - start + 1));
ctx.status = 206; // 设置返回状态 这个貌似必须是206,如果是200,视频又没有请求完成,就不会再请求下一次了
ctx.body = fs.createReadStream(process.cwd() + path, { start, end }); // 返回视频流
});
我的代码使用的是alaska框架,alaska框架依赖于koa2,
这段代码是在后台开了一个接口,用于视频的请求,参数接收一个url,url是视频播放地址,因为视频是直接传到我的服务器上的,所以对于后台来说,视频是在本地,所以直接用fs读取了。
前端调用:
<video
src={`/video-play?url=${encodeURIComponent(postDetail.video)}`}
controls
autoPlay
width="100%"
></video>
我的前端代码是用react写的,所以controls等属性要设置为true,可以省略值的部分。
如果需要自动播放,不要全屏播放等请另行查阅资料。谢谢。
完