鸿蒙实战开发Camera组件:【相机】
相机组件支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。
基本概念
-
拍照
此功能用于拍摄采集照片。
-
预览
此功能用于在开启相机后,在缓冲区内重复采集摄像帧,支持在拍照或录像前进行摄像帧预览显示。
-
录像
此功能用于在开始录像后和结束录像前的时间段内,在缓冲区内重复采集摄像帧,支持视频录制。
图 1 相机组件架构图

目录
仓目录结构如下:
/foundation/multimedia/camera_framework # 相机组件业务代码
├── frameworks # 框架代码
│ ├── native # 内部接口实现
│ │ ├── camera # 相机框架实现
│ │ └── metadata # 元数据实现
│ └── js # 外部接口实现
│ └── camera_napi # 相机NAPI实现
├── interfaces # 接口代码
│ ├── inner_api # 内部接口
│ └── kits # 外部接口
├── LICENSE # 许可证文件
├── ohos.build # 构建文件
├── sa_profile # 服务配置文件
└── services # 服务代码├── camera_service # 相机服务实现└── etc # 相机服务配置
使用说明
拍照
拍照的步骤:
-
创建缓冲区消费者端监听器(CaptureSurfaceListener)以保存图像。
class CaptureSurfaceListener : public IBufferConsumerListener { public:int32_t mode_;sptr<Surface> surface_;void OnBufferAvailable() override{int32_t flushFence = 0;int64_t timestamp = 0;OHOS::Rect damage; // initialize the damageOHOS::sptr<OHOS::SurfaceBuffer> buffer = nullptr;surface_->AcquireBuffer(buffer, flushFence, timestamp, damage);if (buffer != nullptr) {void* addr = buffer->GetVirAddr();int32_t size = buffer->GetSize();// Save the buffer(addr) to a file.surface_->ReleaseBuffer(buffer, -1);}} }; -
获取相机管理器实例并获取相机对象列表。
sptr<CameraManager> camManagerObj = CameraManager::GetInstance(); std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras(); -
使用相机对象创建相机输入来打开相机。
sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); -
创建采集会话。
sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession(); -
开始配置采集会话。
int32_t result = captureSession->BeginConfig(); -
将相机输入添加到采集会话。
result = captureSession->AddInput(cameraInput); -
创建消费者 Surface 并注册监听器以监听缓冲区更新。拍照的宽和高可以配置为所支持的 1280x960 分辨率。
sptr<Surface> photoSurface = Surface::CreateSurfaceAsConsumer(); int32_t photoWidth = 1280; int32_t photoHeight = 960; photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight); photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG)); sptr<CaptureSurfaceListener> capturelistener = new(std::nothrow) CaptureSurfaceListener(); capturelistener->mode_ = MODE_PHOTO; capturelistener->surface_ = photoSurface; photoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)capturelistener); -
使用上面创建的 Surface 创建拍照输出。
sptr<CaptureOutput> photoOutput = camManagerObj->CreatePhotoOutput(photoSurface); -
将拍照输出添加到采集会话。
result = captureSession->AddOutput(photoOutput); -
将配置提交到采集会话。
result = captureSession->CommitConfig(); -
拍摄照片。
result = ((sptr<PhotoOutput> &)photoOutput)->Capture(); -
释放采集会话资源。
captureSession->Release(); -
释放相机输入关闭相机。
cameraInput->Release();
开始和停止预览
开始和停止预览的步骤:
-
获取相机管理器实例并获取相机对象列表。
sptr<CameraManager> camManagerObj = CameraManager::GetInstance(); std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras(); -
使用相机对象创建相机输入来打开相机。
sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); -
创建采集会话。
sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession(); -
开始配置采集会话。
int32_t result = captureSession->BeginConfig(); -
将相机输入添加到采集会话。
result = captureSession->AddInput(cameraInput); -
使用从窗口管理器获得的 Surface 创建预览输出用以在显示上渲染。预览的宽和高可以配置为所支持的 640x480 或 832x480 分辨率,如果想保存到文件,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。
int32_t previewWidth = 640; int32_t previewHeight = 480; previewSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP)); sptr<CaptureOutput> previewOutput = camManagerObj->CreateCustomPreviewOutput(previewSurface, previewWidth, previewHeight); -
将预览输出添加到采集会话。
result = captureSession->AddOutput(previewOutput); -
将配置提交到采集会话。
result = captureSession->CommitConfig(); -
开始预览。
result = captureSession->Start(); -
需要时停止预览。
result = captureSession->Stop(); -
释放采集会话资源。
captureSession->Release(); -
释放相机输入关闭相机。
cameraInput->Release();
视频录像
视频录像的步骤:
-
获取相机管理器实例并获取相机对象列表。
sptr<CameraManager> camManagerObj = CameraManager::GetInstance(); std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras(); -
使用相机对象创建相机输入来打开相机。
sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); -
创建采集会话。
sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession(); -
开始配置采集会话。
int32_t result = captureSession->BeginConfig(); -
将相机输入添加到采集会话。
result = captureSession->AddInput(cameraInput); -
通过 Surface 创建一个视频输出,来与音频合成并保存到文件,Surface 通过 Recoder 获取。如果想仅保存视频缓冲数据到文件里,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。录像的分辨率可以在录制器内配置为所支持的 1280x720 或 640x360 分辨率。
videoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP)); sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoSurface); -
将视频输出添加到采集会话。
result = captureSession->AddOutput(videoOutput); -
将配置提交到采集会话。
result = captureSession->CommitConfig(); -
开始视频录制。
result = ((sptr<VideoOutput> &)videoOutput)->Start(); -
需要时停止录制。
result = ((sptr<VideoOutput> &)videoOutput)->Stop(); -
释放采集会话的资源。
captureSession->Release(); -
释放相机输入关闭相机。
cameraInput->Release();
切换多个照相机设备
以下演示如何切换多个照相机设备。最初在采集会话中有一个视频输出(video output)。如果用户想要切换其他 照相机,现存的相机输入和输出需要先移除并加入新的相机输入和输出(示例中使用的是photo output)。
-
获取相机管理器实例并获取相机对象列表。
sptr<CameraManager> camManagerObj = CameraManager::GetInstance(); std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras(); -
使用相机对象创建相机输入来打开相机。
sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); -
创建采集会话。
sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession(); -
开始配置采集会话。
int32_t result = captureSession->BeginConfig() -
将相机输入添加到采集会话。
result = captureSession->AddInput(cameraInput); -
通过Surface创建一个视频输出。
sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoSurface); -
将视频输出添加到采集会话。
result = captureSession->AddOutput(videoOutput); -
将配置提交到采集会话。
result = captureSession->CommitConfig(); -
开始录制视频。
result = ((sptr<VideoOutput> &)videoOutput)->Start(); -
需要时停止录制。
result = ((sptr<VideoOutput> &)videoOutput)->Stop(); -
重新配置会话并移除相机输入和输出。
int32_t result = captureSession->BeginConfig(); -
在新的会话配置中移除相机输入。
int32_t result = captureSession->RemoveInput(cameraInput); -
同样移除相机输出。
int32_t result = captureSession->RemoveOutut(videoOutput); -
创建新的相机输入,并把它添加到采集会话。
sptr<CaptureInput> cameraInput2 = camManagerObj->CreateCameraInput(cameraObjList[1]); result = captureSession->AddInput(cameraInput2); -
创建拍照输出,成功创建后将拍照输出添加到采集会话。创建消费者 Surface 并注册监听器以监听新的拍照输出缓冲区更新。这个 Surface 用于新创建的拍照输出。
// Get the surface sptr<Surface> photoSurface = Surface::CreateSurfaceAsConsumer(); int32_t photoWidth = 1280; int32_t photoHeight = 960; photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight); photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG)); sptr<CaptureSurfaceListener> capturelistener = new(std::nothrow) CaptureSurfaceListener(); capturelistener->mode_ = MODE_PHOTO; capturelistener->surface_ = photoSurface; photoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)capturelistener);// Create the Photo Output sptr<CaptureOutput> photoOutput = camManagerObj->CreatePhotoOutput(photoSurface);// Add the output to the capture session result = captureSession->AddOutput(photoOutput); -
将配置提交到采集会话。
result = captureSession->CommitConfig(); -
释放被移出会话的相机输入。
cameraInput->Release(); -
拍摄照片。
result = ((sptr<PhotoOutput> &)photoOutput)->Capture(); -
释放采集会话资源。
captureSession->Release(); -
释放相机输入关闭相机。
cameraInput2->Release();
设置闪光灯
拍照和录像前可以在相机输入里设置闪光灯。
-
在照相中设置闪光灯。
cameraInput->LockForControl(); cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_OPEN); cameraInput->UnlockForControl(); -
在录像中设置闪光灯。
cameraInput->LockForControl(); cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_ALWAYS_OPEN); cameraInput->UnlockForControl(); -
关闭闪光灯。
cameraInput->LockForControl(); cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_CLOSE); cameraInput->UnlockForControl();鸿蒙OpenHarmony知识已更新←前往

相关文章:
鸿蒙实战开发Camera组件:【相机】
相机组件支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。 基本概念 拍照 此功能用于拍摄采集照片。 预览 此功能用于在开启相机后,在缓冲区内重复采集…...
政安晨:【深度学习处理实践】(三)—— 处理时间序列的数据准备
在深度学习中,对时间序列的处理主要涉及到以下几个方面: 序列建模:深度学习可以用于对时间序列进行建模。常用的模型包括循环神经网络(Recurrent Neural Networks, RNN)和长短期记忆网络(Long Short-Term M…...
PCL不同格式点云读取速度(Binary和ASCII )
首先说明一点:Binary(二进制)格式点云文件进行读取时要比Ascll码格式点云读取时要快的多,尤其是对于大型的点云文件,如几百万、甚至几千万个点云的情况下。 今天遇到了一种情况,在写项目的时候进行点云读取,读取的时候…...
Neo4J图数据库入门示例
前言 - Neo4j和MySQL的区别 Neo4j 和 MySQL 是两种不同类型的数据库,它们在数据模型、用途、性能和查询语言等方面有着显著的区别。以下是它们的主要区别: 数据模型: Neo4j 是一种图数据库,它使用图数据模型来存储和查询数据。在…...
牛客每日一题之 二维前缀和
题目介绍: 题目链接:【模板】二维前缀和_牛客题霸_牛客网 先举两个简单的例子,来帮大家理解题目,注意理解二维前缀和要先要一维前缀和的基础,不了解的可以看我上一篇博客。 若x11,y11, x23, y2 3,这是要…...
动态规划 Leetcode 70 爬楼梯
爬楼梯 Leetcode 70 学习记录自代码随想录 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 示例 1: 输入:n 2 输出:2 解释:有两种方法可以爬到…...
(未解决)macOS matplotlib 中文是方框
reference: Mac OS系统下实现python matplotlib包绘图显示中文(亲测有效)_mac plt 中文值-CSDN博客 module ‘matplotlib.font_manager‘ has no attribute ‘_rebuild‘解决方法_font_manager未解析-CSDN博客 # 问题描述(笑死 显而易见 # solve 找到…...
深入探讨C#中的递归算法
一、什么是递归算法? 递归是指一个函数或方法在执行过程中调用自身的情况。递归算法是编程中常见的一种解决问题的方法。它将一个问题分解成一个或多个与原问题相似但规模更小的子问题,然后通过解决这些子问题来解决原问题。递归算法通常用于解决重复性的…...
三款顶级开源RAG (检索增强生成)工具:Verba、Unstructured 和 Neum
三款顶级开源RAG (检索增强生成)工具:Verba、Unstructured 和 Neum 概述 随着企业对话式数据处理需求的提升,面临的挑战是数据隐私性和缺乏企业级解决方案。虽然类似LangChain能在短时间内构建RAG应用,但忽视了文档解析、多来源数据ETL、批量…...
VC++、MFC中操作excel时,CRange中get_EntireRow()和get_EntireColumn()函数的用法及区别是什么?
在VC和MFC中操作Excel时,通过COM接口与Excel交互时,CRange 对象(或更准确地说是 Excel::Range 对象)代表一个单元格范围。CRange 类提供了一系列方法来获取或操作这个范围内的单元格。其中,get_EntireRow() 和 get_Ent…...
npm 操作报错记录1- uninstall 卸载失效
npm 操作报错记录1- uninstall 卸载失效 1、问题描述 安装了包 vue/cli-plugin-eslint4.5.0 vue/eslint-config-prettier9.0.0 但是没有使用 -d ,所以想重新安装,就使用 uninstall 命令卸载,结果卸载了没反应,也没有报错…...
openCV保存图像
保存图像 //保存为png透明通道vector<int>opts;opts.push_back(IMWRITE_PAM_FORMAT_RGB_ALPHA);imwrite("D:/img_bgra.png", img, opts);//保存为单通道灰度图像img cv::imread(imagePath.toStdString(), IMREAD_GRAYSCALE);vector<int> opts_gray;opts…...
mac 配置.bash_profile不生效问题
1、问题描述 mac系统中配置了环境变量只能在当前终端生效,切换了终端就无效了,查了下问题所在。mac系统会预装一个终极shell - zsh,环境变量读取在 .zshrc 文件下。 2、解决方案 1、切换终端到bash 切换终端到bash chsh -s /bin/bash 切换终端…...
【Cesium for Supermap】S3MTiles图层box裁剪
效果图: 代码: let viewer new Cesium.Viewer(cesiumContainer);// 添加SuperMap iServer发布的S3M缓存服务let promise viewer.scene.addS3MTilesLayerByScp("http://www.supermapol.com/realspace/services/3D-BIMbuilding/rest/realspace/data…...
PAT部分题目相关知识点——python
python中的整除 在Python中,整除(也称为地板除)可以使用**//**运算符来实现。当使用//运算符时,结果将是一个整数,它表示除法运算的整数部分,舍去任何小数部分。 示例: # 使用整除运算符 // …...
Redis核心数据结构之字典(二)
字典 解决键冲突 当有两个或以上数量的键被分配到了一个哈希表数组的同一个索引上面,我们称这些键发生了冲突(collision)。 Redis的哈希表使用链地址法(separate chaining)来解决键冲突,每个哈希表节点都有一个next指针,多个哈希表节点可以…...
拯救行动(BFS)
公主被恶人抓走,被关押在牢房的某个地方。牢房用 N \times M (N, M \le 200)NM(N,M≤200) 的矩阵来表示。矩阵中的每项可以代表道路()、墙壁(#)、和守卫(x)。 英勇的骑士(r…...
985硕的4家大厂实习与校招经历专题分享(part2)
我的个人经历: 985硕士24届毕业生,实验室方向:CV深度学习 就业:工程-java后端 关注大模型相关技术发展 校招offer: 阿里巴巴 字节跳动 等10 研究生期间独立发了一篇二区SCI 实习经历:字节 阿里 京东 B站 (只看大厂,面试…...
【NR技术】 3GPP支持无人机的关键技术以及场景
1 背景 人们对使用蜂窝连接来支持无人机系统(UAS)的兴趣浓厚,3GPP生态系统为UAS的运行提供了极好的好处。无处不在的覆盖范围、高可靠性和QoS、强大的安全性和无缝移动性是支持UAS指挥和控制功能的关键因素。与此同时,监管机构正在调查安全和性能标准以及…...
【译】WordPress Bricks主题安全漏洞曝光,25,000个安装受影响
WordPress的Bricks主题存在一个严重的安全漏洞,恶意威胁行为者正在积极利用该漏洞在易受攻击的安装上运行任意PHP代码。 该漏洞被跟踪为CVE-2024-25600(CVSS评分:9.8),使未经身份验证的攻击者能够实现远程代码执行。它…...
HTTP协议必知必会详解
系列文章目录 文章目录系列文章目录摘要一、开篇:你真的分得清 HTTP 和 HTML 吗?二、HTTP 的本质:浏览器与服务器的 "约定语言"三、一次完整的 HTTP 请求,到底经历了什么?四、拆解 HTTP 报文:请求…...
BitNet b1.58-2B-4T-GGUF快速上手:WebUI界面操作+System Prompt调优指南
BitNet b1.58-2B-4T-GGUF快速上手:WebUI界面操作System Prompt调优指南 1. 项目概述 BitNet b1.58-2B-4T-GGUF是一款革命性的开源大语言模型,采用原生1.58-bit量化技术,在保持高性能的同时大幅降低资源消耗。这个模型最特别的地方在于它的权…...
Qwen-Image-Edit多任务演示:换背景/加配饰/改光照/转风格/去水印五合一
Qwen-Image-Edit多任务演示:换背景/加配饰/改光照/转风格/去水印五合一 想象一下,你有一张满意的照片,但总觉得背景太杂乱;或者一张产品图,想换个风格试试效果;又或者一张带水印的素材,想把它干…...
手把手教你用OllyDbg(OD)修改程序内存数据(附快捷键大全)
逆向工程实战:用OllyDbg从零破解内存数据的终极指南 当你想了解一个程序内部运作机制,或者需要修复某个软件的小缺陷时,逆向工程工具就像一把打开黑盒子的钥匙。而OllyDbg(简称OD)无疑是Windows平台上最强大的调试器之…...
Canal - 数据同步
一、简介 1、介绍 Canal 是用 Java 开发的基于数据库增量日志解析,提供增量数据订阅&消费的中间件。 目前Canal 主要支持了MySQL的Binlog解析,解析完成后利用Canal Client来处理获得相关数据。(数据库同步需要阿里的Otter中间件…...
用 BAPI 打通 SAP Gateway OData 服务,经典 SEGW 路线一次讲透
在很多 SAP 项目里,我们手上早就有一批稳定跑了很多年的 BAPI。销售订单、客户主数据、物料、采购申请,这些对象背后的校验、过账、状态处理,往往已经沉淀在标准 BAPI 或企业自定义 RFC 里。业务前端一升级,Fiori、移动端、外部平台、低代码门户全都开始要 REST 风格接口,…...
Meta烧Token成KPI,OpenClaw引发AI成本结构重塑:不拼算力拼效率
Meta内部烧Token成风近日,据The Information报道,Meta公司内部出现了名为“Claudeonomics”(源自Anthropic旗舰产品Claude)的AI token消费排行榜,由员工自愿在公司内网创建,追踪超8.5万名员工的token使用情…...
你当问卷调查是什么?不是在“发传单”!好写作AI教你设计出能发顶刊的学术问卷
很多人把问卷设计当成一件“谁都会”的事:列几个问题,发出去,回收数据,分析收工。 如果你也是这么想的,那么恭喜你,你已经成功加入了“问卷翻车俱乐部”。 据学者对我国近六年教育类核心期刊发表的113篇问…...
【Dify 2026插件开发权威指南】:零基础到生产级自定义插件的7大核心实践与避坑清单
第一章:Dify 2026插件生态全景与开发范式演进Dify 2026标志着插件架构从“能力扩展”迈向“智能协同”的关键跃迁。其插件生态不再局限于API代理或简单工具封装,而是以统一的语义契约(Semantic Contract)为基础,支持跨…...
算一笔账:招剪辑师VS用易元AI,一年的成本差距有多大?
电商短视频成本,正在成为压在商家头上的一座隐形大山。在当前环境下,AI省人工成本已经不再是“锦上添花”,而是影响利润结构的关键变量。越来越多团队开始重新审视一个问题:继续招剪辑师,还是用AI替代? 当内…...
