小程序获取 Camera 实时帧数据,转base64 - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 小程序相关 >

小程序获取 Camera 实时帧数据,转base64

发表时间:2021-1-4

发布人:葵宇科技

浏览次数:150

1、业务场景

在小程序中,需要每隔0.5s获取获取一次Camera实时帧数据,转为base64


2、开始

(1)获取Camera 实时帧数据
// wxml
<camera device-position="{{device?'front':'back'}}" flash="off" binderror="error" style="width: 100%; height: 560rpx;" class="camera"></camera>
复制代码
// js

let listener

page({
  data: {
    device: true,
    speedMaxCount: 30
  },
  startTacking() {
    var _that = this;
    var count = 0;
    const context = wx.createCameraContext();
    if (!context.onCameraFrame) {
      var message = '基础库 2.7.0 开始支持".';
      wx.showToast({
          title: message,
          icon: 'none'
      });
      return;
    }
    listener = context.onCameraFrame(async function (res) {
    // 每秒60帧,这里控制每0.5获取一次图片
      if (count < _that.data.speedMaxCount) {
        count++;
        return;
      }
      count = 0;
      _that.stopTacking()
      // onCameraFrame 获取的是未经过编码的原始 RGBA 格式的图像数据,接下来转为图片
      _that.changeDataToBase64(res)
      
    });
    // start
    listener.start();
    console.log('startTacking', 'listener is start');
  },
  stopTacking() {
    if (listener) {
      listener.stop();
    }
  },
  onReady: function () {
    this.startTacking();
  },
})
复制代码

(2)将获取到的原始图片数据转base64

onCameraFrame返回的数据格式如下图,将获取到的原始图片数据转base64

方法1:upng

在js页面中引入upng

// js
const upng = require('../../../utils/upng/UPNG.js')
复制代码

// js
changeDataToBase64() {
  let pngData = http://www.wxapp-union.com/upng.encode([frame.data], frame.width, frame.height)
  let base64 = wx.arrayBufferToBase64(pngData)
  // 拿到数据后的其他操作
}
复制代码

主要问题:开发者工具测试时没有问题,真机测试,安卓机测试没有问题,但是ios机型转码时间特别长,基本在10s以上。这,,,都不用用户反馈,测试就过不了

方法2:实时帧数据添加到Canvas上

借用 canvas 的 putImageData,添加到画布上,再转为临时文件,再将临时文件转为base64

小程序中canvasPutImageData写入data的数据类型为Uint8ClampedArray,但是获取的实时帧数据的data的数据类型为ArrayBuffer,所以需要先将ArrayBuffer的数据类型转为Uint8ClampedArray

// js
changeDataToBase64(frame) {
  var data = http://www.wxapp-union.com/new Uint8Array(frame.data);
  var clamped = new Uint8ClampedArray(data);
  let that = this
    wx.canvasPutImageData({
      canvasId: 'myCanvas',
      x: 0,
      y: 0,
      width: frame.width,
      height: frame.height,
      data: clamped,
      success(res) {
        // 转换临时文件
        console.log(res)
        wx.canvasToTempFilePath({
          x: 0,
          y: 0,
          width: frame.width,
          height: frame.height,
          canvasId: 'myCanvas',
          fileType: 'jpg',
          destWidth: frame.width,
          destHeight: frame.height,
          // 精度修改
          quality: 0.8,
          success(res) {
            // 临时文件转base64
            wx.getFileSystemManager().readFile({
              filePath: res.tempFilePath, //选择图片返回的相对路径
              encoding: 'base64', //编码格式
              success: res => {
                // 保存base64
                let base64 = res.data;    
                // 拿到数据后的其他操作   
              }
            })
          },
          fail(res) {
            console.log(res)
            wx.showToast({
              title: '图片生成失败,重新检测',
              icon: 'none',
              duration: 1000
            })
            // 测试的时候发现安卓机型,转为临时文件失败,这里从新获取帧数据,再转码就能成功,不知道为什么
            that.startTacking()
          }
        }, that)
      }
    })
 }
复制代码

主要问题:开发者工具测试时没有问题,真机测试,ios时间明显缩短,大概在1s左右。安卓机时间也大概在1s左右,除了部分机型首次转为临时文件报错,只要再次获取帧数据,进行转码就没有问题了。


作者:小黑2333
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关案例查看更多