查看: 275|回复: 0

鸿蒙ASCF相机API拍照录像三方法与权限避坑实践

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在鸿蒙 ASCF 中,相机相关 API 的核心方法只有三个:takePhoto 拍照、startRecord 开始录像、stopRecord 结束录像。前后置切换、闪光灯、对焦等并不在 API 层提供,而是通过 camera 组件的属性控制。实际开发时,权限声明、camera 组件事件和临时路径处理反而更容易踩坑。

权限先配全:CAMERA 与 MICROPHONE
相机 API 需要两个系统权限,在 module.json5 的 requestPermissions 中声明:
  1. {
  2.   "requestPermissions": [
  3.     { "name": "ohos.permission.CAMERA" },
  4.     { "name": "ohos.permission.MICROPHONE" }
  5.   ]
  6. }
复制代码
拍照只需要 CAMERA,录像还需要 MICROPHONE,因为要录音。随后在代码中用 has.authorize 请求授权:
  1. has.authorize({
  2.   scope: 'scope.camera',
  3.   success: () => { console.info('相机权限已授权'); },
  4.   fail: (err) => { console.error('授权失败:', err); }
  5. });
  6. has.authorize({
  7.   scope: 'scope.record',
  8.   success: () => { console.info('录音权限已授权'); },
  9.   fail: (err) => { console.error('授权失败:', err); }
  10. });
复制代码
如果没拿到权限就调用相机 API,会直接进入 fail 回调。原文作者就因为没有先配权限,调了半天一直失败。

创建相机上下文
相机控制通过 CameraContext 完成。createCameraContext 不需要传参数,也不像 VideoContext 那样需要组件 id:
  1. Page({
  2.   onReady() {
  3.     this.ctx = has.createCameraContext();
  4.   }
  5. });
复制代码
注意要在页面加载完成后创建,放在 onLoad 或 onReady 中都可以。

拍照:takePhoto 的三个参数关注点
  1. this.ctx.takePhoto({
  2.   quality: 'high',
  3.   selfieMirror: false,
  4.   success: (res) => {
  5.     console.info('照片路径:', res.tempImagePath);
  6.   },
  7.   fail: (err) => {
  8.     console.error('拍照失败:', err);
  9.   }
  10. });
复制代码
quality 控制成像质量,有 high、normal、low 三档。实际体验 normal 够用,high 文件大不少,上传会更慢。selfieMirror 控制前置摄像头是否镜像,默认 true;自拍功能保持默认即可,若需要与后置方向一致可设为 false。拍照结果通过 res.tempImagePath 返回。

录像:startRecord 与 stopRecord
开始录像:
  1. this.ctx.startRecord({
  2.   timeout: 30,
  3.   timeoutCallback: (res) => {
  4.     console.info('录像超时,视频路径:', res.tempVideoPath);
  5.     console.info('封面路径:', res.tempThumbPath);
  6.   },
  7.   success: () => {
  8.     console.info('开始录像');
  9.   },
  10.   fail: (err) => {
  11.     console.error('录像失败:', err);
  12.   }
  13. });
复制代码
timeout 是录制时长上限,单位秒,默认 30,最长不能超过 5 分钟,也就是 300 秒。timeoutCallback 会在两种场景触发:录制时间达到 timeout 后自动停止,或者录像异常退出。返回值里包含 tempVideoPath 和 tempThumbPath。
结束录像:
  1. this.ctx.stopRecord({
  2.   success: (res) => {
  3.     console.info('视频路径:', res.tempVideoPath);
  4.     console.info('封面路径:', res.tempThumbPath);
  5.   },
  6.   fail: (err) => {
  7.     console.error('停止录像失败:', err);
  8.   }
  9. });
复制代码
stopRecord 的返回值和 timeoutCallback 一致,同样有视频路径和封面路径。一个按钮控制开始和停止时,可以用 isRecording 状态切换。

camera 组件负责预览和属性控制
API 只操作相机逻辑,画面预览要靠 camera 组件:
  1. <camera flash="off" mode="normal" device-position="back" frame-size="medium" binderror="onCameraError" bindstop="onCameraStop" bindinitdone="onCameraInit" />
复制代码
常用属性方面,flash 控制闪光灯,mode 一般用 normal,device-position 控制前后置,frame-size 控制帧大小。组件事件里 binderror 一定要处理,否则用户拒绝相机权限时无法感知:
  1. onCameraError(e) {
  2.   console.error('相机错误:', e.detail);
  3.   has.showToast({ title: '无法访问相机' });
  4. }
复制代码
前后置切换也不是 API,而是通过 camera 组件的 device-position 属性完成,例如在 data 中维护 position,再绑定到 device-position。

实际场景中的做法
证件拍照上传:takePhoto 建议用 quality 为 high,保证文字清晰;拿到 tempImagePath 后可用 has.getImageInfo 获取宽高,再上传服务器。短视频录制:startRecord 的 timeout 可设为 15 秒,超时回调中停止计时并处理 tempVideoPath;手动 stopRecord 成功后同样处理视频,可用 has.getVideoInfo 获取时长和分辨率。前后置切换:只更新绑定到 camera 组件的 device-position 值,不需要调用额外 API。

容易踩的坑
第一,权限不全导致录像没声音。拍照只需要 CAMERA,录像还需要 MICROPHONE,两个权限都要在 module.json5 声明并请求授权。
第二,takePhoto 的 quality 大小写。文档写的是 high、normal、low 小写,Demo 里用过 HIGH、MEDIUM、LOW 大写,实测两种都能用,但建议按文档使用小写。
第三,startRecord 的 timeout 不要超过 300 秒。超过 5 分钟可能被截断或报错,需要更长录制时间时可以考虑分段录制。
第四,临时路径要尽快使用。takePhoto 返回的 tempImagePath、stopRecord 返回的 tempVideoPath 都是临时路径;需要保存时及时调用 saveImageToPhotosAlbum 或 saveVideoToPhotosAlbum,临时文件可能在应用重启后被清理。
第五,camera 组件的 mode 不要随便设成 scanCode。扫码模式下拍照功能可能不正常,普通拍照录像用 mode="normal"。
第六,frame-size 影响清晰度和性能。small 低清晰度省性能,medium 中等,large 高清晰度更费性能;扫码场景 small 够用,拍照建议 medium 或 large。

Demo 与方案选择
原文项目中包含两个相机相关 Demo:组件级 Demo 展示 camera 组件基本用法;API 级 Demo 展示 CameraContext 的拍照和录像功能,包括三档画质拍照、开始/结束录像、超时自动停止、拍照结果预览和录像结果预览。
如果只是需要拍照或选视频,不一定要使用 camera 组件加 CameraContext。has.chooseImage 和 has.chooseVideo 也能调起系统相机,用法更简单。只有需要自定义相机界面,比如加滤镜、水印、实时预览时,才需要自己搭建 camera 组件并结合这套 API。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-30 12:26 , Processed in 0.020965 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部