当前位置:   article > 正文

鸿蒙HarmonyOS开发实战—多媒体开发(相机开发 二)_鸿蒙开发录制视频

鸿蒙开发录制视频
相机帧捕获

Camera操作类,包括相机预览、录像、拍照等功能接口。

接口名

描述

triggerSingleCapture​(FrameConfig frameConfig)

启动相机帧的单帧捕获。

triggerMultiCapture​(List<FrameConfig> frameConfigs)

启动相机帧的多帧捕获。

configure​(CameraConfig config)

配置相机。

flushCaptures​()

停止并清除相机帧的捕获,包括循环帧/单帧/多帧捕获。

getCameraConfigBuilder​()

获取相机配置构造器对象。

getCameraId​()

获取当前相机的ID。

getFrameConfigBuilder​(int type)

获取指定类型的相机帧配置构造器对象。

release​()

释放相机对象及资源。

triggerLoopingCapture​(FrameConfig frameConfig)

启动或者更新相机帧的循环捕获。

stopLoopingCapture​()

停止当前相机帧的循环捕获。

启动预览(循环帧捕获)

用户一般都是先看见预览画面才执行拍照或者其他功能,所以对于一个普通的相机应用,预览是必不可少的。启动预览的建议步骤如下:

1. 通过getFrameConfigBuilder(FRAME_CONFIG_PREVIEW)方法获取预览配置模板,常用帧配置项见下表,更多的帧配置项以及详细使用方法请参考API接口说明的FrameConfig.Builder部分。

接口名

描述

是否必选

addSurface(Surface surface)

配置预览surface和帧的绑定。

setAfMode(int afMode, Rect rect)

配置对焦模式。

setAeMode(int aeMode, Rect rect)

配置曝光模式。

setZoom(float value)

配置变焦值。

setFlashMode(int flashMode)

配置闪光灯模式。

setFaceDetection(int type, boolean isEnable)

配置人脸检测或者笑脸检测。

setParameter(Key<T> key, T value)

配置其他属性(如自拍镜像等)。

setMark(Object mark)

配置一个标签,后续可以从FrameConfig中通过Object getMark()拿到标签,判断两个是否相等,相等就说明是同一个配置。

setCoordinateSurface(Surface surface)

配置坐标系基准Surface,后续计算Ae/Af等区域都会基于此Surface为基本的中心坐标系,不设置默认使用添加的第一个Surface。

2. 通过triggerLoopingCapture(FrameConfig)方法实现循环帧捕获(如预览/录像)。

  1. private final class CameraStateCallbackImpl extends CameraStateCallback {
  2. @Override
  3. public void onConfigured(Camera camera) {
  4. // 获取预览配置模板
  5. frameConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
  6. // 配置预览Surface
  7. frameConfigBuilder.addSurface(previewSurface);
  8. previewFrameConfig = frameConfigBuilder.build();
  9. try {
  10. // 启动循环帧捕获
  11. int triggerId = camera.triggerLoopingCapture(previewFrameConfig);
  12. } catch (IllegalArgumentException e) {
  13. HiLog.error(LABEL, "Argument Exception");
  14. } catch (IllegalStateException e) {
  15. HiLog.error(LABEL, "State Exception");
  16. }
  17. }
  18. }

复制

经过以上的操作,相机应用已经可以正常进行实时预览了。在预览状态下,开发者还可以执行其他操作,比如:

当预览帧配置更改时,可以通过triggerLoopingCapture(FrameConfig)方法实现预览帧配置的更新;

  1. // 预览帧变焦值变更
  2. frameConfigBuilder.setZoom(1.2f);
  3. // 调用triggerLoopingCapture方法实现预览帧配置更新
  4. triggerLoopingCapture(frameConfigBuilder.build());

复制

通过stopLoopingCapture()方法停止循环帧捕获(停止预览)。

  1. // 停止预览帧捕获
  2. camera.stopLoopingCapture()

复制

实现拍照(单帧捕获)

拍照功能属于相机应用的最重要功能之一,而且照片质量对用户至关重要。相机模块基于相机复杂的逻辑,从应用接口层到器件驱动层都已经默认的做好了最适合用户的配置,这些默认配置尽可能地保证用户拍出的每张照片的质量。发起拍照的建议步骤如下:

1. 通过getFrameConfigBuilder(FRAME_CONFIG_PICTURE)方法获取拍照配置模板,并且设置拍照帧配置,如下表

接口名

描述

是否必选

FrameConfig.Builder addSurface(Surface)

实现拍照Surface和帧的绑定。

必选

FrameConfig.Builder setImageRotation(int)

设置图片旋转角度。

可选

FrameConfig.Builder setLocation(Location)

设置图片地理位置信息。

可选

FrameConfig.Builder setParameter(Key<T>, T)

配置其他属性(如自拍镜像等)。

可选

2. 拍照前准备图像帧数据的接收实现

  1. // 图像帧数据接收处理对象
  2. private ImageReceiver imageReceiver;
  3. // 执行回调的EventHandler
  4. private EventHandler eventHandler = new EventHandler(EventRunner.create("CameraCb"));
  5. // 拍照支持分辨率
  6. private Size pictureSize;
  7. // 单帧捕获生成图像回调Listener
  8. private final ImageReceiver.IImageArrivalListener imageArrivalListener = new ImageReceiver.IImageArrivalListener() {
  9. @Override
  10. public void onImageArrival(ImageReceiver imageReceiver) {
  11. StringBuffer fileName = new StringBuffer("picture_");
  12. fileName.append(UUID.randomUUID()).append(".jpg"); // 定义生成图片文件名
  13. File myFile = new File(dirFile, fileName.toString()); // 创建图片文件
  14. imageSaver = new ImageSaver(imageReceiver.readNextImage(), myFile); // 创建一个读写线程任务用于保存图片
  15. eventHandler.postTask(imageSaver); // 执行读写线程任务生成图片
  16. }
  17. };
  18. // 保存图片, 图片数据读写,及图像生成见run方法
  19. class ImageSaver implements Runnable {
  20. private final Image myImage;
  21. private final File myFile;
  22. ImageSaver(Image image, File file) {
  23. myImage = image;
  24. myFile = file;
  25. }
  26. @Override
  27. public void run() {
  28. Image.Component component = myImage.getComponent(ImageFormat.ComponentType.JPEG);
  29. byte[] bytes = new byte[component.remaining()];
  30. component.read(bytes);
  31. FileOutputStream output = null;
  32. try {
  33. output = new FileOutputStream(myFile);
  34. output.write(bytes); // 写图像数据
  35. } catch (IOException e) {
  36. HiLog.error(LABEL, "save picture occur exception!");
  37. } finally {
  38. if (output != null) {
  39. try {
  40. output.close(); // 关闭流
  41. } catch (IOException e) {
  42. HiLog.error(LABEL, "image release occur exception!");
  43. }
  44. }
  45. myImage.release();
  46. }
  47. }
  48. }
  49. private void takePictureInit() {
  50. List<Size> pictureSizes = cameraAbility.getSupportedSizes(ImageFormat.JPEG); // 获取拍照支持分辨率列表
  51. pictureSize = getPictureSize(pictureSizes) // 根据拍照要求选择合适的分辨率
  52. imageReceiver = ImageReceiver.create(Math.max(pictureSize.width, pictureSize.height),
  53. Math.min(pictureSize.width, pictureSize.height), ImageFormat.JPEG, 5); // 创建ImageReceiver对象,注意create函数中宽度要大于高度;5为最大支持的图像数,请根据实际设置。
  54. imageReceiver.setImageArrivalListener(imageArrivalListener);
  55. }

复制

3. 通过triggerSingleCapture(FrameConfig)方法实现单帧捕获(如拍照)。

  1. private void capture() {
  2. // 获取拍照配置模板
  3. framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);
  4. // 配置拍照Surface
  5. framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
  6. // 配置拍照其他参数
  7. framePictureConfigBuilder.setImageRotation(90);
  8. try {
  9. // 启动单帧捕获(拍照)
  10. cameraDevice.triggerSingleCapture(framePictureConfigBuilder.build());
  11. } catch (IllegalArgumentException e) {
  12. HiLog.error(LABEL, "Argument Exception");
  13. } catch (IllegalStateException e) {
  14. HiLog.error(LABEL, "State Exception");
  15. }
  16. }

复制

为了捕获到质量更高和效果更好的图片,还可以在帧结果中实时监测自动对焦和自动曝光的状态,一般而言,在自动对焦完成,自动曝光收敛后的瞬间是发起单帧捕获的最佳时机。

实现连拍(多帧捕获)

连拍功能方便用户一次拍照获取多张照片,用于捕捉精彩瞬间。同普通拍照的实现流程一致,但连拍需要使用triggerMultiCapture(List<FrameConfig> frameConfigs)方法。

启动录像(循环帧捕获)

启动录像和启动预览类似,但需要另外配置录像Surface才能使用。

1. 录像前需要进行音视频模块的配置。

  1. private Source source; // 音视频源
  2. private AudioProperty.Builder audioPropertyBuilder; // 音频属性构造器
  3. private VideoProperty.Builder videoPropertyBuilder; // 视频属性构造器
  4. private StorageProperty.Builder storagePropertyBuilder; // 音视频存储属性构造器
  5. private Recorder mediaRecorder; // 录像操作对象
  6. private String recordName; // 音视频文件名
  7. private Size mRecordSize; // 录像分辨率
  8. private void initMediaRecorder() {
  9. videoPropertyBuilder.setRecorderBitRate(10000000); // 设置录制比特率
  10. int rotation = DisplayManager.getInstance().getDefaultDisplay(this).get().getRotation();
  11. videoPropertyBuilder.setRecorderDegrees(getOrientation(rotation)); // 设置录像方向
  12. videoPropertyBuilder.setRecorderFps(30); // 设置录制采样率
  13. videoPropertyBuilder.setRecorderHeight(Math.min(recordSize.height, recordSize.width)); // 设置录像支持的分辨率,需保证width > height
  14. videoPropertyBuilder.setRecorderWidth(Math.max(recordSize.height, recordSize.width));
  15. videoPropertyBuilder.setRecorderVideoEncoder(Recorder.VideoEncoder.H264); // 设置视频编码方式
  16. videoPropertyBuilder.setRecorderRate(30); // 设置录制帧率
  17. source.setRecorderAudioSource(Recorder.AudioSource.MIC); // 设置录制音频源
  18. source.setRecorderVideoSource(Recorder.VideoSource.SURFACE); // 设置视频窗口
  19. mediaRecorder.setSource(source); // 设置音视频源
  20. mediaRecorder.setOutputFormat(Recorder.OutputFormat.MPEG_4); // 设置音视频输出格式
  21. StringBuffer fileName = new StringBuffer("record_"); // 生成随机文件名
  22. fileName.append(UUID.randomUUID()).append(".mp4");
  23. recordName = fileName.toString();
  24. File file = new File(dirFile, recordName); // 创建录像文件对象
  25. storagePropertyBuilder.setRecorderFile(file); // 设置存储音视频文件名
  26. mediaRecorder.setStorageProperty(storagePropertyBuilder.build());
  27. audioPropertyBuilder.setRecorderAudioEncoder(Recorder.AudioEncoder.AAC); // 设置音频编码格式
  28. mediaRecorder.setAudioProperty(audioPropertyBuilder.build()); // 设置音频属性
  29. mediaRecorder.setVideoProperty(videoPropertyBuilder.build()); // 设置视频属性
  30. mediaRecorder.prepare(); // 准备录制
  31. HiLog.info(LABEL, "initMediaRecorder end");
  32. }

复制

2. 配置录像帧,启动录像

  1. private final class CameraStateCallbackImpl extends CameraStateCallback {
  2. @Override
  3. public void onConfigured(Camera camera) {
  4. // 获取录像配置模板
  5. frameConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_RECORD);
  6. // 配置预览Surface
  7. frameConfigBuilder.addSurface(previewSurface);
  8. // 配置录像的Surface
  9. mRecorderSurface = mediaRecorder.getVideoSurface();
  10. frameConfigBuilder.addSurface(mRecorderSurface);
  11. previewFrameConfig = frameConfigBuilder.build();
  12. try {
  13. // 启动循环帧捕获
  14. int triggerId = camera.triggerLoopingCapture(previewFrameConfig);
  15. } catch (IllegalArgumentException e) {
  16. HiLog.error(LABEL, "Argument Exception");
  17. } catch (IllegalStateException e) {
  18. HiLog.error(LABEL, "State Exception");
  19. }
  20. }
  21. }

复制

相机设备释放

使用完相机后,必须通过release()来关闭相机和释放资源,否则可能导致其他相机应用无法启动。一旦相机被释放,它所提供的操作就不能再被调用,否则会导致不可预期的结果,或是会引发状态异常。

相机设备释放的示例代码如下:

  1. private void releaseCamera() {
  2. if (camera != null) {
  3. // 关闭相机和释放资源
  4. camera.release();
  5. camera = null;
  6. }
  7. // 拍照配置模板置空
  8. framePictureConfigBuilder = null;
  9. // 预览配置模板置空
  10. previewFrameConfig = null;
  11. }

最后,为了能让大家更好的去学习提升鸿蒙 (Harmony OS) 开发技术,小编连夜整理了一份30个G纯血版学习资料(含视频电子书学习文档等)以及一份在Github上持续爆火霸榜的《纯血版华为鸿蒙 (Harmony OS)开发手册》(共计890页),希望对大家有所帮助。

纯血版鸿蒙 HarmonyOS 4.0 视频学习资料

 需要以上视频学习资料小伙伴

请点击→纯血版全套鸿蒙HarmonyOS学习资料


《纯血版华为鸿蒙 (Harmony OS)开发手册》

这份手册涵盖了当前鸿蒙 (Harmony OS) 开发技术必掌握的核心知识点

纯血版鸿蒙 (Harmony OS)开发手册部分精彩内容

HarmonyOS 概念:

  • 系统定义
  • 技术架构
  • 技术特性
  • 系统安全

如何快速入门?

  • 基本概念
  • 构建第一个ArkTS应用
  • 构建第一个JS应用
  • ……


开发基础知识: 

  • 应用基础知识
  • 配置文件
  • 应用数据管理
  • 应用安全管理
  • 应用隐私保护
  • 三方应用调用管控机制
  • 资源分类与访问
  • 学习ArkTS语言
  • ……

基于ArkTS 开发:

  • Ability开发
  • UI开发
  • 公共事件与通知
  • 窗口管理
  • 媒体
  • 安全
  • 网络与链接
  • 电话服务
  • 数据管理
  • 后台任务(Background Task)管理
  • 设备管理
  • 设备使用信息统计
  • DFX
  • 国际化开发
  • 折叠屏系列
  • .……

获取以上文中提到的这份纯血版鸿蒙 (Harmony OS) 开发资料的小伙伴 

请点击→纯血版全套鸿蒙HarmonyOS学习资料


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/234623

推荐阅读
相关标签