微信小程序camera相机帧转图片base64

适用于图像实时识别,形状识别,人脸识别等场景

相机组件

复制代码
        <camera class="camera-view" device-position="back" flash="off" binderror="onCameraError" bindinitdone="onCameraInit" frame-size="small">
            <!-- 扫描框 -->
            <view class="scan-frame"></view>
        </camera>

初始化相机

复制代码
   onCameraInit() {
        console.log('相机初始化完成');

        // 创建相机上下文
        this.cameraContext = wx.createCameraContext();

        // 获取系统信息判断平台
        const systemInfo = wx.getSystemInfoSync();
        const isIOS = systemInfo.platform === 'ios';

        let lastTime = 0;
        const interval = 3000; // 每3秒取一帧

        try {
            this.frameListener = this.cameraContext.onCameraFrame((frame) => {
                const now = Date.now();
                if (now - lastTime < interval) return; // 跳过多余帧
                lastTime = now;

                if (!frame || !frame.data || frame.data.byteLength === 0) {
                    console.warn('帧数据为空或无效');
                    return;
                }

                console.log('取到一帧', frame.width, frame.height, frame.data.byteLength);

                // 转成图片 base64
                this.frameToBase64(frame).then((base64: string) => {
                    // 调用识别 API
                    this.recognizeFrameData(base64, frame.width, frame.height);
                }).catch((error: any) => {
                    console.error('frameToBase64 转换失败:', error);
                });
            });

            // iOS 使用 worker,Android 不使用
            if (isIOS) {
                try {
                    this.worker = wx.createWorker('workers/cameraWorker.js', {
                        useExperimentalWorker: true
                    });
                    this.frameListener.start({ worker: this.worker });
                } catch (error) {
                    console.error('创建 Worker 失败,使用普通模式:', error);
                    this.frameListener.start();
                }
            } else {
                this.frameListener.start();
            }

            console.log('相机帧监听器已启动');
        } catch (error) {
            console.error('启动相机帧监听失败:', error);
        }


    },

注意ios要使用workers

相关代码

复制代码
// workers/cameraWorker.js
setInterval(() => {
  try {
    const frameData = worker.getCameraFrameData(); // ArrayBuffer
    if (frameData.byteLength === 0) return;

    // base64 转换
    const base64 = wx.arrayBufferToBase64(frameData);
    console.log('iOS 帧 base64 长度', base64.length);

    // 可以 postMessage 给主线程做处理
    worker.postMessage({ base64 });
  } catch (err) {
    console.error(err);
  }
}, 1000); // 每秒处理一帧

这里直接获取的帧需要转换成图片base64,为什么要转?

小程序相机每一帧给的是 原始 RGBA 像素数据,并不能直接使用,而是需要转换。

目前的方案是创建一个canvas将图片像素图绘制上去,然后再把 canvas 内容 转成 Base64 格式的 JPEG。

复制代码
   frameToBase64(frame: any): Promise<string> {
        return new Promise((resolve, reject) => {
            try {
                // 创建离屏 canvas
                const canvas = wx.createOffscreenCanvas({ 
                    type: '2d',
                    width: frame.width, 
                    height: frame.height 
                });
                
                const ctx = canvas.getContext('2d');
                
                if (!ctx) {
                    reject(new Error('Failed to get canvas context'));
                    return;
                }

                // 创建 ImageData 对象
                const imageData = ctx.createImageData(frame.width, frame.height);
                
                // 将帧数据复制到 ImageData
                const data = new Uint8Array(frame.data);
                imageData.data.set(data);
                
                // 将 ImageData 绘制到 canvas
                ctx.putImageData(imageData, 0, 0);
                
                // 转为 base64 - 使用同步方式
                try {
                    const base64 = canvas.toDataURL({
                        type: 'image/jpeg',
                        quality: 0.8
                    });
                    resolve(base64);
                } catch (e) {
                    reject(e);
                }
            } catch (error) {
                reject(error);
            }
        });
    },
相关推荐
说私域1 小时前
分享经济应用:以“开源链动2+1模式AI智能名片S2B2C商城小程序”为例
人工智能·小程序·开源
一 乐5 小时前
智慧养老|基于springboot+小程序社区养老保障系统设计与实现(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端·小程序
小小王app小程序开发7 小时前
盈利 + 留存双驱动:分销商城小程序的增长法则与落地指南
小程序
不如摸鱼去7 小时前
uni-app 也能远程调试?使用 PageSpy 打开调试的新大门!
前端·小程序·uni-app
峰兄1983058 小时前
8266实现Modbus TCP协议转RTU串口通讯之旅
小程序
黑马源码库miui520869 小时前
JAVA成人用品商城系统源码微信小程序+h5+安卓+ios
android·java·微信小程序
UI设计兰亭妙微9 小时前
从“功能堆砌“到“体验至上“的蜕变之路:兰亭妙微如何助力“臻选生活馆“实现小程序重生与业绩倍增
小程序·小程序开发
万岳软件开发小城9 小时前
开发一套私域直播 APP/Web/小程序需要哪些核心模块?完整技术清单来了
小程序·php·直播带货系统源码·直播带货软件开发·私域直播系统源码·私域直播平台搭建·私域直播软件开发
计算机毕设指导69 小时前
基于微信小程序的篮球场馆预订系统【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·tomcat·maven
闹小艾10 小时前
制作知识付费线上课程小程序:制作平台实操指南,不用编程3分钟学会搭建
小程序