小程序获取 Camera 实时帧数据,转base64
发表时间:2021-1-4
发布人:葵宇科技
浏览次数:214
1、业务场景
在小程序中,需要每隔0.5s获取获取一次Camera实时帧数据,转为base64
(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
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。