前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一篇文章带你了解Google CameraX

一篇文章带你了解Google CameraX

作者头像
小驰随想录
发布2022-09-22 11:38:45
3.2K0
发布2022-09-22 11:38:45
举报
文章被收录于专栏:Android Camera开发Android Camera开发

Camera、Camera2、CameraX?3者之间啥关系?

CameraX、CamX分不清?

今天我们就一起来学习、了解下这些内容,为大家解开迷惑。

这篇文章分下面几点展开:

1) CameraX初认识?

2) Google为啥要推出CameraX?

3) CameraX基本框架介绍;

4) CameraX的基本使用示例;

5) CameraX、Camx要分清;

一、CameraX初认识?

1) CameraX 是一个 Jetpack 库,最低版本是兼容到Android5.0。好学的同学们,肯定又会问,那Jetpack库又是啥呢?

好了,那我们先来扯下Android Jetpack又是个啥。

在 Jetpack 的官方文档中是这样对它定义的:

Jetpack 是一套组件库,可帮助开发人员遵循最佳实践,减少样板代码并编写可在 Android 版本和设备上一致工作的代码,以便开发人员可以专注于他们关心的代码。

上面其实就是2个核心点,第一:Jetpack是一套组件库,注意,是一套,一套那就表示包含很多不同的组件。第二:使用Jetpack,方便我们在不同的android设备和不同的android版本上的适配,简单说,就是适配性强。

下面列表,就是热门和常用的Jetpack库,我们可以看到Camera也在其中,这个Camera*就是我们今天要重点介绍的CameraX。

上面介绍了这么多,大家应该对cameraX应该有个最基础的了解了。CameraX是一个 Jetpack 库。

这个CameraX库呢,然后呢,这个库是针对相机领域的。

二、 Google为啥要推出CameraX?

关于这点,从前面Android Jetpack库的介绍里面,其实我们也基本可以知道原因了。这个库是为了方便我们在各个Android版本和Android设备直接的适配和兼容。

官方的介绍是这样的:

CameraX 是 Jetpack 的新增库。利用该库,可以更轻松地向应用添加相机功能。该库提供了很多兼容性修复程序和解决方法,有助于在众多设备上打造一致的开发者体验。

主要优势表现为以下几点:

1)广泛的设备兼容性

CameraX 支持搭载 Android 5.0(API 级别 21)或更高版本的设备,覆盖现有 Android 设备的 98% 以上。

2)易用性

CameraX 着重于用例,使您可以专注于需要完成的任务,而无需花时间处理不同设备之间的细微差别。CameraX 支持大多数常见的相机用例:

  • 预览:在屏幕上查看图片。
  • 图片分析:无缝访问缓冲区中的图片以便在算法中使用,例如将其传递到机器学习套件。
  • 图片拍摄:保存图片。
  • 视频拍摄:保存视频和音频。

3)确保各设备间的一致性

要维持一致的相机行为并非易事。您必须考虑宽高比、屏幕方向、旋转角度、预览大小和图像大小。有了 CameraX,这些基本行为都不用您再费心。

我们设立了一个自动化 CameraX 测试实验室,用于测试搭载了 Android 5.0 及更高版本的一系列设备和这些操作系统版本中的各种相机行为。我们将持续运行这些测试,以找出各种各样的问题并进行修复。

4)新体验

CameraX 有一个可选的 Extensions API,您只需两行代码,便可借助该 API 实现与设备的原生相机应用相同的特性和功能。

扩展程序包含焦外成像(人像)、高动态范围 (HDR)、夜间模式和脸部照片修复功能,所有这些都需要设备支持。

三、 CameraX基本框架介绍

从下图我们可以看到,CameraX是基于Camera2的API进行的封装。

Camera API1,Google已经声明在Android5.0之后的设备上废弃了。所以,CameraX所能支持的功能,也就是Camera2所支持的功能。

目前CameraX为我们提供下下面几个最主要的功能,分别是预览、图片分析、图片拍摄、视频拍摄等。这些都是相机开发里面常用的功能。

四、 CameraX的基本使用示例

1)实现预览

在向应用添加预览时,请使用 PreviewView,这是一种可以剪裁、缩放和旋转以确保正确显示的 View

当相机处于活动状态时,图片预览会流式传输到 PreviewView 中的 Surface。

使用 PreviewView

如需使用 PreviewView 实现 CameraX 预览,请按以下步骤操作(稍后将对这些步骤进行说明):

  1. (可选)配置 CameraXConfig.Provider
  2. PreviewView 添加到布局。
  3. 请求 ProcessCameraProvider
  4. 在创建 View 时,请检查 ProcessCameraProvider
  5. 选择相机并绑定生命周期和用例。

使用 PreviewView 存在一些限制。使用 PreviewView 时,您无法执行以下任何操作:

  • 创建 SurfaceTexture,以在 TextureViewPreview.SurfaceProvider 上进行设置。
  • TextureView 检索 SurfaceTexture,并在 Preview.SurfaceProvider 上对其进行设置。
  • SurfaceView 获取 Surface,并在 Preview.SurfaceProvider 上对其进行设置。

如果出现上述任何一种情况,Preview 就会停止将帧流式传输到 PreviewView

将 PreviewView 添加到布局

以下示例显示了布局中的 PreviewView

代码语言:javascript
复制
<FrameLayout
    android:id="@+id/container">
        <androidx.camera.view.PreviewView
            android:id="@+id/previewView" />
</FrameLayout>

请求 CameraProvider

以下代码展示了如何请求 CameraProvider

代码语言:javascript
复制
import androidx.camera.lifecycle.ProcessCameraProvider
import com.google.common.util.concurrent.ListenableFuture

public class MainActivity extends AppCompatActivity {
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        cameraProviderFuture = ProcessCameraProvider.getInstance(this);
    }
}

检查 CameraProvider 可用性

请求 CameraProvider 后,请验证它能否在视图创建后成功初始化。以下代码展示了如何执行此操作:

代码语言:javascript
复制
cameraProviderFuture.addListener(() -> {
    try {
        ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
        bindPreview(cameraProvider);
    } catch (ExecutionException | InterruptedException e) {
        // No errors need to be handled for this Future.
        // This should never be reached.
    }
}, ContextCompat.getMainExecutor(this));

如需查看此示例中使用的 bindPreview 函数的示例,请参阅下一部分中提供的代码。

选择相机并绑定生命周期和用例

创建并确认 CameraProvider 后,请执行以下操作:

  1. 创建 Preview
  2. 指定所需的相机 LensFacing 选项。
  3. 将所选相机和任意用例绑定到生命周期。
  4. Preview 连接到 PreviewView

以下代码展示了一个示例:

代码语言:javascript
复制
void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
    Preview preview = new Preview.Builder()
            .build();

    CameraSelector cameraSelector = new CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build();

    preview.setSurfaceProvider(previewView.getSurfaceProvider());

    Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview);
}

请注意,bindToLifecycle() 会返回一个 Camera 对象。如需详细了解如何控制相机输出(如变焦和曝光),请参阅此指南。

现在,您已完成实现相机预览的操作。请构建您的应用,然后确认预览是否出现在您的应用中并能按预期工作。

2) 图像分析

图像分析用例为您的应用提供可供 CPU 访问的图像,您可以对这些图像执行图像处理、计算机视觉或机器学习推断。应用会实现对每个帧运行的 analyze() 方法。

如需在您的应用中使用图像分析,请按以下步骤操作:

  • 构建 ImageAnalysis 用例。
  • 创建 ImageAnalysis.Analyzer
  • 将分析器设为 ImageAnalysis
  • 将生命周期所有者、相机选择器和 ImageAnalysis 用例绑定到生命周期。

绑定后,CameraX 会立即将图像发送到已注册的分析器。完成分析后,调用 ImageAnalysis.clearAnalyzer() 或解除绑定 ImageAnalysis 用例以停止分析。

构建 ImageAnalysis 用例

ImageAnalysis 可将分析器(图像使用方)连接到 CameraX(图像生成方)。应用可以使用 ImageAnalysis.Builder 来构建 ImageAnalysis 对象。借助 ImageAnalysis.Builder,应用可以进行以下配置:

  • 图像输出参数:
  • 格式:CameraX 可通过 setOutputImageFormat(int) 支持 YUV_420_888RGBA_8888。默认格式为 YUV_420_888
  • Resolution 和 AspectRatio:您可以设置其中一个参数,但请注意,您不能同时设置这两个值。
  • 旋转角度。
  • 目标名称:使用该参数进行调试。* 图像流控制:
  • 后台执行器
  • 图像队列深度(分析器和 CamaraX 之间)
  • 背压策略

应用可以设置分辨率或宽高比,但不能同时设置这两个值。确切的输出分辨率取决于应用请求的大小(或宽高比)和硬件功能,并可能与请求的大小或宽高比不同。如需了解分辨率匹配算法,请参阅有关 setTargetResolution() 的文档

应用可以将输出图像像素配置为采用 YUV(默认)或 RGBA 颜色空间。设置 RGBA 输出格式时,CameraX 会在内部将图像从 YUV 颜色空间转换为 RGBA 颜色空间,并将图像位打包到 ImageProxy 第一个平面(其他两个平面未使用)的 ByteBuffer 中,序列如下:

代码语言:javascript
复制
ImageProxy.getPlanes()[0].buffer[0]: alpha
ImageProxy.getPlanes()[0].buffer[1]: red
ImageProxy.getPlanes()[0].buffer[2]: green
ImageProxy.getPlanes()[0].buffer[3]: blue
...

在执行设备无法满足帧速率要求的复杂图像分析时,您可以使用本主题的操作模式部分所述的策略将 CameraX 配置为丢帧。

创建分析器

应用可以通过实现 ImageAnalysis.Analyzer 接口并替换 analyze(ImageProxy image) 来创建分析器。在每个分析器中,应用都会收到一个 ImageProxy,它是 Media.Image 的封装容器。可以使用 ImageProxy.getFormat() 来查询图像格式。该格式使用应用通过 ImageAnalysis.Builder 提供的以下值之一表示:

  • 如果应用请求了 OUTPUT_IMAGE_FORMAT_RGBA_8888,则为 ImageFormat.RGBA_8888
  • 如果应用请求了 OUTPUT_IMAGE_FORMAT_YUV_420_888,则为 ImageFormat.YUV_420_888

如需了解颜色空间配置以及可检索像素字节的位置,请参阅构建 ImageAnalysis 用例。

在分析器中,应用应执行以下操作:

  1. 尽快分析给定的帧,最好在给定的帧速率时间限制内进行分析(例如,如果帧速率为 30 fps,则用时应低于 32 毫秒)。如果应用无法足够快地分析帧,请考虑采用一种受支持的丢帧机制。
  2. 通过调用 ImageProxy.close()ImageProxy 发布到 CameraX。请注意,您不应调用已封装 Media.Image 的 close 函数 (Media.Image.close())。

应用可以直接使用 ImageProxy 中的已封装 Media.Image。请不要对已封装的图像调用 Media.Image.close(),因为这会破坏 CameraX 中的图像分享机制;请改为使用 ImageProxy.close() 将底层 Media.Image 发布到 CameraX。

针对 ImageAnalysis 配置分析器

创建分析器后,使用 ImageAnalysis.setAnalyzer() 注册该分析器以开始分析。完成分析后,使用 ImageAnalysis.clearAnalyer() 移除已注册的分析器。

您只能配置一个活跃分析器用于分析图像。调用 ImageAnalysis.setAnalyzer() 会替换已注册的分析器(如果已存在该分析器)。应用可以在绑定用例之前或之后随时设置新的分析器。

将 ImageAnalysis 绑定到生命周期

注意:该步骤适用于所有 CameraX 用例。如需详细了解绑定和生命周期自定义,请参阅 CameraX API 模型。

强烈建议您使用 ProcessCameraProvider.bindToLifecycle() 函数将 ImageAnalysis 绑定到现有的 AndroidX 生命周期。请注意,bindToLifecycle() 函数会返回选定的 Camera 设备,该函数可用于微调曝光等高级设置。如需详细了解如何控制相机输出,请参阅此指南。

以下示例结合了上述步骤中的所有操作,将 CameraX ImageAnalysisPreview 用例绑定到了 lifeCycle 所有者:

代码语言:javascript
复制
ImageAnalysis imageAnalysis =
    new ImageAnalysis.Builder()
        // enable the following line if RGBA output is needed.
        //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
        .setTargetResolution(new Size(1280, 720))
        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
        .build();

imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
    @Override
    public void analyze(@NonNull ImageProxy imageProxy) {
        int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();
            // insert your code here.
            ...
            // after done, release the ImageProxy object
            imageProxy.close();
        }
    });

cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);

3)图片拍摄

图片拍摄用例旨在拍摄高分辨率的优质照片,不仅提供简单的相机手动控制功能,还提供自动白平衡、自动曝光和自动对焦 (3A) 功能。调用方负责决定如何使用拍摄的照片,具体包括以下选项:

  • takePicture(Executor, OnImageCapturedCallback):此方法为拍摄的图片提供内存缓冲区。
  • takePicture(OutputFileOptions, Executor, OnImageSavedCallback):此方法将拍摄的图片保存到提供的文件位置。

运行 ImageCapture 的可自定义执行程序有两种类型:回调执行程序和 IO 执行程序。

  • 回调执行程序是 takePicture 方法的参数。它用于执行用户提供的 OnImageCapturedCallback()
  • 如果调用方选择将图片保存到文件位置,您可以指定执行程序以执行 IO。如需设置 IO 执行程序,请调用 ImageCapture.Builder.setIoExecutor(Executor)。如果执行程序不存在,则默认 CameraX 为任务的内部 IO 执行程序。

实现

提供了拍照所需的基本控制功能。照片是使用闪光灯选项和连续自动对焦拍摄的。

如需缩短照片拍摄的延迟时间,请将 ImageCapture.CaptureMode 设置为 CAPTURE_MODE_MINIMIZE_LATENCY。如需优化照片质量,请将其设置为 CAPTURE_MODE_MAXIMIZE_QUALITY

以下代码示例展示了如何配置应用以拍摄照片:

代码语言:javascript
复制
ImageCapture imageCapture =
    new ImageCapture.Builder()
        .setTargetRotation(view.getDisplay().getRotation())
        .build();

cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, imageCapture, imageAnalysis, preview);

请注意,bindToLifecycle() 会返回一个 Camera 对象。如需详细了解如何控制相机输出(如变焦和曝光),请参阅此指南。

配置好相机后,以下代码会根据用户操作拍照:

代码语言:javascript
复制
public void onClick() {
    ImageCapture.OutputFileOptions outputFileOptions =
            new ImageCapture.OutputFileOptions.Builder(new File(...)).build();
    imageCapture.takePicture(outputFileOptions, cameraExecutor,
        new ImageCapture.OnImageSavedCallback() {
            @Override
            public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) {
                // insert your code here.
            }
            @Override
            public void onError(ImageCaptureException error) {
                // insert your code here.
            }
       }
    );
}

图片拍摄方法完全支持 JPEG 格式。如需查看有关如何将 Media.Image 对象从 YUV_420_888 格式转换为 RGB Bitmap对象的示例代码,请参阅 YuvToRgbConverter.kt

4)CameraX 视频捕获架构

捕获系统通常会录制视频流和音频流,对其进行压缩,对这两个流进行多路复用,然后将生成的流写入磁盘。

图 1. 视频和音频捕获系统概念图。

在 CameraX 中,用于视频捕获的解决方案是 VideoCapture 用例:

图 2. 展示 CameraX 如何处理 VideoCapture 用例的概念图。

如图 2 所示,CameraX 视频捕获包括几个高级架构组件:

  • SurfaceProvider,表示视频来源。
  • AudioSource,表示音频来源。
  • 用于对视频/音频进行编码和压缩的两个编码器。
  • 用于对两个流进行多路复用的媒体复用器。
  • 用于写出结果的文件保存器。

VideoCapture API 会对复杂的捕获引擎进行抽象化处理,为应用提供更加简单且直观的 API。

VideoCapture API 概述

VideoCapture 是一种 CameraX 用例,既可以单独使用,也可以与其他用例搭配使用。受支持的具体组合取决于相机硬件功能,不过 PreviewVideoCapture 这一用例组合适用于所有设备。

注意VideoCapture 是在 CameraX 软件包内的 camera-video 库中实现的,在 1.1.0-alpha10 及更高版本中可用。

VideoCapture API 包含可与应用通信的以下对象:

  • VideoCapture 是顶级用例类。VideoCapture 通过 CameraSelector 和其他 CameraX 用例绑定到 LifecycleOwner。如需详细了解这些概念和用法,请参阅 CameraX 架构。
  • Recorder 是与 VideoCapture 紧密耦合的 VideoOutput 实现。 Recorder 用于执行视频和音频捕获操作。应用通过 Recorder 创建录制对象。
  • PendingRecording 会配置录制对象,同时提供启用音频和设置事件监听器等选项。您必须使用 Recorder 来创建 PendingRecordingPendingRecording 不会录制任何内容。
  • Recording 会执行实际录制操作。您必须使用 PendingRecording 来创建 Recording

图 3 展示了这些对象之间的关系:

图 3. 展示 VideoCapture 用例中发生的交互的示意图。

图例

  1. 使用 QualitySelector 创建 Recorder
  2. 使用其中一个 OutputOptions 配置 Recorder
  3. 如果需要,使用 withAudioEnabled() 启用音频。
  4. 使用 VideoRecordEvent 监听器调用 start() 以开始录制。
  5. 针对 Recording 使用 pause()/resume()/stop() 来控制录制操作。
  6. 在事件监听器内响应 VideoRecordEvents

详细的 API 列表位于源代码内的 current-txt 中。

使用 VideoCapture API

如需将 CameraX VideoCapture 用例集成到您的应用中,请执行以下操作:

  1. 绑定 VideoCapture
  2. 准备和配置录制。
  3. 开始和控制运行时录制。

后面的部分概述了您可以在每个步骤中执行哪些操作,以获取端到端录制会话。

绑定 VideoCapture

如需绑定 VideoCapure 用例,请执行以下操作:

  1. 创建一个 Recorder 对象。
  2. 创建 VideoCapture 对象。
  3. 绑定到 Lifecycle

CameraX VideoCapture API 遵循构建器设计模式。应用使用 Recorder.Builder 来创建 Recorder。您还可以通过 QualitySelector 对象为 Recorder 配置视频分辨率。

CameraX Recorder 支持以下预定义的视频分辨率 Qualities

  • Quality.UHD,适用于 4K 超高清视频大小 (2160p)
  • Quality.FHD,适用于全高清视频大小 (1080p)
  • Quality.HD,适用于高清视频大小 (720p)
  • Quality.SD,适用于标清视频大小 (480p)

请注意,获得应用授权后,CameraX 还可以选择其他分辨率。

每个选项对应的确切视频大小取决于相机和编码器的功能。如需了解详情,请参阅 CamcorderProfile 的文档。

应用可以通过创建 QualitySelector 来配置分辨率。您可以使用以下方法之一创建 QualitySelector

  • 使用 fromOrderedList() 提供几个首选分辨率,并包含一个后备策略,以备在不支持任何首选分辨率时使用。

CameraX 可以根据所选相机的功能确定最佳后备匹配项。如需了解详情,请参阅 QualitySelectorFallbackStrategy specification。例如,以下代码会请求支持的最高录制分辨率;如果所有请求分辨率都不受支持,则授权 CameraX 选择最接近 Quality.SD 分辨率的分辨率:

代码语言:javascript
复制
val qualitySelector = QualitySelector.fromOrderedList(
         listOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD),
         FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))

  • 首先查询相机功能,然后使用 QualitySelector::from() 从受支持的分辨率中进行选择:
代码语言:javascript
复制
val cameraInfo = cameraProvider.availableCameraInfos.filter {
    Camera2CameraInfo
    .from(it)
    .getCameraCharacteristic(CameraCharacteristics.LENS\_FACING) == CameraMetadata.LENS_FACING_BACK
}

val supportedQualities = QualitySelector.getSupportedQualities(cameraInfo[0])
val filteredQualities = arrayListOf (Quality.UHD, Quality.FHD, Quality.HD, Quality.SD)
                       .filter { supportedQualities.contains(it) }

// Use a simple ListView with the id of simple_quality_list_view
viewBinding.simpleQualityListView.apply {
    adapter = ArrayAdapter(context,
                           android.R.layout.simple_list_item_1,
                           filteredQualities.map { it.qualityToString() })

    // Set up the user interaction to manually show or hide the system UI.
    setOnItemClickListener { _, _, position, _ ->
        // Inside View.OnClickListener,
        // convert Quality.* constant to QualitySelector
        val qualitySelector = QualitySelector.from(filteredQualities[position])

        // Create a new Recorder/VideoCapture for the new quality
        // and bind to lifecycle
        val recorder = Recorder.Builder()
            .setQualitySelector(qualitySelector).build()

         // ...
    }
}

// A helper function to translate Quality to a string
fun Quality.qualityToString() : String {
    return when (this) {
        Quality.UHD -> "UHD"
        Quality.FHD -> "FHD"
        Quality.HD -> "HD"
        Quality.SD -> "SD"
        else -> throw IllegalArgumentException()
    }
}


请注意,QualitySelector.getSupportedQualities() 返回的功能肯定适用于 VideoCapture 用例或 VideoCapturePreview 用例的组合。与 ImageCaptureImageAnalysis 用例绑定时,如果请求的相机不支持所需的组合,CameraX 仍可能会绑定失败。

具有 QualitySelector 后,应用即可创建 VideoCapture 对象并执行绑定。请注意,此绑定与和其他用例的绑定相同:

代码语言:javascript
复制
val recorder = Recorder.Builder()
    .setExecutor(cameraExecutor).setQualitySelector(qualitySelector)
    .build()
val videoCapture = VideoCapture.withOutput(recorder)

try {
    // Bind use cases to camera
    cameraProvider.bindToLifecycle(
            this, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture)
} catch(exc: Exception) {
    Log.e(TAG, "Use case binding failed", exc)
}

请注意,bindToLifecycle() 会返回一个 Camera 对象。如需详细了解如何控制相机输出(如变焦和曝光),请参阅此指南

注意:目前无法配置最终的视频编解码器和容器格式。

Recorder 会选择最适合系统的格式。最常见的视频编解码器是 H.264 AVC,其容器格式为 MPEG-4。

配置和创建录制对象

应用可以通过 Recorder 创建录制对象来执行视频和音频捕获操作。应用通过执行以下操作来创建录制对象:

  1. 使用 prepareRecording() 配置 OutputOptions
  2. (可选)启用录音功能。
  3. 使用 start() 注册 VideoRecordEvent 监听器,并开始捕获视频。

当您调用 start() 函数时,Recorder 会返回 Recording 对象。应用可以使用此 Recording 对象完成捕获或执行其他操作,例如暂停或恢复。

Recorder 一次支持一个 Recording 对象。对前面的 Recording 对象调用 Recording.stop()Recording.close() 后,您便可以开始新的录制。

我们来更详细地看看这些步骤。首先,应用使用 Recorder.prepareRecording() 为 Recorder 配置 OutputOptionsRecorder 支持以下类型的 OutputOptions

  • FileDescriptorOutputOptions,用于捕获到 FileDescriptor 中。
  • FileOutputOptions,用于捕获到 File 中。
  • MediaStoreOutputOptions,用于捕获到 MediaStore 中。

无论使用哪种 OutputOptions 类型,您都能通过 setFileSizeLimit() 来设置文件大小上限。其他选项特定于单个输出类型,例如 ParcelFileDescriptor 特定于 FileDescriptorOutputOptions

prepareRecording() 会返回 PendingRecording 对象,该对象是一个中间对象,用于创建相应的 Recording 对象。PendingRecording 是一个瞬态类,在大多数情况下应不可见,并且很少被应用缓存。

应用可以进一步配置录制对象,例如:

  • 使用 withAudioEnabled() 启用音频。
  • 使用 start(Executor, Consumer<VideoRecordEvent>) 注册监听器,以接收视频录制事件。

要开始录制,请调用 PendingRecording.start()。CameraX 会将 PendingRecording 转换为 Recording,将录制请求加入队列,并将新创建的 Recording 对象返回给应用。一旦在相应相机设备上开始录制,CameraX 就会发送 VideoRecordEvent.EVENT_TYPE_START 事件。

以下示例展示了如何将视频和音频录制到 MediaStore 文件中:

代码语言:javascript
复制
// Create MediaStoreOutputOptions for our recorder
val name = "CameraX-recording-" +
        SimpleDateFormat(FILENAME_FORMAT, Locale.US)
                .format(System.currentTimeMillis()) + ".mp4"
val contentValues = ContentValues().apply {
   put(MediaStore.Video.Media.DISPLAY_NAME, name)
}
val mediaStoreOutput = MediaStoreOutputOptions.Builder(this.contentResolver,
                              MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
                              .setContentValues(contentValues)
                              .build()

// 2. Configure Recorder and Start recording to the mediaStoreOutput.
val recording = videoCapture.output
                .prepareRecording(context, mediaStoreOutput)
                .withAudioEnabled()
                .start(ContextCompat.getMainExecutor(this), captureListener)

控制活跃录制对象

您可以使用以下方法暂停、恢复和停止正在进行的 Recording

  • pause,用于暂停当前的活跃录制。
  • resume(),用于恢复已暂停的活跃录制。
  • stop(),用于完成录制并清空所有关联的录制对象。

请注意,无论录制处于暂停状态还是活跃状态,您都可以调用 stop() 来终止 Recording

如果您已使用 PendingRecording.start() 注册了 EventListenerRecording 会使用 VideoRecordEvent 进行通信。

  • VideoRecordEvent.EVENT_TYPE_STATUS 用于录制统计信息,例如当前文件的大小和录制的时间跨度。
  • VideoRecordEvent.EVENT_TYPE_FINALIZE 用于录制结果,会包含最终文件的 URI 以及任何相关错误等信息。

在您的应用收到表示录制会话成功的 EVENT_TYPE_FINALIZE 后,您就可以从 OutputOptions 中指定的位置访问捕获的视频。

五、 CameraX、Camx要分清

从事高通平台Camera Hal开发的同学, 对Camx应该不陌生。CamX是高通目前最新的Camera框架,是Hal层实现的一套框架,高通旧的Camera框架是mm-camera框架。

所以对应CameraX,我一般会说成Google CameraX,方便有些同学搞混淆。

参考文档:

Android Jetpack介绍

https://developer.android.google.cn/jetpack?hl=zh-cn

CameraX架构

https://developer.android.google.cn/training/camerax/architecture?hl=zh_cn

相机使用示例代码

https://github.com/android/camera-samples/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-07-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小驰成长圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、CameraX初认识?
  • 二、 Google为啥要推出CameraX?
  • 三、 CameraX基本框架介绍
  • 四、 CameraX的基本使用示例
  • 使用 PreviewView
    • 将 PreviewView 添加到布局
      • 请求 CameraProvider
        • 检查 CameraProvider 可用性
          • 选择相机并绑定生命周期和用例
            • 构建 ImageAnalysis 用例
              • 创建分析器
                • 针对 ImageAnalysis 配置分析器
                  • 将 ImageAnalysis 绑定到生命周期
                  • 3)图片拍摄
                  • 实现
                  • VideoCapture API 概述
                  • 使用 VideoCapture API
                    • 绑定 VideoCapture
                    • 配置和创建录制对象
                    • 控制活跃录制对象
                    • 五、 CameraX、Camx要分清
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档