Vue获取视频首帧作为视频封面图

Web前端开发 / 13 次阅读

Ajax返回的对象中使用Vue做的视频列表页面,把每个视频的首帧作为封面图片或者视频poster。

HTML代码:

<ul>
    <li v-for="item,index in videoList">
        <video :ref="'video'+index" crossorigin="anonymous" :poster="item.videoPoster" preload="metadata" style="display: none;"></video>
        <canvas :ref="'canvas'+index" style="display: none;"></canvas>
    </li>
</ul>

Vue代码:

var app = new Vue({
    el: '#app',//作用域
    data: {
        videoList:[
            {
                "videoUrl":"../upload/video1.mp4",
                "videoPoster:"../upload/poster1.jpg" //默认封面
            },
            {
                "videoUrl":"../upload/video2.mp4",
                "videoPoster:"../upload/poster2.jpg" //默认封面
            },
            {
                "videoUrl":"../upload/video3.mp4",
                "videoPoster:"../upload/poster3.jpg" //默认封面
            }
        ]
    },
    methods: { 
        // 生成视频缩略图函数
        generateThumbnail: function(video, index) {
            const self = this;
            
            //重置缩略图,如果要更换所有的默认封面则使用,否则不需要
            //self.$set(self.videos[index], 'videoPoster', null);
            
            const videoElement = self.$refs[`video${index}`][0]; //定义对应下标的视频对象
            const canvasElement = self.$refs[`canvas${index}`][0];    //定义对应下标的画布对象
            videoElement.src = video.FileUrl; // 设置视频源
            //当视频加载完成时
            videoElement.addEventListener('loadeddata', () => {
                videoElement.currentTime = 0.1; //设置视频当前时间为第一帧
            });
            //当视频跳转到指定时间点时
            videoElement.addEventListener('seeked', () => {
                const videoWidth = videoElement.videoWidth; //获取视频宽度
                const videoHeight = videoElement.videoHeight; //获取视频高度
                canvasElement.width = 960; //设置画布宽度,或者直接使用视频的宽度
                canvasElement.height = 540;    //设置画布高度,或者直接使用视频的高度
                
                //绘制视频帧到Canvas
                const ctx = canvasElement.getContext('2d');
                ctx.drawImage(videoElement, 0, 0, videoWidth, videoHeight);
                
                // 将Canvas转换为DataURL
                const dataURL = canvasElement.toDataURL();
                
                //更新返回对象里的默认封面为视频首帧
                if(self.list[index].videoPoster== ''){
                    self.$set(self.list[index], 'videoPoster', dataURL); //如果返回对象的默认封面为空,则使用视频首帧
                }else{
                    const orURL = self.list[index].videoPoster; 
                    self.$set(self.list[index], 'videoPoster', orURL); //如果返回对象的默认封面不为空,则使用对象原来的默认封面(可以不要)
                }
            });
            //加载视频
            videoElement.load();
        },
        init: function(){
            $.post(url, {
                action: 'GetVideoList',
            }, function (res) {
                if (res.success) {
                    self.list = res.data.Items;
                    //等待vue的双向绑定后执行的js
                    self.$nextTick(function () {
                        self.list.forEach((video, index) => {
                            self.generateThumbnail(video, index);
                        });
                    })
                }else{
                    
                }
            }, 'json');
        }
    },
    mounted: function () {
        this.init();
    }
});

完成。