import type { CameraFrame } from './types' type FrameListener = { start: () => void stop: () => void } type CameraContextLike = { onCameraFrame?: (cb: (frame: { width: number; height: number; data: ArrayBuffer }) => void) => FrameListener } function createContext(cameraId?: string): CameraContextLike | null { try { // uni-app 优先:可按 camera 组件 id 绑定 if (typeof uni !== 'undefined' && typeof uni.createCameraContext === 'function') { return uni.createCameraContext(cameraId || 'gripCamera') as CameraContextLike } } catch (_) {} // #ifdef MP-WEIXIN try { // @ts-ignore if (typeof wx !== 'undefined' && typeof wx.createCameraContext === 'function') { // @ts-ignore return wx.createCameraContext() as CameraContextLike } } catch (_) {} // #endif return null } export function isCameraFrameSupported(): boolean { try { const ctx = createContext('gripCamera') return typeof ctx?.onCameraFrame === 'function' } catch (_) { return false } } /** * 管理 CameraContext.onCameraFrame:只保留最新一帧,不入 Vue 响应式。 */ export function createCameraFramePump(options?: { cameraId?: string }) { let listener: FrameListener | null = null let latest: CameraFrame | null = null let running = false let callbackCount = 0 let fpsWindowStart = Date.now() let fps = 0 let onFrame: ((frame: CameraFrame) => void) | null = null function start(cb: (frame: CameraFrame) => void) { stop() onFrame = cb const ctx = createContext(options?.cameraId || 'gripCamera') if (!ctx?.onCameraFrame) { throw new Error('当前基础库不支持 onCameraFrame') } listener = ctx.onCameraFrame((raw) => { if (!running) return const frame: CameraFrame = { width: raw.width, height: raw.height, data: raw.data, ts: Date.now(), } latest = frame callbackCount += 1 const now = Date.now() if (now - fpsWindowStart >= 1000) { fps = callbackCount callbackCount = 0 fpsWindowStart = now } onFrame?.(frame) }) running = true listener.start() } function stop() { running = false try { listener?.stop() } catch (_) {} listener = null onFrame = null } function getLatest() { return latest } function getFps() { return fps } function isRunning() { return running } return { start, stop, getLatest, getFps, isRunning } } export type CameraFramePump = ReturnType