You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用HTML5的drawImage()将视频分割为分块播放?

嘿,我帮你搞定这个3×4视频网格的问题!你说drawImage出问题,大概率是踩了这个函数参数顺序或者区域计算的坑——我先给你理清楚核心问题,再给你修正后的完整代码。

你可能踩的drawImage坑

drawImage()的参数顺序特别容易搞混,尤其是源区域和目标区域的位置/尺寸,很多人会把两者的参数写反。正确的参数顺序是:

ctx.drawImage(video, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
  • sx/sy:视频上要截取的起始坐标
  • sWidth/sHeight:视频上截取的区域宽高
  • dx/dy:canvas上绘制的起始坐标
  • dWidth/dHeight:canvas上绘制的区域宽高

另外,你可能没等视频加载完成就计算宽高,用了默认值导致区域划分错误,或者CSS拉伸了canvas导致显示变形。

修正后的完整代码

这是可以直接运行的版本,实现3×4网格每个区域播放对应视频片段:

<!DOCTYPE html>
<html>
<head>
    <title>Lab 5: HTML5</title>
    <style>
        .grid-container {
            display: grid;
            grid-template-columns: repeat(3, 1fr); /* 3列均分 */
            grid-template-rows: repeat(4, 1fr); /* 4行均分 */
            gap: 2px;
            width: 660px; /* 和你原来的box宽度一致 */
            margin: 0 auto;
        }
        canvas {
            border: 1px solid #333;
            width: 100%;
            height: auto;
        }
        video {
            display: none; /* 隐藏原始视频,只用canvas播放 */
        }
    </style>
</head>
<body>
    <video id="sourceVideo" controls>
        <source src="your-video.mp4" type="video/mp4">
        Your browser does not support HTML5 video.
    </video>
    <div class="grid-container" id="gridContainer"></div>

    <script>
        const video = document.getElementById('sourceVideo');
        const gridContainer = document.getElementById('gridContainer');
        const cols = 3;
        const rows = 4;
        let canvases = [];
        let ctxs = [];
        let videoWidth, videoHeight;
        let cellSourceWidth, cellSourceHeight;

        // 必须等视频加载元数据后,才能获取真实宽高
        video.addEventListener('loadedmetadata', () => {
            videoWidth = video.videoWidth;
            videoHeight = video.videoHeight;
            // 计算每个网格对应的视频源区域尺寸
            cellSourceWidth = videoWidth / cols;
            cellSourceHeight = videoHeight / rows;

            // 创建3×4的canvas网格
            for (let row = 0; row < rows; row++) {
                for (let col = 0; col < cols; col++) {
                    const canvas = document.createElement('canvas');
                    // 设置canvas的实际绘图尺寸(和视频源区域一致,避免拉伸)
                    canvas.width = cellSourceWidth;
                    canvas.height = cellSourceHeight;
                    gridContainer.appendChild(canvas);
                    canvases.push(canvas);
                    ctxs.push(canvas.getContext('2d'));
                }
            }
        });

        // 视频播放时循环绘制每一帧
        video.addEventListener('play', () => {
            function drawFrames() {
                if (!video.paused && !video.ended) {
                    // 遍历每个canvas,绘制对应的视频片段
                    canvases.forEach((canvas, index) => {
                        const row = Math.floor(index / cols);
                        const col = index % cols;
                        const ctx = ctxs[index];
                        // 关键:正确对应源区域和目标区域
                        ctx.drawImage(
                            video,
                            col * cellSourceWidth, // 视频上的起始x坐标
                            row * cellSourceHeight, // 视频上的起始y坐标
                            cellSourceWidth, // 截取的视频宽度
                            cellSourceHeight, // 截取的视频高度
                            0, 0, // canvas上的起始坐标(左上角)
                            canvas.width, canvas.height // canvas上的绘制尺寸
                        );
                    });
                    requestAnimationFrame(drawFrames);
                }
            }
            drawFrames();
        });
    </script>
</body>
</html>

关键细节解释

  1. 等待视频加载:用loadedmetadata事件确保获取视频真实宽高,避免用默认的300×150计算导致区域错位
  2. 网格区域计算:每个网格的视频源区域是列索引×源宽、行索引×源高,确保每个canvas对应视频的正确子区域
  3. canvas尺寸适配:canvas的width/height属性设置为源区域尺寸(保证绘图清晰),CSS的width:100%用来适配网格容器大小,避免拉伸变形
  4. 循环绘制:用requestAnimationFrame实现流畅的帧绘制,和视频播放同步

额外排查小技巧

  • 可以在控制台打印cellSourceWidth、col * cellSourceWidth这些值,看是否符合预期(比如视频宽600的话,cellSourceWidth应该是200)
  • 如果用单个大canvas绘制所有网格,只需要修改目标区域的dx/dy为每个网格在大canvas上的坐标即可

内容的提问来源于stack exchange,提问作者potatoguy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:08:20