js canvas视频截帧

阿超 阿超 | 415 | 2022-09-03

礼貌是儿童和青年都应该特别小心地养成习惯的第一件大事——约翰·洛克

先放代码:

 <script>
        /**
         * 
         * @param src string 视频url
         * @param currentTime double 视频截取位置,单位秒
         * @return 截取图片的 base64
         */
        function getImgFromVideoUrl(src, currentTime) {
            if (!src) return
            if (!currentTime || currentTime < 0) {
                // 如果传入截取位置小于0, 给个默认值
                currentTime = 0.001
            }
            return new Promise(resolve => {
                const body = document.querySelector("body")
                // 获取/创建video节点
                const video = document.querySelector("#imgExtractorVideo") || document.createElement("video")
                if (!video.id) {
                    // id,隐藏样式
                    Object.assign(video, {
                        id: 'imgExtractorVideo',
                        style: "display: none"
                    })
                    // 允许跨域
                    video.setAttribute('crossorigin', 'anonymous')
                    // 添加到页面上,下次就不用创建,直接用
                    body.append(video)
                }
                // 此处给video赋值,canplay需要重新赋值,否则load后不会重复调用
                Object.assign(video, { src, currentTime, oncanplay })
                // 获取/创建canvas节点
                const canvas = document.querySelector("#imgExtractorCanvas") || document.createElement("canvas")
                if (!canvas.id) {
                    // id,隐藏样式
                    Object.assign(canvas, {
                        id: 'imgExtractorCanvas',
                        style: "display: none"
                    })
                    // 添加到页面上,下次就不用创建,直接用
                    body.append(canvas)
                }
                // 获取canvas context
                const context = canvas.getContext("2d")
                // canvas渲染视频节点,转换为base64
                async function oncanplay() {
                    // 为canvas设置宽高为视频的宽高
                    Object.assign(canvas, { height: video.videoHeight, width: video.videoWidth })
                    // 渲染视频
                    context.drawImage(video, 0, 0)
                    // 获取视频时长
                    const duration = isNaN(video.duration) ? 0 : video.duration
                    if (currentTime > duration) {
                        // 如果当前传入截取位置大于视频时长,取视频时长 -0.1 然后重新截取
                        currentTime = duration - 0.1;
                        resolve(await getImgFromVideoUrl(src, currentTime))
                    } else {
                        // 这里的 toDataURL 第二个参数为图片质量,可接受范围 0~1 ,超出后为默认值 0.92
                        resolve(canvas.toDataURL("image/png", 1.0))
                    }
                }
            })
        }



        window.onload = async () => {
            // 视频长度 15s 左右

            // 调用
            let imgBase64 = await getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4")

            // 使用
            console.log({ imgBase64 })
            let img = document.createElement("img")
            img.src = imgBase64
            document.querySelector("body").append(img)

            // 调用
            imgBase64 = await getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 3)
            // 重复使用
            console.log({ imgBase64 })
            img = document.createElement("img")
            img.src = imgBase64
            document.querySelector("body").append(img)

            // 调用
            imgBase64 = await getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 4)
            // 重复使用
            console.log({ imgBase64 })
            img = document.createElement("img")
            img.src = imgBase64
            document.querySelector("body").append(img)

            // 调用
            imgBase64 = await getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 20)
            // 重复使用
            console.log({ imgBase64 })
            img = document.createElement("img")
            img.src = imgBase64
            document.querySelector("body").append(img)

            // Promise回调地狱
            getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 3)
                .then(base64 => {
                    // 使用
                    console.log({ base64 })
                    let img = document.createElement("img")
                    img.src = base64
                    document.querySelector("body").append(img)

                    // Promise回调地狱
                    getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 4)
                        .then(base64 => {
                            // 使用
                            console.log({ base64 })
                            let img = document.createElement("img")
                            img.src = base64
                            document.querySelector("body").append(img)

                            // Promise回调地狱
                            getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 5)
                                .then(base64 => {
                                    // 使用
                                    console.log({ base64 })
                                    let img = document.createElement("img")
                                    img.src = base64
                                    document.querySelector("body").append(img)
                                })
                        })
                })

        }



    </script>

效果:

e4aea97dd3d24bba9781e2e7c3c27c7d.png

接下来是博客和MDN

Promise博客:https://vampireachao.gitee.io/2021/12/04/Promise/

oss视频截封面博客:https://vampireachao.gitee.io/2022/01/10/oss视频截封面/

MDN

文章标签: 前端相关JavaScript
推荐指数:

真诚点赞 诚不我欺~

js canvas视频截帧

点赞 收藏 评论

关于作者

阿超
阿超

​ 我的名字叫阿超 年龄21岁 家在四川省成都市 未婚 职业是软件开发 每天最晚也会在八点前回家 不抽烟 酒浅尝辄止 晚上十二点上床 保证睡足八个小时 睡前写一篇博客 再做二十分钟俯卧撑暖身 然后再睡觉 基本能熟睡到天亮 像婴儿一样不留下任何疲劳和压力 就这样迎来第二天的早晨 健康检查结果也显示我很正常 我想说明我是一个不论何时都追求内心平稳的人 不拘泥于胜负 不纠结于烦恼 不树立使我夜不能寐的敌人 这就是我在这社会的生活态度

等级 LV1

粉丝 3

获赞 7

经验 73