当前位置:首页 > JavaScript

js实现视频压缩

2026-04-04 11:12:28JavaScript

使用 MediaRecorder API 压缩视频

通过 MediaRecorder API 可以录制视频并设置压缩参数。该方法适合在浏览器端直接处理视频文件。

async function compressVideo(file) {
  const videoElement = document.createElement('video');
  videoElement.src = URL.createObjectURL(file);
  await new Promise(resolve => videoElement.onloadedmetadata = resolve);

  const canvas = document.createElement('canvas');
  canvas.width = videoElement.videoWidth * 0.5; // 缩小分辨率
  canvas.height = videoElement.videoHeight * 0.5;
  const ctx = canvas.getContext('2d');

  const stream = canvas.captureStream();
  const recorder = new MediaRecorder(stream, {
    mimeType: 'video/webm;codecs=vp9',
    bitsPerSecond: 250000 // 设置比特率
  });

  videoElement.play();
  const chunks = [];
  recorder.ondataavailable = e => chunks.push(e.data);
  recorder.start();

  const interval = setInterval(() => {
    ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
  }, 1000/30);

  return new Promise(resolve => {
    setTimeout(() => {
      clearInterval(interval);
      recorder.stop();
      resolve(new Blob(chunks, {type: 'video/webm'}));
    }, 3000); // 录制3秒
  });
}

使用 FFmpeg.wasm 进行高级压缩

FFmpeg.wasm 是 WebAssembly 版本的 FFmpeg,提供更专业的视频处理能力。

import { createFFmpeg } from '@ffmpeg/ffmpeg';

async function compressWithFFmpeg(file) {
  const ffmpeg = createFFmpeg({ log: true });
  await ffmpeg.load();

  ffmpeg.FS('writeFile', 'input.mp4', await fetchFile(file));
  await ffmpeg.run(
    '-i', 'input.mp4',
    '-vf', 'scale=640:-1', // 调整分辨率
    '-c:v', 'libx264',     // H.264编码
    '-crf', '28',          // 压缩质量(18-28)
    '-preset', 'fast',
    'output.mp4'
  );

  const data = ffmpeg.FS('readFile', 'output.mp4');
  return new Blob([data.buffer], { type: 'video/mp4' });
}

使用 Canvas 和 Web Worker 处理

对于长时间压缩任务,建议使用 Web Worker 避免阻塞主线程。

// worker.js
self.onmessage = async (e) => {
  const { file, width, height, quality } = e.data;
  const video = document.createElement('video');
  video.src = URL.createObjectURL(file);

  await new Promise(resolve => {
    video.onloadedmetadata = resolve;
    video.play();
  });

  const canvas = new OffscreenCanvas(width, height);
  const ctx = canvas.getContext('2d');

  const frames = [];
  for (let i = 0; i < video.duration * 30; i++) {
    ctx.drawImage(video, 0, 0, width, height);
    frames.push(await canvas.convertToBlob({quality}));
    await new Promise(r => setTimeout(r, 1000/30));
  }

  postMessage(frames);
};

使用第三方库 compressor.js

compressor.js 提供简单的视频压缩接口,适合快速实现基本需求。

import Compressor from 'compressorjs';

new Compressor(file, {
  quality: 0.6,
  maxWidth: 1280,
  maxHeight: 720,
  success(result) {
    console.log('压缩完成', result);
  },
  error(err) {
    console.error('压缩失败', err);
  }
});

注意事项

视频压缩会受浏览器兼容性限制,不同浏览器支持的编码格式不同。建议检测浏览器支持情况:

js实现视频压缩

function checkCodecSupport() {
  return MediaRecorder.isTypeSupported('video/webm;codecs=vp9') 
    || MediaRecorder.isTypeSupported('video/mp4');
}

移动端设备可能对高分辨率视频处理性能有限,建议先降低分辨率再压缩。

标签: 视频压缩js
分享给朋友:

相关文章

js分组实现

js分组实现

分组实现方法 在JavaScript中,可以通过多种方式实现数组或对象的分组操作。以下是几种常见的方法: 使用Array.prototype.reduce() 通过reduce方法可以轻松实现数组分…

链表实现js

链表实现js

链表的基本概念 链表是一种线性数据结构,由一系列节点组成,每个节点包含数据和一个指向下一个节点的指针(单向链表)或两个指针(双向链表)。与数组不同,链表在内存中非连续存储,插入和删除操作更高效,但随机…

js实现跑马灯

js实现跑马灯

实现跑马灯效果 使用HTML和JavaScript可以轻松实现跑马灯效果。以下是两种常见的实现方式: HTML结构 <div id="marquee"> <span>…

js实现路由

js实现路由

js实现路由的方法 在JavaScript中实现路由功能可以通过多种方式完成,以下是几种常见的方法: 使用原生JavaScript实现路由 通过监听window.onhashchange事件来实现基…

js实现上传文件

js实现上传文件

文件上传的基本实现 使用HTML的<input type="file">元素配合JavaScript的File API可以实现文件上传功能。 <input type="file"…

js实现按钮点击

js实现按钮点击

实现按钮点击的JavaScript方法 HTML按钮元素 在HTML中创建按钮元素,为其添加id或class以便JavaScript选择: <button id="myButton">点…