这可能是全网关于Camera慢动作录像(SlowMotion)介绍最全的文章了

这是一篇关于慢动作录像(slowmotion)的文章,看完后相信你对慢动作录像不会再感到陌生了~

这篇文章针对下面几点来展开:
1)写这篇文章的原由?
2)什么是慢动作录像(SlowMotionRecord)?
3)Android上如何实现慢动作录像?
4)调试demo下载地址?
5)调试遇到的问题及解决?

一、写这篇文章的原由?

2月份的时候,在一个音视频开发的学习交流群里,有位网友问到**“Android相机有啥设置可以做到slow motion?”**,我认真的想了下,然后又简单看了下高通的晓龙相机源码,大概知道是怎么实现后,给了下思路。

后面我还一直在想这个事情,觉的自己给的思路太简单了,有时间还是得再研究研究,自己得敲下代码跑通下才好,于是就有了这篇文章。
image.png

二、什么是慢动作录像(SlowMotionRecord)?

通常我们人眼能够接受的最好的视频帧速率是24帧/每秒左右。那如果我们用120帧/秒拍摄一个动作,再用24帧每秒来播放的话,视频就放慢了5倍,这个就是慢动作录像了。

慢动作录像,又叫高帧率录像(HFR),也就是以高fps(运行速率)捕获、编码并保存为30 fps(目标速率),这种情况运行速率大于目标速率。

还有一种模式叫做高速录制(HSR) : 即以高fps(运行速率)捕获、编码并保存为高 fps(目标速率),运行速率等于目标速率。

这篇文章只介绍慢动作录像。(调试环境基于高通晓龙865芯片 Android9.0)

三、Android上如何实现视频慢动作?

有了上面关于慢动作的概念后,那在Android上如何用代码来实现呢?说到录像,那我们应该要想到MediaRecorder了。慢动作,也就是高帧率录像,那肯定得调用mediaRecorder设置高帧率了。

好了,我们还得再有一个概念,数据是从摄像头sensor出来的,那我们需要120fps,总得摄像头支持才行吧。所以呢,就有一个先决条件了,硬件得支持才行,下面会讲如何查询当前硬件是否支持。

假设硬件支持的情况下,我们来看下软件上应用的调用情况。
1、新类CameraConstrainedHighSpeedCaptureSession
查看Android的开发文档,我们可以看到,从Android 6.0开始,Camera相关的,添加了一个新的类CameraConstrainedHighSpeedCaptureSession,从描述上看,我们就可以知道,这个是专门为高速、高帧率录像准备的。换一句话说,也就是Android 6.0以上,Android本身才支持这个高速、高帧率录像。(我在自己早年用的nubiya手机上看了下,Android 5.1的系统,系统相机也带了慢动作功能,不过它这个慢动作应该是厂家自己定制开发的,那会Android还没提供相关接口)
https://developer.android.google.cn/reference/android/hardware/camera2/package-summary.html

2、查询当前硬件是否支持高帧率录像
通过CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS来获取available size。如果存在available,则判断为支持。

 public static boolean hasHighSpeedVideoConfigs(Context context, String cameraId) {
        try {
            CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
            HighSpeedVideoConfiguration[] highSpeedVideoConfigs = characteristics.get(
                    CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
            return highSpeedVideoConfigs != null && highSpeedVideoConfigs.length > 0;
        } catch (Exception e) {
     
        }
        return false;
    }

3、获取支持的高帧率录像videoSize
从map.getHighSpeedVideoSizes()中获取支持的videoSize,然后选择个合适的size,注意这里的previewSize需要和videoSize保持一致。

  CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap map = characteristics
                    .get(SCALER_STREAM_CONFIGURATION_MAP);

  mVideoSize = chooseVideoSize(map.getHighSpeedVideoSizes());
  mPreviewSize = mVideoSize;//这里需要保持previewSize 和videoSize一致

4、CONTROL_AE_TARGET_FPS_RANGE设置为高帧率范围(120,120)

   Range aeFps = new Range(120, 120);
   mPreviewBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, aeFps);

5、创建session采用createConstrainedHighSpeedCaptureSession
高帧率录像创建session,使用专门提供的api接口。

 // Start a capture session
   mCameraDevice.createConstrainedHighSpeedCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
      @Override
      public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
         ......
      }

     @Override
     public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
          ......
     }
   }, mBackgroundHandler);

6、采用setRepeatingBurst
session configure成功后,调用setRepeatingBurst不停的request,这个和正常模式有点区别,正常模式是调用的setRepeatingRequest。

   CaptureRequest request = mPreviewBuilder.build();
   List<CaptureRequest> slowMoRequests = ((CameraConstrainedHighSpeedCaptureSession) mPreviewSession)
                       .createHighSpeedRequestList(request);

    mPreviewSession.setRepeatingBurst(slowMoRequests, null,
                     mBackgroundHandler);

7、MediaRecorder相关参数设置为对应的高帧率参数
相对应的,mediaRecorder的一些参数也需要设置为高帧率参数。

    mProfile = getProfile();
    int bitRate = getHighSpeedVideoEncoderBitRate(mProfile, 
    mProfile.videoFrameRate,
               VEDIO_HIGH_SPEED_FRAME_RATE);

    mMediaRecorder.setVideoEncodingBitRate(bitRate);
    mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);
    mMediaRecorder.setCaptureRate(VEDIO_HIGH_SPEED_FRAME_RATE);

五、调试遇到的问题及解决方法

》》》》问题1:

Process: com.xcbj.camera, PID: 21818
   java.lang.IllegalArgumentException: Surface size 1440x1080 is not part of the high speed supported size list [1280x720, 720x480, 640x480, 1920x1080]
       at android.hardware.camera2.utils.SurfaceUtils.checkConstrainedHighSpeedSurfaces(SurfaceUtils.java:193)
       at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureSessionInternal(CameraDeviceImpl.java:881)
       at android.hardware.camera2.impl.CameraDeviceImpl.createConstrainedHighSpeedCaptureSession(CameraDeviceImpl.java:627)

[分析]

》》》》问题2: Fps rang[30,30] in the request is not a supported hight speed fps range…

 Process: com.xcbj.camera, PID: 27138
   java.lang.IllegalArgumentException: Fps range [30, 30] in the request is not a supported 
high speed fps range [[120, 120], [240, 240], [480, 480], [30, 120], [30, 240], [30, 480]]
       at android.hardware.camera2.utils.SurfaceUtils.checkConstrainedHighSpeedSurfaces(SurfaceUtils.java:180)
       at android.hardware.camera2.impl.CameraConstrainedHighSpeedCaptureSessionImpl.createHighSpeedRequestList(CameraConstrainedHighSpeedCaptureSessionImpl.java:89)

[分析]


*本人从事Android Camera相关开发已有5年,
*目前在深圳上班,
*小伙伴记得点我头像,看【个人介绍】进行关注哦,希望和更多的小伙伴一起交流 ~
在这里插入图片描述

-------- 2021.03.25 深圳 00:53·

**

欢迎关注我的个人博客:http://www.xiaochibiji.com

**

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Android Camera2 API 支持高速捕捉会话,可以在支持的设备上实现高帧率预览和录像。但是,要使用高速捕捉会话,您需要满足以下条件: 1. 设备支持高速捕捉会话。您可以使用 CameraCharacteristics 来检查支持的高速捕捉模式。 2. 您需要创建一个支持高速捕捉会话的 CaptureRequest。这个请求需要设置 HighSpeedRequestBuilder 的参数,包括预览和录像的帧率、分辨率、格式等。 3. 您需要创建一个支持高速捕捉会话的 CaptureSession。这个会话需要设置 HighSpeedCaptureSession 的参数,包括预览和录像的 Surface,以及捕捉的回调。 下面是一个简单的代码示例,展示如何使用高速捕捉会话实现高帧率预览和录像: ``` // 创建一个支持高速捕捉会话的 CaptureRequest CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); builder.addTarget(surface); builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range<Integer>(30, 60)); // 创建一个支持高速捕捉会话的 CaptureSession List<Surface> outputs = Arrays.asList(surface, recordingSurface); cameraDevice.createConstrainedHighSpeedCaptureSession(outputs, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { try { CaptureRequest request = builder.build(); session.setRepeatingBurst(Arrays.asList(request), null, null); session.setRepeatingBurst(Arrays.asList(request), null, null); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { Log.e(TAG, "Failed to configure camera"); } }, handler); ``` 在这个示例中,我们创建了一个支持高速捕捉会话的 CaptureRequest,并设置了预览和录像的帧率为 30 到 60 帧。然后,我们创建了一个支持高速捕捉会话的 CaptureSession,将预览和录像的 Surface 添加到会话中,并设置了捕捉的回调。最后,我们使用 setRepeatingBurst 方法开始捕捉预览和录像帧。 需要注意的是,高速捕捉会话需要较高的硬件性能和更长的处理时间,因此可能会影响电池寿命和设备温度。在使用高速捕捉会话时,请确保您的应用程序仅在必要时使用它,并在不需要时及时关闭会话。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小驰行动派

谢谢老板,今晚吃鸡~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值