js实现视频压缩
使用FFmpeg.wasm进行视频压缩
FFmpeg.wasm是FFmpeg的WebAssembly版本,可以在浏览器中直接运行。安装FFmpeg.wasm后,可以通过JavaScript调用其功能进行视频压缩。
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';
const ffmpeg = createFFmpeg({ log: true });
async function compressVideo(file) {
await ffmpeg.load();
ffmpeg.FS('writeFile', 'input.mp4', await fetchFile(file));
await ffmpeg.run('-i', 'input.mp4', '-vf', 'scale=640:-1', '-c:v', 'libx264', '-crf', '28', 'output.mp4');
const data = ffmpeg.FS('readFile', 'output.mp4');
return new Blob([data.buffer], { type: 'video/mp4' });
}
使用Canvas API和MediaRecorder
对于简单的视频压缩,可以使用Canvas API和MediaRecorder组合实现。这种方法适合需要降低分辨率或帧率的场景。
async function compressWithCanvas(videoFile, width = 640, quality = 0.7) {
const videoElement = document.createElement('video');
videoElement.src = URL.createObjectURL(videoFile);
await new Promise(resolve => videoElement.onloadedmetadata = resolve);
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = (videoElement.videoHeight / videoElement.videoWidth) * width;
const stream = canvas.captureStream();
const recorder = new MediaRecorder(stream, {
mimeType: 'video/webm',
bitsPerSecond: 500000
});
const ctx = canvas.getContext('2d');
const chunks = [];
recorder.ondataavailable = e => chunks.push(e.data);
recorder.start(100);
const drawFrame = () => {
ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
if (!videoElement.ended) requestAnimationFrame(drawFrame);
else recorder.stop();
};
videoElement.play();
drawFrame();
return new Promise(resolve => {
recorder.onstop = () => {
const blob = new Blob(chunks, { type: 'video/webm' });
resolve(blob);
};
});
}
使用第三方库videoconverter.js
videoconverter.js是一个专门用于视频转换的JavaScript库,支持多种格式的压缩和转换。
const converter = new videojs.VideoConverter();
converter.setInputFormat('mp4');
converter.setOutputFormat('mp4');
converter.setQuality(50); // 质量百分比
converter.on('complete', function(outputBlob) {
console.log('压缩完成', outputBlob);
});
converter.convert(videoFile);
使用Web Worker处理大文件
对于大型视频文件,建议使用Web Worker避免阻塞主线程。将压缩逻辑放在Worker中执行。
// main.js
const worker = new Worker('video-worker.js');
worker.postMessage({ file: videoFile });
worker.onmessage = function(e) {
const compressedBlob = e.data;
// 处理压缩后的视频
};
// video-worker.js
self.onmessage = function(e) {
const file = e.data.file;
// 执行压缩逻辑
const compressed = compressVideo(file);
self.postMessage(compressed);
};
优化压缩参数
调整视频编码参数可以平衡文件大小和质量。常用的x264编码器参数示例:
await ffmpeg.run(
'-i', 'input.mp4',
'-c:v', 'libx264',
'-preset', 'slow',
'-crf', '28',
'-c:a', 'aac',
'-b:a', '128k',
'output.mp4'
);
其中CRF值范围18-28(值越大压缩率越高),预设值可选ultrafast到veryslow(越慢压缩效率越高)。
浏览器兼容性处理
不同浏览器对视频编码的支持不同,需要检测并回退处理:
function getSupportedMimeType() {
const types = [
'video/webm; codecs=vp9',
'video/webm; codecs=vp8',
'video/mp4; codecs=avc1'
];
return types.find(type => MediaRecorder.isTypeSupported(type)) || 'video/webm';
}
const mimeType = getSupportedMimeType();
const recorder = new MediaRecorder(stream, {
mimeType,
bitsPerSecond: 1000000
});






