微信小程序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);
            }
        });
    },
相关推荐
蜗牛前端2 天前
codex 全流程开发上线的高颜值礼簿小程序
前端·微信小程序
爱勇宝6 天前
我想认真做一件小事:让孩子和家长更好地互动
微信小程序·小程序·云开发
唯火锅不可辜负6 天前
避坑指南:iOS 下 scroll-view 嵌套 fixed 布局的“翻车”现场与修复
微信小程序
didiplus6 天前
运维人的随身神器:我把25个常用工具塞进了微信小程序
微信小程序
一份执念7 天前
uni-app 小程序分包限制处理与主包体积优化实战
前端·微信小程序
一份执念7 天前
ECharts 安装与使用完全指南:从全量引入到小程序分包优化
微信小程序·echarts
skiyee8 天前
🔥UniApp 仅需 5 行代码!实现所有页面中控制应用主题变化
前端·微信小程序
Jinkey9 天前
要用户手机号真的是为了打骚扰电话吗?浅谈微信生态会员账号体系与资产合并
后端·微信·微信小程序
用户43242810611411 天前
微信小程序从0到1接入微信支付的完整攻略
微信小程序
spmcor13 天前
微信小程序 setStorageSync 踩坑实录:别让"顺手一存"变成"隐形炸弹"
微信小程序