一、需求:
后端返回包含视频链接的数组对象,格式如下:
[
{
url: 'xxxxx.mp4',
},
{
url: 'xxxxx.mp4',
},
{
url: 'xxxxx.mp4',
},
]
从上面的mp4视频中截取一帧设置为封面,如下图,下面的封面图从视频中截取而来。
二、代码实现:
<script>
export default {
onLoad()
this.getViedoList();
},
data() {
return{
videoLists:[], // 获取到的视频列表数组
posterList: [] ,// 视频封面图数组
}
},
methods: {
getViedoList(){
this.$uniReq({
url:"doc/api/doc's/@freevideo",
method:"GET",
}).then((re)=>
this.videoLists = re
this.createPoster();
}).catch((err)=>{
console.log(err);
})
}
createPoster() { // 截取封面 封装函数
var videoCanList = []
this.videoLists.forEach((item,index) => {
var promise = new Promise((reslove, reject) => {
// 在缓存中创建video标签
var video = document.createElement("VIDEO")
// 通过setAttribute给video dom元素添加自动播放的属性,因为视频播放才能获取封面图
video.currentTime = 1; // 截取视频的第1秒
video.setAttribute('crossOrigin', 'anonymous');
video.setAttribute('autoplay', 'autoplay')
// 再添加一个静音的属性,否则自动播放会有声音
video.setAttribute('muted', 'muted')
// 上面我们只是创建了video标签,视频播放需要内部的source的标签,scr为播放源
video.innerHTML = '<source src=' + item.url + ' type="audio/mp4">'
// 再创建canvas画布标签
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// video注册canplay自动播放事件
video.addEventListener('canplay', function() {
// 创建画布的宽高属性节点,就是图片的大小,单位PX
var anw = document.createAttribute("width");
anw.nodeValue = 500;
var anh = document.createAttribute("height");
anh.nodeValue = 300;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
// 画布渲染
ctx.drawImage(video, 0, 0, 500, 300);
// 生成图片
var base64 = canvas.toDataURL('image/png') // 这就是封面图片的base64编码
// 视频结束播放的事件
video.pause()
reslove(base64) // promise函数成功的回调
}, false)
})
videoCanList.push(promise)
})
Promise.all(videoCanList).then(res => {
this.posterList = res
})
}
}
}
</script>
按照上面的代码,其中posterList就是对应的每一个视频的封面base64数组,一切看起来都挺好,在H5正常运行,但是在APP端使用,明显是不可以的,因为在app端,document为undefined,那么怎么弄呢,查阅了资料,发现使用renderjs即可以识别。
<view class='healthPromotion' :videoLists="videoLists" :change:videoLists="renderScript.createPoster"></view>
<script>
export default {
onLoad()
this.getViedoList();
},
data() {
return{
videoLists:[], // 获取到的视频列表数组
posterList: [] ,// 视频封面图数组
}
},
methods: {
getViedoList(){
this.$uniReq({
url:"doc/api/doc's/@freevideo",
method:"GET",
}).then((re)=>
this.videoLists = re
}).catch((err)=>{
console.log(err);
})
},
reciveMessage(val) {
this.posterList = val
}
}
}
</script>
<script module="renderScript" lang="renderjs">
export default {
methods: {
createPoster(val) {
var videoCanList = [],curDateList = []
val.forEach((item,index) => {
var promise = new Promise((reslove, reject) => {
// 在缓存中创建video标签
var video = document.createElement("VIDEO")
// 通过setAttribute给video dom元素添加自动播放的属性,因为视频播放才能获取封面图
video.currentTime = 5
video.setAttribute('crossOrigin', 'anonymous');
video.setAttribute('autoplay', 'autoplay')
// 再添加一个静音的属性,否则自动播放会有声音
video.setAttribute('muted', 'muted')
// 上面我们只是创建了video标签,视频播放需要内部的source的标签,scr为播放源
video.innerHTML = '<source src=' + item.url + ' type="audio/mp4">'
// 再创建canvas画布标签
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// video注册canplay自动播放事件
video.addEventListener('canplay', function() {
// 创建画布的宽高属性节点,就是图片的大小,单位PX
var anw = document.createAttribute("width");
anw.nodeValue = 500;
var anh = document.createAttribute("height");
anh.nodeValue = 300;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
// 画布渲染
ctx.drawImage(video, 0, 0, 500, 300);
// 生成图片
var base64 = canvas.toDataURL('image/png') // 这就是封面图片的base64编码
// 视频结束播放的事件
video.pause()
curDateList.unshift({ // 这里是我自己的数据处理模块
type: 'video',
videoUrl: item.url,
img: base64
})
reslove(base64) // promise函数成功的回调
}, false)
})
videoCanList.push(promise)
})
Promise.all(videoCanList).then(res => {
this.$ownerInstance.callMethod('reciveMessage', res)
})
},
}
}
</script>
1)当 videoLists变化时,通过 :change:videoLists=”renderScript.createPoster”这一段代码, renderjs 中的createPoster被调用
2)renderjs给script传递数据 this.$ownerInstance.callMethod(‘reciveMessage’, res),调用reciveMessage代码,给posterList 赋值
通过上面的方法完成renderjs与常规script的通信,这样就达到了开篇的需求图的封面列表,H5,APP端都可以生成封面图,亲测有效
版权声明:本文为yuanqi3131原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。