简体   繁体   English

带有自定义表面的 Android CameraX

[英]Android CameraX with custom surface

In my app I am using CameraX for screen recording.在我的应用程序中,我使用 CameraX 进行屏幕录制。 I am trying to save not just camera output, but also GUI layout presented over camera surface.我不仅要保存相机输出,还要保存在相机表面呈现的 GUI 布局。

I am executing some basic animations on GUI layer( showing or hiding layouts and progress bar animations).我正在 GUI 层上执行一些基本动画(显示或隐藏布局和进度条动画)。

在此处输入图片说明

According to my knowledge, VideoCapture is capturing camera surface.据我所知,VideoCapture 正在捕捉相机表面。 So if I create custom surface for Camera, it should be possible to capture video with GUI layout.因此,如果我为相机创建自定义表面,则应该可以使用 GUI 布局捕获视频。

How to set custom surface to CameraX?如何将自定义表面设置为 CameraX? I was thinking about creating custom view(surface) from PreviewView but it is not possible.我正在考虑从 PreviewView 创建自定义视图(表面),但这是不可能的。 (PrevieView is final class) Is it possible to create custom surface provider? (PrevieView 是最后一类)是否可以创建自定义表面提供程序? How?如何?

PreviewView预览视图

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

Start of camera相机开始

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()))
    }

As far as I know It is not possible to record video with an overlay in CameraX.据我所知,不可能在 CameraX 中录制带有叠加层的视频。
That's why many people use some other libs to record videos with overlay like ffmpeg.这就是为什么许多人使用其他一些库来录制像 ffmpeg 这样的叠加视频。 Luckily you can use MediaCodec on Android.幸运的是,您可以在 Android 上使用 MediaCodec。

I believe the examples here at Grafika repository by Google would be very helpful for your case.我相信 Google Grafika存储库中的示例对您的案例非常有帮助。 Especially, Show + Capture Camera Activity in the readme part.特别是自述部分中的 Show + Capture Camera Activity。

Unfortunately if you want to provide a custom surface you need to give up on PreviewView.不幸的是,如果您想提供自定义表面,则需要放弃 PreviewView。

The way to do it is by creating a custom Preview.SurfaceProvider implementation and feed that provider, you will then have to provide the surface yourself as per the interface contract, for example providing a basic surface from a SurfaceHolder looks like this:这样做的方法是通过创建自定义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
    }
}

Then you can build your custom surface provider and use it with the Preview use case as you already do.然后,您可以构建您的自定义表面提供程序并将其与预览用例一起使用,就像您已经做的那样。

preview.setSurfaceProvider(
            yourCustomSurfaceProvider)

As a bonus, there is MediaProjection API which records anything happening on the device screen, unfortunately it's min API 21 and has to be started through an intent.作为奖励, MediaProjection API 可以记录设备屏幕上发生的任何事情,不幸的是它是最小 API 21,必须通过意图启动。

Good luck.祝你好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM