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

这是一篇关于慢动作录像(slowmotion)的文章,看完后相信你对慢动作录像不会再感到陌生了,而且下一次如果老板要你实现慢动作录像的功能,应该也是信心慢慢的了~
这篇文章针对下面几点来展开:
1)写这篇文章的原由?
2)什么是慢动作录像(SlowMotionRecord)?
3)Android上如何实现慢动作录像?
4)调试demo下载地址?
5)调试遇到的问题及解决?
这篇文章是基于高通平台调试,在Android11上验证功能正常。如果您实际调试遇到什么问题,请以实际情况为准。现在国产的手机,很大会在系统层做了一些定制化差异,所有不同的手机品牌的手机,实际情况可能都会不一样。
一、写这篇文章的原由?
关于录像慢动作,我之前只是有自己大概的实现思路,不过并没有在机器上实际调试过。没有写demo调试,很大一部分的原因事,最近公司的事情比较多,忙的不行,实在是没有多余的时间来写demo。毕竟demo的调试还是很花时间的。
后面在一个微信交流群,有同学问到了慢动作录像的问题,想着是要花点事情去看下慢动作相关的内容了。
我一直接触的是高通平台,所有,所有demo的调试都是在高通平台上调试。其它平台我暂时也没有接触到,其它平台应该还是会有点差异的。具体情况,以自己遇到的问题分析为准。
2月份的时候,在一个音视频开发的学习交流群里,有位网友问到"Android相机有啥设置可以做到slow motion?",我认真的想了下,然后又简单看了下高通的晓龙相机源码,大概知道是怎么实现后,给了下思路。
后面我还一直在想这个事情,觉的自己给的思路太简单了,有时间还是得再研究研究,自己得敲下代码跑通下才好,于是就有了这篇文章。

二、什么是慢动作录像(SlowMotionRecord)?
通常我们人眼能够接受的最好的视频帧速率是24帧/每秒左右。那如果我们用120帧/秒拍摄一个动作,再用24帧每秒来播放的话,视频就放慢了5倍,这个就是慢动作录像了。
慢动作录像,又叫高帧率录像(HFR),也就是以高fps(运行速率)捕获、编码并保存为30 fps(目标速率),这种情况运行速率大于目标速率。
(
这篇文章只介绍慢动作录像。
三、Android上如何实现视频慢动作?
有了上面关于慢动作的概念后,那在Android上如何用代码来实现呢?说到录像,那我们应该要想到MediaRecorder了。慢动作,也就是高帧率录像,那肯定得调用mediaRecorder设置高帧率了。
好了,我们还得再有一个概念,数据是从摄像头sensor出来的,那我们需要120fps,总得摄像头支持才行吧。所以呢,就有一个先决条件了,硬件得支持才行,下面会讲如何查询当前硬件是否支持。
假设硬件支持的情况下,我们来看下软件上应用的调用情况。
1、新类CameraConstrainedHighSpeedCaptureSession
查看Android的开发文档,我们可以看到,从Android 6.0开始,Camera相关的,添加了一个新的类CameraConstrainedHighSpeedCaptureSession,从描述上看,我们就可以知道,这个是专门为高速、高帧率录像准备的。换一句话说,也就是Android 6.0以上,Android本身才支持这个高速、高帧率录像。

2、查询当前硬件是否支持高帧率录像
通过CONTROL
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(SCALERSTREAMCONFIGURATION_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.CONTROLAETARGETFPSRANGE, 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 slowMoRequests = ((CameraConstrainedHighSpeedCaptureSession) mPreviewSession)
.createHighSpeedRequestList(request);
mPreviewSession.setRepeatingBurst(slowMoRequests, null,
mBackgroundHandler);
7、MediaRecorder相关参数设置为对应的高帧率参数
相对应的,mediaRecorder的一些参数也需要设置为高帧率参数。
mProfile = getProfile();
int bitRate = getHighSpeedVideoEncoderBitRate(mProfile,
mProfile.videoFrameRate,
VEDIOHIGHSPEEDFRAMERATE);
mMediaRecorder.setVideoEncodingBitRate(bitRate);
mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);
mMediaRecorder.setCaptureRate(VEDIOHIGHSPEEDFRAMERATE);
四、调试Demo 下载地址
本来想着上传到github的,奈何github不给力,访问不了。先上传到百度网盘先,需要的可以自行下载参考。(关注"小驰笔记",回复"慢动作录像"即可获取代码下载地址)

五、调试遇到的问题及解决方法
调试的过程,其实并没有那么的顺利,总会遇到一些问题,这里总结下,如果你也遇到,希望对各位能有所帮忙,同时也方面自己后面查看。
》》》》问题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)
[分析]

----------------------------------
*
*
*
*

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