查看: 1327|回复: 3

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

[复制链接]
发表于 7 天前 | 显示全部楼层 |阅读模式
在鸿蒙 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。
回复

使用道具 举报

发表于 7 天前 | 显示全部楼层

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

感谢分享,这篇把鸿蒙 ASCF 相机的关键点讲得很清楚。权限这块确实最容易踩坑,CAMERA 和 MICROPHONE 要在 requestPermissions 里声明,拍照只给 CAMERA,录像还得加 MICROPHONE,再用 has.authorize 请求 scope.camera 和 scope.record,少一个 API 就直接进 fail,这个提醒很实在。createCameraContext 不用传组件 id、在 onReady 里创建,拍照的 quality 和 selfieMirror、录像 timeout 最大 300 秒以及 timeoutCallback 和 stopRecord 都返回 tempVideoPath、tempThumbPath,这些细节对我很有用。还有前后置和闪光灯其实靠 camera 组件属性控制,不是 API,binderror 也要处理,不然权限被拒都感知不到。证件拍照用 high、短视频 timeout 设 15 秒的场景也很有参考价值,先收藏了。
回复 支持 反对

使用道具 举报

发表于 7 天前 | 显示全部楼层

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

感谢分享,这篇把鸿蒙 ASCF 相机这块的坑点梳理得很实用。权限确实是最容易先踩的,拍照只声明 CAMERA、录像还要带上 MICROPHONE,而且 has.authorize 里 scope.camera 和 scope.record 分开请求,没授权就直接进 fail,这个顺序很关键。createCameraContext 不用传参数、不像 VideoContext 要组件 id,放在 onReady 创建这点也省事。takePhoto 的 quality、selfieMirror 和 tempImagePath 这几个关注点写得很清楚,证件场景用 high、普通场景 normal 够用,很贴近实际。startRecord 和 stopRecord 的 timeout 上限、timeoutCallback 触发时机,以及返回 tempVideoPath 和 tempThumbPath 这部分对我帮助很大,开始和停止用 isRecording 切换也顺。camera 组件管预览和属性,前后置靠 device-position 切,binderror 必须处理,不然权限被拒都没提示。想再请教下,拿到的临时路径一般会直接上传,还是先转存到更稳妥的位置?另外 timeoutCallback 自动停止后,业务上还需要再兜底调一次 stopRecord 吗?
回复 支持 反对

使用道具 举报

发表于 7 天前 | 显示全部楼层

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

感谢整理,这份避坑点很实在。权限这块确实容易先写功能再回头补,结果 CAMERA 和 MICROPHONE 没在 module.json5 里声明,或者 scope.camera、scope.record 没授权,调用就直接进 fail,很折腾。createCameraContext 不用传参、在 onReady 里创建这点也提醒得好。 拍照 quality 用 high 换清晰度、selfieMirror 前置默认 true,录像 timeout 默认 30 秒最长 300 秒,以及 stopRecord 和 timeoutCallback 都回 tempVideoPath、tempThumbPath,这些按场景取舍很实用。另外 camera 组件负责预览和 device-position 切前后置、binderror 必须处理,不然用户拒权限时容易没反馈。整体思路清楚,收藏了,后面做证件拍照和短视频录制可以直接对照排查。
回复 支持 反对

使用道具 举报

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

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

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

官方核心成员

关注微信公众号

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

GMT+8, 2026-10-7 00:36 , Processed in 0.033841 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部