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

iPhone 13 Pro上canvas绘制摄像头画面亮度偏亮如何解决

问题背景

需要调用手机摄像头采集画面,绘制到canvas元素后做后续保存操作。
异常表现:仅iPhone 13 Pro设备上canvas绘制输出的图像亮度偏高于正常水平,其余iOS设备、安卓设备均无该问题,同设备下<video>元素直接播放摄像头流的画面亮度正常。

核心实现代码如下:

let video = document.createElement('video');
  let canvas = document.getElementById('canvas');
  // 注意:原代码此处存在笔误,不应从未定义的container变量获取上下文
  let ctx = container.getContext('2d');

  navigator.mediaDevices.getUserMedia({
    audio: false,
    video: {
      width: 1920,
      height: 1020,
      facingMode: 'environment'
    }}).then(stream => {
      window.stream = stream;
      video.srcObject = stream;
      const track = stream.getVideoTracks()[0];

      video.setAttribute('playsinline', 'true');

      video.play();

      requestAnimationFrame(() => {
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      });
  })
故障原因

iPhone 13 Pro及后续搭载支持HDR拍摄摄像头的iOS设备,摄像头默认输出HDR格式视频帧。系统原生的<video>组件自带HDR到SDR的色调映射能力,所以直接播放时亮度显示正常;但部分iOS版本的2D Canvas上下文没有内置该色调映射逻辑,直接将HDR帧的高亮度值按SDR色域解析,就会出现画面整体过亮、高光发白的异常。
另外原代码存在两个逻辑缺陷:一是没有等视频加载完成第一帧就开始绘制,可能拿到未处理完成的异常帧;二是上下文获取对象写错,正常运行时会直接抛出JS错误。

修复方案
  • 从源头上关闭视频轨的HDR输出
    获取视频轨道后,强制约束输出非HDR格式帧,不支持该配置的设备会自动忽略约束,不会影响原有逻辑:
    const track = stream.getVideoTracks()[0];
    try {
      await track.applyConstraints({
        advanced: [{ hdrMode: 'none' }]
      });
    } catch (err) {}
    
  • 修正上下文获取笔误,等待视频加载完成后再启动绘制循环
    不要在调用play()后直接执行单次绘制,要等视频loadeddata事件触发,确认第一帧已经可渲染后再启动循环绘制,同时可以显式指定Canvas色彩空间为sRGB,避免不同设备的色彩解析偏差:
    // 修正笔误,从canvas元素获取2D上下文
    let ctx = canvas.getContext('2d', { colorSpace: 'srgb' });
    
    video.setAttribute('playsinline', 'true');
    await video.play();
    
    video.addEventListener('loadeddata', () => {
      const draw = () => {
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
        requestAnimationFrame(draw);
      }
      draw();
    });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:27:17