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

如何水平翻转画中画(Picture-in-Picture)模式下的摄像头视频

解决画中画模式下摄像头视频镜像翻转失效的问题

问题根源

画中画(PiP)窗口的视频内容由浏览器独立渲染,不属于网页DOM树的一部分——网页里的CSS变换(包括:picture-in-picture伪类样式)无法作用到PiP窗口内的画面。仅靠CSS只能处理网页内的video元素显示,没法影响PiP模式的内容。

可行解决方案

方案1:直接配置MediaStreamTrack翻转流(简洁高效)

部分现代浏览器支持通过视频轨道的约束直接设置镜像翻转,这样网页和PiP模式的画面都会是翻转后的状态:

修改JS代码如下:

const button = document.getElementById('button');
const webCamVideo = document.querySelector('.webcam-vid')

button.addEventListener('click', async () => {
  // 初始化摄像头流时尝试配置翻转
  const stream = await navigator.mediaDevices.getUserMedia({ 
    video: { 
      facingMode: 'user',
      transform: { horizontalFlip: true }
    } 
  });
  
  // 兼容不支持transform约束的浏览器,手动更新轨道配置
  const videoTrack = stream.getVideoTracks()[0];
  const capabilities = videoTrack.getCapabilities();
  if (capabilities.transform?.horizontalFlip && !videoTrack.getConstraints().transform) {
    await videoTrack.applyConstraints({
      transform: { horizontalFlip: true }
    });
  }
  
  webCamVideo.srcObject = stream;
  // 修正原代码变量名错误:video改为webCamVideo
  webCamVideo.play();
  webCamVideo.addEventListener('loadedmetadata', () => {
    webCamVideo.requestPictureInPicture()
      .catch(console.error)
  });
});

同时移除CSS中.webcam-vid的transform: scaleX(-1),因为流本身已经是翻转后的状态。

方案2:Canvas中转视频流(兼容性拉满)

如果需要适配不支持轨道transform约束的浏览器,用Canvas中转处理是通用方案:

  1. 在HTML中添加隐藏的Canvas元素:
<canvas id="mirrorCanvas" style="display: none;"></canvas>
<video class="webcam-vid" autoPlay playsInline></video>
<button class="btn btn-primary" id="button">Display Webcam feed in Picture-in-Picture mode</button>
  1. 修改JS代码,通过Canvas绘制翻转后的视频帧,再将Canvas的流作为video的源:
const button = document.getElementById('button');
const webCamVideo = document.querySelector('.webcam-vid');
const mirrorCanvas = document.getElementById('mirrorCanvas');
const ctx = mirrorCanvas.getContext('2d');

button.addEventListener('click', async () => {
  const stream = await navigator.mediaDevices.getUserMedia({ video: true });
  webCamVideo.srcObject = stream;
  
  webCamVideo.addEventListener('loadedmetadata', () => {
    // 同步Canvas与视频的尺寸
    mirrorCanvas.width = webCamVideo.videoWidth;
    mirrorCanvas.height = webCamVideo.videoHeight;
    
    // 循环绘制翻转后的视频帧
    function drawMirrorFrame() {
      ctx.save();
      ctx.scale(-1, 1); // 水平翻转画布上下文
      ctx.drawImage(webCamVideo, -mirrorCanvas.width, 0, mirrorCanvas.width, mirrorCanvas.height);
      ctx.restore();
      requestAnimationFrame(drawMirrorFrame);
    }
    drawMirrorFrame();
    
    // 将Canvas的流作为video的源,PiP会使用Canvas的内容
    const canvasStream = mirrorCanvas.captureStream();
    webCamVideo.srcObject = canvasStream;
    
    webCamVideo.play();
    webCamVideo.requestPictureInPicture().catch(console.error);
  });
});

同样移除CSS中的transform: scaleX(-1),因为Canvas已经完成了翻转处理。

额外提示

原代码存在变量名错误:video.play()需改为webCamVideo.play(),否则会触发未定义变量的报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:57:18