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

WebRTC+RecordRTC录制对等端视频流:方向检测与旋转适配需求

解决WebRTC/RecordRTC录制视频方向不一致的问题

我之前也踩过这个坑!用RecordRTC保存WebRTC对等端的MediaStream时,不同设备输出的视频方向经常乱掉——明明是竖屏录制的视频,录出来却是横的,甚至上下颠倒。折腾了好久,总结出两个靠谱的解决思路,核心都是先拿到视频的原始旋转角度,再针对性修正。

一、先获取视频的原始旋转角度

现代浏览器的MediaStreamTrack提供了getSettings()方法,能直接拿到设备传感器返回的视频旋转参数,这是最关键的一步。这个参数叫videoRotation,值只会是0、90、180、270中的一个,分别对应不同的旋转方向:

  • 0:无旋转
  • 90:顺时针旋转90度
  • 180:顺时针旋转180度(上下颠倒)
  • 270:顺时针旋转270度(等同于逆时针90度)

代码示例:

// 假设你已经获取到对等端的MediaStream
const videoTrack = peerStream.getVideoTracks()[0];
const trackSettings = videoTrack.getSettings();
const rotationAngle = trackSettings.videoRotation; // 拿到0/90/180/270

注意:旧版浏览器可能不支持这个属性,比如Chrome 69以下,但主流现代浏览器(Chrome 69+、Firefox 63+、Edge 79+)都已经支持了。如果要兼容旧版本,可以用deviceOrientation事件作为 fallback,但复杂度会高一些。

二、实时修正画面再录制(推荐)

如果不想后期处理,最直接的方式是在录制前,用Canvas把视频帧旋转到正确方向,再录制Canvas的流。这样录出来的视频直接就是正的,不用二次处理。

步骤和代码示例:

function getCorrectedStream(originalStream, rotation) {
  const video = document.createElement('video');
  video.srcObject = originalStream;
  video.muted = true;
  video.play(); // 先加载视频流

  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  // 根据旋转角度调整Canvas的宽高(比如90度时,宽是原视频的高,高是原视频的宽)
  if (rotation === 90 || rotation === 270) {
    canvas.width = video.videoHeight;
    canvas.height = video.videoWidth;
  } else {
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
  }

  // 定时绘制视频帧到Canvas,做旋转处理
  setInterval(() => {
    ctx.save();
    // 先平移到Canvas中心,旋转后再平移回来,确保画面居中
    ctx.translate(canvas.width / 2, canvas.height / 2);
    ctx.rotate((rotation * Math.PI) / 180);
    ctx.translate(-video.videoWidth / 2, -video.videoHeight / 2);
    ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
    ctx.restore();
  }, 1000/30); // 按30fps绘制,可根据需求调整

  // 返回修正后的Canvas流
  return canvas.captureStream(30);
}

// 使用示例
const peerStream = peerConnection.getRemoteStreams()[0];
const videoTrack = peerStream.getVideoTracks()[0];
const rotation = videoTrack.getSettings().videoRotation;
const correctedStream = getCorrectedStream(peerStream, rotation);

// 用修正后的流开始录制
const recorder = new RecordRTC(correctedStream, { type: 'video' });
recorder.startRecording();

三、录制后批量修正视频

如果已经录好了视频文件,或者需要批量处理,可以用ffmpeg.wasm在浏览器里直接旋转视频。这种方式适合对实时性要求不高的场景。

代码示例:

// 先安装ffmpeg.wasm:npm install @ffmpeg/ffmpeg
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';

const ffmpeg = createFFmpeg({ log: true });

async function rotateRecordedVideo(inputBlob, rotation) {
  await ffmpeg.load(); // 加载ffmpeg核心库,首次加载会稍慢
  ffmpeg.FS('writeFile', 'input.webm', await fetchFile(inputBlob));

  // 根据旋转角度设置ffmpeg的滤镜参数
  let rotateFilter = '';
  switch(rotation) {
    case 90:
      rotateFilter = 'transpose=1'; // 顺时针旋转90度
      break;
    case 180:
      rotateFilter = 'transpose=2,transpose=2'; // 顺时针旋转180度
      break;
    case 270:
      rotateFilter = 'transpose=2'; // 逆时针旋转90度
      break;
    default:
      rotateFilter = ''; // 无需旋转
  }

  if (rotateFilter) {
    // 旋转视频,音频直接复制不处理
    await ffmpeg.run('-i', 'input.webm', '-vf', rotateFilter, '-c:a', 'copy', 'output.webm');
  } else {
    // 无需旋转,直接复制文件
    await ffmpeg.run('-i', 'input.webm', '-c', 'copy', 'output.webm');
  }

  // 导出处理后的文件
  const outputData = ffmpeg.FS('readFile', 'output.webm');
  return new File([outputData.buffer], 'corrected-video.webm', { type: 'video/webm' });
}

// 使用示例:录制完成后修正
recorder.stopRecording(() => {
  const recordedBlob = recorder.getBlob();
  rotateRecordedVideo(recordedBlob, rotationAngle).then(correctedFile => {
    // 下载修正后的视频
    const downloadUrl = URL.createObjectURL(correctedFile);
    const a = document.createElement('a');
    a.href = downloadUrl;
    a.download = 'corrected-video.webm';
    a.click();
    URL.revokeObjectURL(downloadUrl);
  });
});

小提示

  • 用Canvas实时旋转时,如果是高分辨率视频,可能会有性能损耗,可以考虑降低录制帧率或者用WebGL加速绘制。
  • 部分安卓设备的videoRotation可能返回异常值,建议在实际测试中多覆盖几种设备场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:06:52