• js实现视频截图,视频批量截图,canvas实现


    截取视频的某一时间的图像并保存

    利用canvas的绘画能力画出视频某一帧的视频画面, 获得到图像之后转换成base64图像, 再利用a标签的实现自动保存到本地

    • html代码
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>视频截图保存到本地</title>
    </head>
    
    <body>
        <div><button id="btn">开始截图</button></div>
        <img id="img">
        <a id="a" download="" style="display: none;">去下载</a>
    </body>
    
    </html>
    
    • js代码
    // 绑定下载
    document.getElementById("btn").onclick = function() {
        videoCover("视频地址", null, 400)
    }
    /**
     * @param {String} src 视频链接
     * @param {Number} width 视频容器播放的宽
     * @param {Number} height 视频容器播放的高
     * @param {Number} second 需要截图视频的帧数, 单位秒
     * @param {Number} bufftime 视频加载缓冲的时长, 单位秒
     */
    function videoCover(src, width, height, second, bufftime) {
        const canvas = document.createElement('canvas'); //  创建canvas 用来截图
        const video = document.createElement('video'); //  创建video 用来存放被截图的视频
        const img = document.getElementById('img') //  用来显示截图的图片效果
        const a = document.getElementById('a') //  用来自动下载图片保存到本地
        video.setAttribute('crossOrigin', 'anonymous'); //  支持跨域
        document.body.appendChild(video); //  把视频插入页面里
        video.setAttribute('src', src); //  设置video路径
        video.style.visibility = "hidden" //  视频不显示
    
        // 监听视频播放
        video.onplay = function() {
            // 暂停
            video.pause()
            // 指定播放时间 1代表视频的第一秒帧 可以浮点数
            video.currentTime = second || 1
            // 设置视频容器的宽高播放 如果设置一项会自动按照比例生成  这里是高固定,宽自动
            video.height = height || video.clientHeight;
            // 设置canvas的截图大小,如果没给定宽高值会取视频容器的宽高
            canvas.width = width || video.clientWidth;
            canvas.height = height || video.height;
            /*  
                使用定时器为了视频跳转到某一帧的时候视频进行缓冲,等视频加载完成之后进行截图
                如果截图是黑屏说明视频未加载完成就开始截屏了
            */
            setTimeout(() => {
                //  使用canvas进行绘画 视频画面
                canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
                // 获取到base64图片 png格式
                const IMG_TYPE = "png"
                const b64 = canvas.toDataURL('image/' + IMG_TYPE);
                // 展示到页面上给img的src赋值
                document.getElementById('img').setAttribute('src', b64);
                // 设置下载图片地址
                document.getElementById('a').setAttribute('href', b64);
                //  设置下载图片的名称
                const filename = "测试图" + "." + IMG_TYPE
                document.getElementById('a').setAttribute('download', filename);
                //  模拟点击自动下载图片
                document.getElementById('a').click()
                //  移除视频容器
                document.body.removeChild(video);
            }, bufftime * 1000 || 3000);
        }
        // 当视频准备就绪的时候 
        video.onloadeddata = () => {
            //  播放它
            video.play()
        }
    }
    

    以上代码就完成了单个的视频截图了.

    • 如何实现多个视频批量截图视频呢?

    使用for循环遍历 调用 videoCover 函数, videoCover 需要重写一下.

    先规定需要遍历视频截图的内容

    [
        {
            "src":"*******.video", // 视频下载地址
            "currentTime":5, //需要截取的视频帧数,第几秒
            "filename":"测试1", // 需要下载到本地的文件名
            "filetype":"png" // 下载的图片类型
        },
        {
            "src":"*******.video", // 视频下载地址
            "currentTime":5, //需要截取的视频帧数,第几秒
            "filename":"测试1", // 需要下载到本地的文件名
            "filetype":"png" // 下载的图片类型
        }
    ]
    
    • 重写videoCover 函数

    使用promise,async,await 遍历循环截图下载图片

    /**
    * @param {Object} obj 视频内容对象
    * @param {Number} width 视频容器播放的宽
    * @param {Number} height 视频容器播放的高
    * @param {Number} bufftime 视频加载缓冲的时长, 单位秒
    */
    function videoCover(obj, width, height, bufftime) {
        return new Promise((resolve, reject) => {
            const canvas = document.createElement('canvas'); //  创建canvas 用来截图
            const video = document.createElement('video'); //  创建video 用来存放被截图的视频
            const img = document.getElementById('img') //  用来显示截图的图片效果
            const a = document.getElementById('a') //  用来自动下载图片保存到本地
            video.setAttribute('crossOrigin', 'anonymous'); //  支持跨域
            document.body.appendChild(video); //  把视频插入页面里
            video.setAttribute('src', obj.src); //  设置video路径
            video.style.visibility = "hidden" //  视频不显示
            // 监听视频播放
            video.onplay = function () {
                // 暂停
                video.pause()
                // 指定播放时间 1代表视频的第一秒帧 可以浮点数
                video.currentTime = obj.currentTime || 1
                // 设置视频容器的宽高播放 如果设置一项会自动按照比例生成  这里是高固定,宽自动
                video.height = height || video.clientHeight;
                // 设置canvas的截图大小,如果没给定宽高值会取视频容器的宽高
                canvas.width = width || video.clientWidth;
                canvas.height = height || video.height;
                /*  
                    使用定时器为了视频跳转到某一帧的时候视频进行缓冲,等视频加载完成之后进行截图
                    如果截图是黑屏说明视频未加载完成就开始截屏了
                */
                setTimeout(() => {
                    //  使用canvas进行绘画 视频画面
                    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
                    // 获取到base64图片 png格式
                    const b64 = canvas.toDataURL('image/' + obj.filetype);
                    //  移除视频容器
                    document.body.removeChild(video);
                    resolve(b64)
                }, bufftime * 1000 || 3000);
            }
            // 当视频准备就绪的时候 
            video.onloadeddata = () => {
                //  播放它
                video.play()
            }
        })
    
    }
    
    • 在写个循环遍历videoCover 函数
    async function start() {
        const DATA = [{
            "src": "http:/****.mp4", // 视频下载地址
            "currentTime": 5, //需要截取的视频帧数,第几秒
            "filename": "测试1", // 需要下载到本地的文件名
            "filetype": "png" // 下载的图片类型
        },
        {
            "src": "http:/****.mp4", // 视频下载地址
            "currentTime": 2, //需要截取的视频帧数,第几秒
            "filename": "测试2", // 需要下载到本地的文件名
            "filetype": "png" // 下载的图片类型
        }]
        const img = document.getElementById('img')      //  用来显示截图的图片效果
        const a = document.getElementById('a')          //  用来自动下载图片保存到本地
        for (let index = 0; index < DATA.length; index++) {
            const element = DATA[index];
            console.log("开始截图视频:" + element.src);
            const b64 = await videoCover(element, null, 400, 3)
            // 展示到页面上给img的src赋值
            img.setAttribute('src', b64);
            // 设置下载图片地址
            a.setAttribute('href', b64);
            //  设置下载图片的名称
            const filename = element.filename + "." + element.filetype
            a.setAttribute('download', filename);
            //  模拟点击自动下载图片
            a.click()
            console.log("截图保存到本地成功:命名<" + filename + ">");
        }
        console.log("所有视频截图下载本地完成!");
    }
    // 绑定下载
    document.getElementById("btn").onclick = function () {
        start()
    }
    

    然后点击按钮去截图,就可以开始批量截图视频保存到本地了.
    多个视频截图

    提示: async/await属于es7语法,部分低版本浏览器暂不支持,需要前往高版本浏览器使用!

  • 相关阅读:
    最近实际项目中遇到的技术问题与解决思路
    独立完成一个城市选择组件(阿里前端题目,内附知识点、思路)
    用Node.js写爬虫,撸羞羞的图片
    Flutter项目之app升级方案
    Flutter数据持久化入门以及与Web开发的对比
    为什么要学会正则表达式
    async/await,了解一下?
    面向面试题和实际使用谈promise
    从一次输入框无法输入的bug,谈如何限制输入框输入类型
    Vue组件的is具体用法
  • 原文地址:https://www.cnblogs.com/kongyijilafumi/p/14088697.html
Copyright © 2020-2023  润新知