更新记录
1.1.6(2026-07-29)
-优化Android的返回按钮 关闭相机事件
1.1.5(2026-07-29)
-优化界面 -增加手势缩放 -手电筒等等若干优化功能
1.1.4(2026-07-28)
-重新上传插件包
查看更多平台兼容性
uni-app(4.18)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| - | - | × | × | - | - | 7.0 | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | - | × | - | - | - | - |
uni-app x(4.18)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | - | - | - | - |
ly028-Camera UTS 三端实时帧相机
真实案例体验
门禁 / 考勤类真实项目落地(ly028-reg):人脸注册、人脸库管理、拍照识别、实时相机流识别。
实时相机流 OCR 识别(ly028-cameraOCR)-- 基于 ly028-Camera 帧捕获 + ly028-OCR 流式识别,实时文字识别。
实际接入项目:人脸识别考勤打卡(Camera + OffFace 组合方案) 扫码体验完整的人脸识别打卡 App:
| 插件 | 下载 | 插件市场 |
|---|---|---|
| ly028-Camera(本插件) | ![]() 📱 下载 APK |
https://ext.dcloud.net.cn/plugin?id=28471 |
| ly028-OffFace(人脸检测识别) | ![]() 📱 下载 APK |
https://ext.dcloud.net.cn/plugin?id=28446 |
Android / iOS / HarmonyOS 原生相机 UTS 插件,实时多格式帧数据输出(NV12/NV21/YUV420P/BGR888/RGBA8888),全屏原生 UI 预览(Android/iOS),适用于人脸识别(seetaface6)、AI 视觉等场景。
特性
- 📷 全屏原生相机 UI — Android/iOS 全屏原生相机 UI(鸿蒙需 uni-app x 配合 XComponent)
- 🔄 实时多格式帧捕获 — 支持 NV12 / NV21 / YUV420P (I420) / BGR888 / RGBA8888 逐帧回调,无需前端转换即可直接喂给 AI 引擎(seetaface6/MediaPipe/OpenCV)
- 📱 三端一致 API — Android / iOS / HarmonyOS API 完全相同,调用端无平台差异
- 🎯 拍照 + 录像 — 支持拍照和视频录制
- 👤 人脸框叠加 — 支持实时人脸检测框与标签文字叠加显示
- 🔦 手电筒 — 原生 UI 手电筒按钮,点击点亮/关闭
- 👆 点击对焦 — 触摸屏幕自动对焦到点击位置(原生手势,无需 API)
- ⇆ 双指变焦 — 双指捏合拉近拉远,显示变焦倍数(原生手势,无需 API)
- 🔄 文字自适应 — 框标签文字自动沿长边旋转 + 面积法自动字号
- 📱 沉浸式全屏兼容 — 适配挖孔屏/刘海屏系统栏,预览不变形
- 🧩 UTS 插件 — uni-app 原生插件,即插即用
平台兼容
| 平台 | 最低版本 | 架构 | 预览 UI | 无界面帧捕获 |
|---|---|---|---|---|
| Android | 7.0 (API 24) | arm64-v8a, armeabi-v7a | ✅ 全屏原生 | ✅ |
| iOS | 12.0 | arm64 | ✅ 全屏原生 | ✅ |
| HarmonyOS (uni-app x) | API 12 | arm64 | ✅ 需 xcomponentId |
✅ |
| HarmonyOS (普通 uni-app) | API 12 | arm64 | ❌ 见下文 | ✅ |
鸿蒙(HarmonyOS)特别说明
架构限制
鸿蒙 ArkUI 与 iOS/Android 的 UI 架构有本质区别,这直接影响了相机预览的实现方式:
| 平台 | 创建全屏预览方式 |
|---|---|
| iOS | keyWindow.addSubview(cameraView) — UIKit 允许任意添加 UIView |
| Android | decorView.addView(nativeView) — Android View 系统允许任意添加 View |
| 鸿蒙 | 没有等价 API — ArkUI 组件树由框架统一管理,后台代码无法插入可见节点 |
iOS/Android 可以直接在插件后端创建全屏相机 View。鸿蒙则必须在页面组件树中有一个 <XComponent> 或 <NodeContainer> 作为相机预览的挂载点。
xcomponentId 参数(仅 uni-app x)
如果你使用 uni-app x,可以在 CameraOptions 中传入 XComponent 的 id:
import { openCamera } from '@/uni_modules/ly028-Camera'
openCamera(JSON.stringify({
position: 'back',
enableFrameCapture: true,
xcomponentId: 'camera-preview', // 页面中 <XComponent> 的 id
format: 'rgba',
}), (res) => {
if (JSON.parse(res).code === 0) {
console.log('相机已启动(带预览)')
}
})
当 xcomponentId 不为空时:
- 插件用该 id 创建
PreviewOutput并加到相机 session - XComponent 上会显示实时相机画面
enableFrameCapture: true同时获取帧数据
普通 uni-app(WebView)
普通 uni-app 的页面运行在 WebView 中,无法嵌入 ArkUI 原生 XComponent。因此在鸿蒙上:
- 无相机预览画面
- 但帧数据捕获正常工作 — 可通过
onFrame获取 NV12/NV21/YUV420P/BGR888/RGBA 帧数据用于 AI 处理 - API 调用方式与 Android/iOS 完全一致
三端 API 一致性
无论是否有预览,所有平台使用相同的 API:
import { openCamera, closeCamera, onFrame, onCameraClosed } from '@/uni_modules/ly028-Camera'
// 打开相机(三端一致)
openCamera(JSON.stringify({
enableFrameCapture: true,
format: 'nv12',
maxFps: 15
}), () => {})
// 获取帧数据(三端一致)
onFrame((json) => {
const frame = JSON.parse(json)
console.log(frame.width, frame.height, frame.format)
})
| `closeCamera()` | 关闭相机释放资源 |
onCameraClosed(() => {
console.log('相机已关闭')
})
// 关闭相机(三端一致)
| `closeCamera()` | 关闭相机释放资源 |
集成与调试
HBuilderX 自定义基座运行
- 插件市场购买插件后,在
manifest.json→ App 原生插件配置中选择ly028-Camera - 选择需要使用的模块
- 自定义调试基座:菜单栏 → 运行 → 运行到手机或模拟器 → 制作自定义调试基座
- 制作完成后,选择自定义基座运行到真机即可调试所有功能
首次使用请确保已关联 uni-app 开发者证书,自定义基座有效期为 7 天,过期后需重新制作。
离线打包
插件为原生代码插件,离线打包需自行集成原生依赖。
快速开始
import { openCamera, closeCamera, onFrame, onCameraClosed } from '@/uni_modules/ly028-Camera'
// 1. 打开相机纯帧捕获模式(无 UI,直接回调帧数据)
openCamera(JSON.stringify({
position: 'front',
enableFrameCapture: true,
format: 'rgba', // 输出格式:nv12 / nv21 / yuv420p / bgr888 / rgba
maxFps: 15, // 帧率上限
}), (res) => {
if (JSON.parse(res).code === 0) {
console.log('相机已启动')
}
})
// 2. 监听帧数据
onFrame((json) => {
const frame = JSON.parse(json)
// frame: { data: base64, width, height, format, timestamp, rotation, position }
console.log('帧:', frame.width, 'x', frame.height, 'format:', frame.format)
// RGBA 帧可直接喂给 OffFace
// import { detectFace } from '@/uni_modules/ly028-OffFace'
// const buf = uni.base64ToArrayBuffer(frame.data)
// const result = detectFace(buf, frame.width, frame.height, 4)
})
| `closeCamera()` | 关闭相机释放资源 |
onCameraClosed(() => {
console.log('相机已关闭')
})
// 4. 关闭相机
| `closeCamera()` | 关闭相机释放资源 |
全量 API 参考
相机生命周期
| API | 说明 |
|---|---|
openCamera(options, callback) |
打开相机预览 |
stopPreview() |
停止预览(冻结画面,不释放相机资源) |
closeCamera() |
关闭相机释放资源 |
帧捕获
| API | 说明 |
|---|---|
onFrame(callback) |
注册帧数据回调 |
offFrame() |
移除帧数据回调 |
updateFaceRects(json) |
更新人脸框(坐标/标签/颜色) |
updateDebugInfo(json) |
显示调试文字(text/color/x/y/fontSize) |
帧捕获格式 — 通过 FrameCaptureOptions 的 format 字段指定:
| 格式 | 说明 | 字节/像素 | 用途 |
|---|---|---|---|
'nv12' |
NV12 Y+交错UV | 1.5 | 默认,iOS 原生输出 |
'nv21' |
NV21 Y+交错VU | 1.5 | Android 相机常见格式 |
'yuv420p' |
I420 平面 Y+U+V | 1.5 | 标准 YUV 交换格式 |
'bgr888' |
BGR888 B,G,R | 3 | seetaface6 引擎内部格式 |
'rgba' |
RGBA8888 R,G,B,A | 4 | 可直接喂给 OffFace detectFace(data, w, h, 4) |
updateFaceRects — 人脸框 JSON schema
传入 JSON 数组字符串。坐标为帧空间(与 onFrame 的 width/height 一致),插件会缩放到预览层;前置摄像头会自动水平镜像 X。
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
x / y |
number |
✅ | — | 框左上角(帧坐标) |
width / height |
number |
✅ | — | 框宽高(帧坐标) |
color |
string |
❌ | '#00FF00' |
边框色,#RGB / #RRGGBB / #RRGGBBAA |
label |
string |
❌ | '' |
框上方文字 |
fontSize |
number |
❌ | 24 |
标签字号 |
fontColor |
string |
❌ | '#FFFFFF' |
标签颜色 |
autoAngle |
boolean |
❌ | true |
true=竖长框文字自动旋转 90° 沿长边 |
autoFontSize |
boolean |
❌ | false |
true=字号按框面积 √(w×h)/5 自动计算,忽略 fontSize |
angle |
number |
❌ | 0 |
文字旋转角度(autoAngle=false 时可手动指定) |
import { updateFaceRects } from '@/uni_modules/ly028-Camera'
// 绘制人脸框
updateFaceRects(JSON.stringify([
{
x: 100, y: 200, width: 120, height: 120,
color: '#00FF00', label: '人脸1',
fontSize: 15, fontColor: '#FFFFFF'
}
]))
// 清空所有框
updateFaceRects('[]')
updateDebugInfo — 调试文字 JSON schema
传入 JSON 对象字符串。text 为空字符串时清屏;支持 \n 换行。
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
text |
string |
✅ | — | 显示文字;'' 清屏 |
x / y |
number |
❌ | 10 |
预览层像素坐标 |
color |
string |
❌ | '#00FF00' |
文字颜色 |
fontSize |
number |
❌ | 14 |
字号 |
import { updateDebugInfo } from '@/uni_modules/ly028-Camera'
updateDebugInfo(JSON.stringify({
text: '640x480 120KB #42\nfmt: rgba',
x: 16, y: 24, color: '#00FF00', fontSize: 14
}))
// 清屏
updateDebugInfo(JSON.stringify({ text: '' }))
拍照
| API | 说明 |
|---|---|
onPhoto(callback) |
注册拍照结果回调 |
offPhoto() |
移除拍照结果回调 |
签名:(json: string) => void。json 为统一信封;data 是嵌套 JSON 字符串,需再 JSON.parse 一次。拍照按钮与相册选择都走同一回调。
import { onPhoto, offPhoto } from '@/uni_modules/ly028-Camera'
onPhoto((json) => {
const r = JSON.parse(json)
if (r.code === 0 && r.data) {
const d = JSON.parse(r.data)
// d: { filePath, width, height }
console.log('照片:', d.filePath, d.width, 'x', d.height)
}
})
// 页面卸载时移除
offPhoto()
成功载荷示例:
{
"code": 0,
"msg": "OK",
"data": "{\"filePath\":\"/path/to/photo.jpg\",\"width\":1920,\"height\":1080}"
}
相册选择时
width/height可能为0(平台未解析图片尺寸)。
事件
| API | 说明 |
|---|---|
onError(callback) |
错误回调 (code, subCode?, msg) |
offError() |
移除错误回调 |
onCameraClosed(callback) |
相机已关闭回调 |
offCameraClosed() |
移除关闭回调 |
onError — 三参签名
签名:(code: number, subCode: number | null, msg: string) => void。与其它 API 的 JSON 信封回调不同,错误事件直接传三个独立参数。
import { onError } from '@/uni_modules/ly028-Camera'
onError((code, subCode, msg) => {
console.log('相机错误:', code, subCode, msg)
// code 恒为 1;subCode 为 HTTP 风格细分码
})
常见 subCode:
| subCode | 含义 |
|---|---|
400 |
参数错误 / 为空 |
404 |
资源未找到(如无可用相机) |
422 |
操作不支持 |
500 |
内部错误 |
501 |
平台不支持 |
502 |
外部错误 |
503 |
服务不可用 |
onCameraClosed — 零参签名
| closeCamera() | 关闭相机释放资源 |
import { onCameraClosed, offCameraClosed } from '@/uni_modules/ly028-Camera'
onCameraClosed(() => {
console.log('相机已关闭')
})
offCameraClosed()
权限
| API | 说明 |
|---|---|
checkCameraPermission() |
检查相机权限 → Boolean |
CameraOptions
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
position |
'back' \| 'front' |
'back' |
相机位置 |
resolution |
{width, height} |
自动 | 预览分辨率 |
fps |
number |
30 | 预览帧率 |
focusMode |
'auto' \| 'continuous' \| 'tap' \| 'locked' |
'continuous' |
对焦模式 |
exposureMode |
'auto' \| 'continuous' \| 'locked' |
'auto' |
曝光模式 |
flashMode |
'off' \| 'on' \| 'auto' \| 'torch' |
'off' |
闪光模式 |
whiteBalance |
'auto' \| 'sunlight' \| 'cloudy' \| 'fluorescent' \| 'incandescent' |
'auto' |
白平衡 |
resizeMode |
'cover' \| 'contain' \| 'fill' |
'cover' |
预览缩放 |
enableAudio |
boolean |
true |
录像是否录音 |
enableFrameCapture |
boolean |
false |
启用帧捕获模式 |
xcomponentId |
string |
'' |
鸿蒙 uni-app x 专用:XComponent 的 id,不为空时显示预览画面 |
format |
string |
'nv12' |
帧输出格式 |
maxFps |
number |
15 | 帧捕获最大帧率 |
debug |
boolean |
false |
调试日志开关 |
返回值格式
所有 API 返回统一 JSON 信封:
// 成功
{"code": 0, "msg": "OK"}
// 带数据(拍照:data 为嵌套 JSON 字符串,含 filePath / width / height)
{"code": 0, "data": "{\\"filePath\\":\\"/path/to/photo.jpg\\",\\"width\\":1920,\\"height\\":1080}"}
// 失败
{"code": 1, "subCode": 500, "msg": "错误描述"}
帧数据结构
{
"data": "<base64 编码帧数据>",
"width": 640,
"height": 480,
"format": "rgba",
"timestamp": 1712345678000,
"rotation": 90,
"position": "front"
}
- 格式:
data为 Base64 编码字符串,需前端解码为ArrayBuffer使用 - 数据类型:根据
format不同,每像素字节数不同(nv12/nv21/yuv420p=1.5B,bgr888=3B,rgba=4B)
帧数据传输:Base64 方案说明
帧数据采用 Base64 编码字符串 传输,而非 ArrayBuffer 或 byte[]。
选择 Base64 的原因:兼容 uni-app 和 uni-app x,三端类型统一。
| 方案 | uni-app JS | uni-app x UTS | Android | iOS | HarmonyOS |
|---|---|---|---|---|---|
ArrayBuffer |
✅ 支持 | ❌ uni-app x 不支持 | ✅ | ✅ | ❌ |
Uint8Array |
✅ | ❌ 类型不一致 | — | — | — |
String (Base64) |
✅ base64ToArrayBuffer |
✅ base64ToArrayBuffer |
✅ Base64.decode |
✅ Data(base64Encoded:) |
✅ 内置 Base64 |
byte[] (原生) |
❌ 无法直传 | ✅ 但跨平台不一致 | ✅ | ❌ | ✅ |
结论: Base64 是 Android / iOS / HarmonyOS 三端和 uni-app / uni-app x 两种模式下唯一都能直接处理的帧数据格式。前端或后端业务层按需解码即可。
注意事项
- 帧数据较大(1080p 约 3MB/帧),建议按需开启
frameCallback - 相机权限需在 manifest.json 中配置
CAMERA、RECORD_AUDIO权限 - 前后切换会短暂黑屏,属正常现象
- 不支持模拟器,请在真机上调试
隐私声明
- 本插件不采集任何用户数据
- 所有相机操作在设备端本地完成
- 不上传任何图像或视频数据
体验
实际接入项目:人脸识别考勤打卡(Camera + OffFace 组合)
以下 APK 为 Camera + OffFace 人脸识别的完整集成示例,扫码可下载 Android 体验包。
| 插件 | 下载 | 插件市场 |
|---|---|---|
| ly028-Camera(本插件) | ![]() 📱 下载 APK |
https://ext.dcloud.net.cn/plugin?id=28471 |
| ly028-OffFace(人脸检测) | ![]() 📱 下载 APK |
https://ext.dcloud.net.cn/plugin?id=28446 |
Camera 提供实时帧数据,OffFace 进行人脸检测/识别,两者组合即可实现完整的端上人脸识别方案。
许可
- 插件市场购买后获得使用授权
- 禁止反编译、二次分发

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)


下载 926
赞赏 0
下载 12490186
赞赏 1938
赞赏
京公网安备:11010802035340号