目前实用性太差,小程序处理不过来,交给后台服务器数据量也太大了,用户体验太差,希望后面改进吧
能否提几个关于onCameraFrame接口(及其相关)的若干个改进建议?onCameraFrame接口是个很有意思也很强大的接口,在微信小程序还没有正式的宣告AR相关能力时我已经让团队基于此功能做了些尝试了。但是在使用过程中还是有诸多不便。所以谈谈我的一点想法和小建议。 这个接口的推出,我相信产品团队是出于目前诸多的AR/视频需求而开发出来的,但是从这两个场景来看这个接口直接用起来不太方便: 采样频率不可控,目前貌似是30FPS。但是这30FPS每帧都把数据扔出来的话,直接在这个事件中接到数据然后去做些相关的业务逻辑。。。。。。根本处理不过来啊。实际的应用场景我相信大家都需要降低频率来处理数据,像我就是先写个环形缓冲区,然后再按照我实际的业务逻辑测试好速度跳帧把数据插入到环形缓冲区。最后随时需要取数据的时候,去环形缓冲区里面拿。所以,从这个角度来说,我希望这个接口提供以下两个功能以便使用起来更加灵活: 能够提供相关的参数配置使得能够按照预先设定的频率输出数据 能够提供一个接口在调用请求的时候再返回最新的当前帧数据 onCameraFrame给出的是RGBA的数据,这玩意儿数据量太大用起来也不方便,尤其是要把数据再传回服务器端处理的或者需要做些裁剪缩放的动作就呵呵了。。。别说用Canvas,用那玩意儿的性能会活活拖死你。所以建议提供以下相关接口功能以便使用起来更加灵活: 对于onCameraFrame的数据,能够有参数配置使得得到jpg或者png的数据 提供一些原生功能对于得到的图像数据进行缩放、裁剪 当然,并不是说onCameraFrame现在的功能不可用。。。。用倒是可以用。。。我们做的一个用摄像头获取数据然后回传后台服务器进行分析判断的测试小程序,如果简单自行小心翼翼的跳帧然后再放到canvas里进行裁剪缩放最后传输到服务器。。。这时间简直是无法忍受的(若干秒) 后来我们加入环形缓冲区,自己用JS来进行图像的压缩裁剪什么的再传输,才成功的把整体处理时间压缩到300~400ms。 所以,我相信如果官方能够提供原生的采样速率控制或者按需请求数据,以及原生的图像缩放裁剪功能。那么对于AR/即时视频处理类的小程序将会得到速度上质的飞跃。 -------------------------------9月5日 追加------------------------- 随便搜一下onCameraFrame关键字就能找到我这里提到的几个同类问题贴: https://developers.weixin.qq.com/community/develop/doc/00004c1441c30840dce8b4d7956000?highLine=onCameraFrame (频率相关) https://developers.weixin.qq.com/community/develop/doc/0000ce49770450ded3e88522e56000?highLine=onCameraFrame (格式相关) https://developers.weixin.qq.com/community/develop/doc/000eeab7238bc8cba6f8840045bc00?highLine=onCameraFrame (真机无法调试onCameraFrame,我猜测也是频率过高造成,当然,仅仅只是猜测) https://developers.weixin.qq.com/community/develop/doc/0008229fccc948215bc8a8bba56800?highLine=onCameraFrame (8月9日 Keep的回复其实也是格式的问题) https://developers.weixin.qq.com/community/develop/doc/00062e5cc14b08e3750982bd457800?highLine=onCameraFrame (频率相关) https://developers.weixin.qq.com/community/develop/doc/00026e57b08e70d06519a7af656c00?highLine=onCameraFrame (图像数据的裁剪) https://developers.weixin.qq.com/community/develop/doc/000a6646b4cce8acd2981b4855f400?highLine=onCameraFrame (格式相关) https://developers.weixin.qq.com/community/develop/doc/00084ed934c730d6b8191124151400?highLine=onCameraFrame (频率相关)
2019-12-09wx.canvasPutImageData这个操作非常耗时,测试了几款机器,都在1s以上,可以设置成2s,或者等处理完成了再绘制下一帧,不然会因为内存占用过大而崩溃,目前这个接口还不是很成熟,处理速度大概在10fps左右,而CameraContext.onCameraFrame回调是按照30fps的速度输出Buffer,所以直接调用会卡顿或者崩溃
CameraContext.onCameraFrame回调时闪退此问题在真机调试及模拟器运行时表现有所不同。简单地说,就是CameraContext.onCameraFrame的回调函数无法被调用,一旦调用就会闪退。 在iPhone X 上是整个微信退出,在Android机(已在一加及OPPO上测试过)上是退出小程序。期间有log而无error信息(见下方截图)。 在模拟器上则是报thirdScriptError错误(见下方截图。本人以createObjectURL为关键词搜索过后,初步怀疑是模拟器环境所使用的Chrome内核的问题),小程序不闪退。 代码见下方。如是本人调用过程中有所遗漏,烦请指正。如是API本身的BUG,请尽快修复并告知。谢谢! WXML: [代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"view_container"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]camera[代码] [代码]device-position[代码][代码]=[代码][代码]"back"[代码] [代码]mode[代码][代码]=[代码][代码]"normal"[代码] [代码]frame-size[代码][代码]=[代码][代码]"medium"[代码] [代码]flash[代码][代码]=[代码][代码]"off"[代码] [代码]class[代码][代码]=[代码][代码]"view_camera"[代码][代码]></[代码][代码]camera[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]button[代码] [代码]type[代码][代码]=[代码][代码]"primary"[代码] [代码]bindtap[代码][代码]=[代码][代码]"scan"[代码][代码]>扫描</[代码][代码]button[代码][代码]>[代码][代码]</[代码][代码]view[代码][代码]>[代码][代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"view_container"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]image[代码] [代码]wx:if[代码][代码]=[代码][代码]"{{src}}"[代码] [代码]mode[代码][代码]=[代码][代码]"widthFix"[代码] [代码]src[代码][代码]=[代码][代码]"{{src}}"[代码][代码]></[代码][代码]image[代码][代码]>[代码][代码]</[代码][代码]view[代码][代码]>[代码] WXSS: [代码].view_container{[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]100%[代码][代码];[代码][代码] [代码][代码]height[代码][代码]: [代码][代码]100%[代码][代码];[代码][代码] [代码][代码]background-color[代码][代码]: [代码][代码]#c1c1c1[代码][代码];[代码][代码] [代码][代码]text-align[代码][代码]: [代码][代码]center[代码][代码];[代码][代码] [代码][代码]display[代码][代码]: flex;[代码][代码] [代码][代码]justify-[代码][代码]content[代码][代码]: [代码][代码]center[代码][代码];[代码][代码] [代码][代码]flex-[代码][代码]direction[代码][代码]: row;[代码][代码]}[代码][代码].view_camera{[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]500[代码][代码]rpx;[代码][代码] [代码][代码]height[代码][代码]: [代码][代码]500[代码][代码]rpx;[代码][代码]}[代码] JS: [代码]// pages/scan/scan.js[代码][代码]Page({[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 页面的初始数据[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]data: {[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 生命周期函数--监听页面加载[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]onLoad: [代码][代码]function[代码] [代码](options) {[代码][代码] [代码][代码]console.log([代码][代码]"loaded scan"[代码][代码]);[代码][代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 生命周期函数--监听页面初次渲染完成[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]onReady: [代码][代码]function[代码] [代码]() {[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 生命周期函数--监听页面显示[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]onShow: [代码][代码]function[代码] [代码]() {[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]scan: [代码][代码]function[代码] [代码](){[代码][代码] [代码][代码]console.log([代码][代码]'start scan'[代码][代码])[代码][代码] [代码][代码]const context = wx.createCameraContext()[代码][代码] [代码][代码]console.log([代码][代码]'created context'[代码][代码])[代码][代码] [代码][代码]context.takePhoto({ // 这是后来为了测试cameraContext是不是真的能运行而加上的,实际运行确实能拍照[代码][代码] [代码][代码]quality: [代码][代码]'high'[代码][代码],[代码][代码] [代码][代码]success: (res) => {[代码][代码] [代码][代码]console.log(res.tempImagePath)[代码][代码] [代码][代码]this[代码][代码].setData({[代码][代码] [代码][代码]src: res.tempImagePath[代码][代码] [代码][代码]})[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码][代码] [代码] [代码] [代码][代码]if[代码] [代码](context.onCameraFrame) {[代码][代码] [代码][代码]console.log([代码][代码]'onCameraFrame is available'[代码][代码]) // 这一句log每次都能顺利打出来[代码][代码] [代码][代码]const listener = context.onCameraFrame((frame) => {[代码][代码] [代码][代码]console.log([代码][代码]'fetch camera'[代码][代码]) // 这一句log从来没有打出来过[代码][代码] [代码][代码]// console.log(frame.data instanceof ArrayBuffer, frame.width, frame.height)[代码][代码] [代码][代码]})[代码][代码] [代码][代码]if[代码] [代码](listener.start) {[代码][代码] [代码][代码]listener.start()[代码][代码] [代码][代码]console.log([代码][代码]'listener start'[代码][代码])[代码][代码] [代码][代码]}[代码][代码] [代码][代码]} [代码][代码]else[代码] [代码]{[代码][代码] [代码][代码]console.log([代码][代码]'onCameraFrame is not available'[代码][代码])[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 生命周期函数--监听页面隐藏[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]onHide: [代码][代码]function[代码] [代码]() {[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 生命周期函数--监听页面卸载[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]onUnload: [代码][代码]function[代码] [代码]() {[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 页面相关事件处理函数--监听用户下拉动作[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]onPullDownRefresh: [代码][代码]function[代码] [代码]() {[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 页面上拉触底事件的处理函数[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]onReachBottom: [代码][代码]function[代码] [代码]() {[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码][代码] [代码][代码]* 用户点击右上角分享[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]onShareAppMessage: [代码][代码]function[代码] [代码]() {[代码] [代码] [代码][代码]}[代码][代码]})[代码] 真机调试日志输出窗口: [图片] 模拟器日志输出窗口: [图片]
2019-12-09目前好像没有办法做到实时AR的程度, 小程序端都不能做到30fps的将视频帧画面绘制到canvas上,处理帧率在10fps以下,使用node.js接收onCameraFrame的buffer,因为buffer过大,接收数据延迟也在100ms左右,不知道阿玛尼的案例是如何实现的,感觉很可能是微信官方开的绿色通道吧
CameraContext.onCameraFrame API设计方式存在缺陷?在真机(小米6)上大量实测后,发现获取camera frame数据,小程序设计为推送帧数据到js引擎之中的方式(测试为30帧速度,即每秒推送30个任务过来)。 这会导致,一旦js引擎存在密集计算型任务正在执行(比如使用asm/wasm做处理),推送过来的这些回调任务就会堆积。 既然使用了onCameraFrame接口,那很多应用场景就是图像计算处理。 此时当用户点击交互时,点击事件也被堆积在后面,导致程序一直不能响应事件。 这在交互体验上就是大问题。 希望能把推送的API设计,优化为js主动拉取的方式,这就能很好的避免这个问题。
2019-12-09