CameraX 使用二

上一篇文章已经介绍了使用CameraX完成预览、拍照功能,和介绍了一些相关的API,今天主要在介绍使用CameraX录制和视频编码的。

视频录制

视频的录制 主要用到了 VideoCapture和Recording这两个类来完成。

  1. 获取到ProcessCameraProvider 对象;
  2. 创建 preview,设置宽高,并和显示的PreviewView绑定到一起;
  3. 创建一个Recoder,设置图片质量;
  4. 创建出 videoCapture 对象;
  5. 绑定 videoCapture;
kotlin 复制代码
private suspend fun bindCaptureUsecase() {
    val cameraProvider = ProcessCameraProvider.getInstance(this).await()
    // CameraSelector(相机选择器)是一种用于选择要使用的相机设备的类。CameraSelector 类提供了一种简便的方式来选择前置或后置摄像头,并根据应用程序需求进行配置。
    val cameraSelector = getCameraSelector(cameraIndex)
    // 获取图片质量选择器
    val quality = cameraCapabilities[cameraIndex].qualities[qualityIndex]
    val qualitySelector = QualitySelector.from(quality)
    // 给 previewView设置宽高比
    previewView.updateLayoutParams<ConstraintLayout.LayoutParams> {
        val orientation = [email protected]
        dimensionRatio = quality.getAspectRatioString(quality,
            (orientation == Configuration.ORIENTATION_PORTRAIT))
    }
    // 创建 preview,设置宽高,并和显示的PreviewView绑定到一起
    val preview = Preview.Builder()
        .setTargetAspectRatio(quality.getAspectRatio(quality))
        .build().apply {
            setSurfaceProvider(previewView.surfaceProvider)
        }
    // 创建一个Recoder
    val recorder = Recorder.Builder()
        .setQualitySelector(qualitySelector)
        .build()
    videoCapture = VideoCapture.withOutput(recorder)

    // 绑定 videoCapture,之后的录制就用videoCapture 完成了
    try {
        cameraProvider.unbindAll()

        cameraProvider.bindToLifecycle(
            this,
            cameraSelector,
            videoCapture,
            preview
        )
    } catch (exc: Exception) {
        
    }
  
}

这样就完成了绑定操作

scss 复制代码
private fun startRecording() {
    // 创建输出配置信息
    val name = "CameraX-recording-" +
            SimpleDateFormat(FILENAME_FORMAT, Locale.US)
                .format(System.currentTimeMillis()) + ".mp4"
    val contentValues = ContentValues().apply {
        put(MediaStore.Video.Media.DISPLAY_NAME, name)
    }
    // 创建好 MediaStoreOutputOptions 里面设置了存储的信息
    val mediaStoreOutput = MediaStoreOutputOptions.Builder(
       contentResolver,
        MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
        .setContentValues(contentValues)
        .build()
    
    currentRecording = videoCapture.output
        .prepareRecording(this, mediaStoreOutput)
        .apply { if (audioEnabled) withAudioEnabled() }
        .start(mainThreadExecutor, captureListener)

    Log.i(TAG, "Recording started")
}

得到一个Recording对象,后续的操作暂停、继续、停止操作都是通过Recording完成。 然后可以通过监听知道录制的状态

csharp 复制代码
private val captureListener = Consumer<VideoRecordEvent> { event ->
    
}

暂停录制:

scss 复制代码
currentRecording?.pause()

继续录制:

lua 复制代码
 currentRecording?.resume()

停止录制:

scss 复制代码
recording.stop()

这样录制就完成了,使用起来还是比较简单的。

视频编码

只要能实时拿到数据,然后输入到MediaCodec 就可以了。我们可以通过 imageAnalyzer 设置监听回调即可。 我们可以在拍照的项目基础上修改一下。

scss 复制代码
imageAnalyzer = ImageAnalysis.Builder()
            // 设定宽高比
//            .setTargetAspectRatio(screenAspectRatio)
            .setTargetResolution(Size(width, height))
            // 设置方向
            .setTargetRotation(rotation)
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .build()
            // 将分析器分配给实例
            .also {
                it.setAnalyzer(cameraExecutor) {
                    it.image?.let { image ->
                        //在回调里面进行编码
                        videoEncode.encode(image)
                        image.close()
                    }
                    it.close()
                }
            }

然后进行绑定:

ini 复制代码
camera = cameraProvider.bindToLifecycle(
    this, cameraSelector, preview, imageAnalyzer
)

这样就可以实时拿到image去做分析了,具体的编码和Camera2的一样,这里就不再赘述了

一些用到的API

VideoCapture

在 Android 中,VideoCapture 是一种用于录制视频的类,它是 CameraX 相机库中的一部分。

VideoCapture 类提供了一种简单且方便的方式来录制视频。可以使用 VideoCapture 类创建一个实例,并配置一些属性和参数来控制视频录制的行为。

以下是 VideoCapture 类的一些功能和常用方法:

  1. 开始和停止录制:使用 startRecording() 方法开始录制视频,并使用 stopRecording() 方法停止录制。这些方法会自动处理音频和视频数据的捕获、编码和保存。

  2. 设置输出文件:使用 setOutputFile() 方法设置保存录制视频的输出文件路径。

  3. 设置视频质量和参数:VideoCapture 支持设置视频帧率、分辨率、比特率等参数,以及选择前置或后置摄像头进行录制。

  4. 监听录制状态:可以注册一个 VideoCapture.OnVideoSavedCallback 回调接口,以监听录制完成的回调和错误处理。

  5. 自定义录制配置:VideoCapture 还支持其他一些配置选项,如设置录制时使用的摄像头、音频源、视频编码器等。

VideoCapture 通过封装底层的 CameraX 和 MediaRecorder 功能,为开发者提供了更简单的录制视频的接口。使用 VideoCapture 类,可以快速实现视频录制的功能,并根据需要进行定制和扩展。

QualitySelector

QualitySelector(图像质量选择器)并不是一个内置的类。可以通过使用相机 API 或图像处理库来实现图像质量的选择和控制。

使用相机 API 进行图像捕获,可以通过设置参数来控制图像的质量。以下是一些可用于控制图像质量的常见参数:

  1. 图像格式(Image Format):您可以选择不同的图像格式,如 JPEG、PNG 等。JPEG 是最常用的图像格式,可以通过设置图像质量参数来控制压缩比例和图像质量级别。

  2. 图像质量(Image Quality):对于 JPEG 格式的图像,您可以设置图像质量参数来控制压缩比例和图像清晰度。通常,图像质量值的范围为 0 到 100,其中 0 表示最低质量、最高压缩,而 100 表示最高质量、最低压缩。

  3. 图像分辨率(Image Resolution):您可以选择不同的图像分辨率来控制图像的细节水平和文件大小。较高的分辨率通常会产生更清晰的图像,但也会增加文件大小。

  4. 其他参数:还有其他一些参数,例如亮度、对比度、饱和度等,可以通过设置来影响图像的质量和效果。

如果您使用图像处理库(如 Glide、Picasso 等)来显示和处理图像,这些库通常提供了一些方法来控制图像的质量。您可以根据库的文档和示例代码来查找有关图像质量控制的具体方法和用法。

需要根据您的具体需求选择相应的方法和参数来控制图像的质量。请注意,图像质量的选择会影响文件大小、加载速度、显示效果等因素,因此需要在图像质量和性能之间进行权衡。

遇到的一些问题

  • imageAnalyzer 设置的分辨率和 MediaCodec 分辨率设置不一致,编码出来的视频 会是绿屏或是别的花屏,这里要特别注意。
  • 在一些时候,会在MediaCodec 的输入缓冲区会报错 BufferOverflowException,尝试找了原因,但都没有找到,试过设置 MediaFormat.KEY_MAX_INPUT_SIZE 和码率还是没有办法解决。但是我想着还是和分辨率有关,接下来拿 CameraX 支持的分辨率再试一试,看看是不是我设置的分辨率问题。

总结

  • 今天简单的介绍了CameraX 录制视频和编码,总体使用起来还是很简单的,都是通过 cameraProvider.bindToLifecycle 方法,只要往里面添加 对应的UseCase就可以;
  • 录制使用添加的 UseCase是VideoCapture;
  • 编码添加的是 UseCase 是ImageAnalysis;
  • 到这里用Camera 采集视频数据就简单的介绍完了,下面开始介绍音频的采集。
相关推荐
哔哩哔哩技术21 天前
2025 B站春晚直播——流媒体技术助力直播体验提升与玩法创新
音视频开发
hepherd21 天前
iOS - 音频: Core Audio - 播放
swift·音视频开发
音视频牛哥22 天前
跨越技术藩篱,低延迟RTMP与RTSP播放器的战略意义
音视频开发·视频编码·直播
音视频牛哥22 天前
流转时光,极致传输:大牛直播SDK跨平台RTMP播放模块的超低延迟之道
音视频开发·视频编码·直播
David凉宸22 天前
视频融合 hls流如何对接
前端·音视频开发
音视频牛哥22 天前
跨平台轻量级RTSP服务模块:一切源自一场小而美的坚持
音视频开发·视频编码·直播
音视频牛哥23 天前
跨平台RTSP播放器之快于心稳于骨,毫秒之间见真章
音视频开发·视频编码·直播
音视频牛哥23 天前
音视频行业的真相是:真正难的,是把一件事做到极致
音视频开发·视频编码·直播
音视频牛哥23 天前
[对话牛哥]技术不是炫技,是让世界听见你声音的开始
音视频开发·视频编码·直播