具有自定义表面的 Android CameraX

Posted

技术标签:

【中文标题】具有自定义表面的 Android CameraX【英文标题】:Android CameraX with custom surface 【发布时间】:2021-09-29 16:00:42 【问题描述】:

在我的应用中,我使用 CameraX 进行屏幕录制。 我不仅要保存相机输出,还要保存在相机表面上呈现的 GUI 布局。

我正在 GUI 层上执行一些基本动画(显示或隐藏布局和进度条动画)。

据我所知,VideoCapture 正在捕获相机表面。因此,如果我为相机创建自定义表面,应该可以使用 GUI 布局捕获视频。

如何将自定义表面设置为 CameraX? 我正在考虑从 PreviewView 创建自定义视图(表面),但这是不可能的。 (PrevieView 是最后一课) 是否可以创建自定义表面提供程序?怎么样?

预览视图

    <androidx.camera.view.PreviewView
        android:id="@+id/view_finder"
        android:layout_
        android:layout_ />
    ...

相机开始

private fun startCamera() 

        val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())

        cameraProviderFuture.addListener(Runnable 
            // Camera provider is now guaranteed to be available
            val cameraProvider = cameraProviderFuture.get()

            // Set up the preview use case to display camera preview.
            val preview = Preview.Builder().apply 
                setCameraSelector(CameraSelector.DEFAULT_FRONT_CAMERA)
            .build()

            // Set up the capture use case to allow users to take photos.
            videoCapture = VideoCapture.Builder().apply 
                setCameraSelector(CameraSelector.DEFAULT_FRONT_CAMERA)
            .build()

            // Choose the camera by requiring a lens facing
            val cameraSelector = CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
                .build()

            // Attach use cases to the camera with the same lifecycle owner
            val camera = cameraProvider.bindToLifecycle(
                customLifecycle as LifecycleOwner, cameraSelector, preview, videoCapture)

            // Connect the preview use case to the previewView
            preview.setSurfaceProvider(
                viewFinder.getSurfaceProvider())

        , ContextCompat.getMainExecutor(requireContext()))
    

【问题讨论】:

【参考方案1】:

据我所知,无法在 CameraX 中录制带有叠加层的视频。 这就是为什么许多人使用其他一些库来录制像 ffmpeg 这样的覆盖的视频。幸运的是,您可以在 Android 上使用 MediaCodec。

我相信 Google 提供的 Grafika 存储库中的示例对您的案例非常有帮助。特别是自述文件部分中的 Show + Capture Camera Activity。

【讨论】:

【参考方案2】:

不幸的是,如果您想提供自定义表面,您需要放弃 PreviewView。

这样做的方法是创建一个自定义的Preview.SurfaceProvider 实现并提供该提供程序,然后您必须根据接口合同自己提供表面,例如从 SurfaceHolder 提供一个基本表面,如下所示:

override fun onSurfaceRequested(request: SurfaceRequest) 
    surfaceHolder?.let 
        providedSurface = with(request.resolution) 
            it.setFixedSize(width, height).run  it.surface 
        
    

    request.provideSurface(providedSurface, executor)  result ->
        //TODO: explore the result of providing the surface
    

然后您可以构建您的自定义表面提供程序,并将其与您已经做的预览用例一起使用。

preview.setSurfaceProvider(
            yourCustomSurfaceProvider)

作为奖励,MediaProjection API 记录了设备屏幕上发生的任何事情,不幸的是它的最低 API 21 并且必须通过意图启动。

祝你好运。

【讨论】:

以上是关于具有自定义表面的 Android CameraX的主要内容,如果未能解决你的问题,请参考以下文章

如何在Android中制作自定义相机布局?

如何使用 Android CameraX ImageAnalysis 提高帧速率?

Android - 具有自定义属性的自定义 UI

android自定义相机拉伸surfaceview

如何在Android中自定义相机布局?

具有自定义视图的 ScrollView 不会滚动 - android?