惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
V
V2EX
B
Blog RSS Feed
有赞技术团队
有赞技术团队
博客园 - Franky
美团技术团队
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
云风的 BLOG
云风的 BLOG
L
LangChain Blog
GbyAI
GbyAI
The Cloudflare Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Stack Overflow Blog
Stack Overflow Blog
博客园 - 【当耐特】
The Register - Security
The Register - Security
大猫的无限游戏
大猫的无限游戏
D
Docker
Vercel News
Vercel News
Blog — PlanetScale
Blog — PlanetScale
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 司徒正美
人人都是产品经理
人人都是产品经理
雷峰网
雷峰网
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
N
Netflix TechBlog - Medium
博客园_首页
A
About on SuperTechFans
J
Java Code Geeks
量子位
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
MongoDB | Blog
MongoDB | Blog
Recent Announcements
Recent Announcements
G
Google Developers Blog
小众软件
小众软件
博客园 - 叶小钗
WordPress大学
WordPress大学
博客园 - 聂微东
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Martin Fowler
Martin Fowler
S
SegmentFault 最新的问题
F
Full Disclosure
Jina AI
Jina AI
H
Help Net Security

WishMeLz - Vue

Electron 主进程起一个可用的 HTTPS 静态服务器 - WishMeLz van-nav-bar 页面宽度改动 placeholder占位元素未自动更新 - WishMeLz Vant UI van-search 键盘没有显示「搜索」按钮的解决方案 - WishMeLz Lodop、C-Lodop使用笔记 - WishMeLz el-upload beforeUpload 使用async无法拦截 ANSI 字体在前端展示 Jenkins日志 - WishMeLz elementui 动态生成的 el-form-item rules校验失效 vue中v-html - WishMeLz SSE(Server-Sent Events) - WishMeLz
获取视频某一秒的截图 - WishMeLz
Wish · 2024-07-04 · via WishMeLz - Vue
        
        const handleGetVideoThumb = async function (url, options = {}) {
            if (typeof url !== "string") {
                console.error("URL must be a string");
                return;
            }

            // 默认参数
            const defaults = {
                seekTime: 1,
                onLoading: () => {},
                onLoaded: () => {},
                onFinish: (thumbData) => {},
                onError: (error) => console.error(error),
            };
            const params = { ...defaults, ...options };

            // 基于视频元素绘制缩略图,而非解码视频
            const video = document.createElement("video");
            // 静音
            video.muted = true;

            // 绘制缩略图的 canvas 画布元素
            const canvas = document.createElement("canvas");
            const context = canvas.getContext("2d", {
                willReadFrequently: true,
            });

            // 绘制缩略图的标志量
            let isTimeUpdated = false;

            // 设置视频源并返回 blob URL
            const setVideoSource = async (url) => {
                if (/^blob:|base64,/i.test(url)) {
                    return url;
                } else {
                    try {
                        const response = await fetch(url);
                        const blob = await response.blob();
                        params.onLoaded();
                        return URL.createObjectURL(blob);
                    } catch (error) {
                        params.onError(error);
                    }
                }
            };

            // 获取视频尺寸并开始绘制
            const onLoadedMetadata = () => {
                canvas.width = video.videoWidth;
                canvas.height = video.videoHeight;
                draw();
            };

            // 触发绘制监控
            const onTimeUpdate = () => {
                isTimeUpdated = true;
            };

            // 绘制方法
            const draw = () => {
                const thumbData = [];
                video.currentTime = params.seekTime;

                const onSeeked = () => {
                    if (isTimeUpdated) {
                        context.clearRect(0, 0, canvas.width, canvas.height);
                        context.drawImage(video, 0, 0, canvas.width, canvas.height);
                        canvas.toBlob((blob) => {
                            thumbData.push(URL.createObjectURL(blob));
                            params.onFinish(thumbData);
                        }, "image/jpeg");
                        video.removeEventListener("seeked", onSeeked);
                    }
                };

                video.addEventListener("seeked", onSeeked);
            };

            // 设置事件监听
            video.addEventListener("loadedmetadata", onLoadedMetadata);
            video.addEventListener("timeupdate", onTimeUpdate);

            // 获取视频数据
            params.onLoading();
            video.src = await setVideoSource(url);
        };

        // 示例调用
        handleGetVideoThumb(
            "https://xxxxx.mp4",
            {
                seekTime: 7, // 截取第7s视频
                onFinish: (data) => {
                    console.log(data); // 图片数据
                },
                onError: (error) => {
                    console.error("Error occurred:", error);
                },
            }
        );