1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| async function extractFrames({ videoEl, clipStart, clipEnd, numFrames, quality = 0.8, outputScale = 1, alpha = 1 // 设置透明度 (1: 完全不透明) }) { // 暂停视频播放 videoEl.pause();
const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); const outputWidth = outputScale * videoEl.videoWidth; const outputHeight = outputScale * videoEl.videoHeight; canvas.width = outputWidth; canvas.height = outputHeight;
const frames = [];
for (let i = 0; i < numFrames; i++) { const duration = clipEnd - clipStart; if (duration <= 0) { throw new Error('clipEnd is before clipStart'); } const time = i * (duration / (Math.max(2, numFrames) - 1)) + clipStart;
// 跳转到指定时间 const seekedTime = await seekTo(videoEl, time);
// 清空 Canvas 背景,确保透明 context.clearRect(0, 0, canvas.width, canvas.height);
// 设置全局透明度 context.globalAlpha = alpha;
// 绘制视频帧到 Canvas context.drawImage(videoEl, 0, 0, outputWidth, outputHeight);
// 获取帧像素数据 const imageData = context.getImageData(0, 0, canvas.width, canvas.height); const data = imageData.data;
// 将白色像素(或近似白色)改为透明 for (let j = 0; j < data.length; j += 4) { const r = data[j]; // 红色通道 const g = data[j + 1]; // 绿色通道 const b = data[j + 2]; // 蓝色通道 const a = data[j + 3]; // 透明度通道
// 判断是否是白色(或接近白色) if (r > 240 && g > 240 && b > 240 && a > 0) { // 将其改为透明 data[j + 3] = 0; } }
// 将修改后的像素数据写回 Canvas context.putImageData(imageData, 0, 0);
// 将帧数据存储为透明背景的 PNG frames.push({ time, seekedTime, data: canvas.toDataURL('image/png', quality) // 输出透明背景帧 }); }
return frames; }
|