视频分享最佳实践

很多人使用 Android 设备分享视频。所接收电子邮件的质量 视频通常不如原始视频, 由分享应用触发本文档介绍了如何优化 共享视频和要避免的一些常见视频处理误区。优化 有关如何分享 HDR 视频内容的信息,请参阅 本页中的使用转换器模块将 HDR 转码为 SDR

主要目标是保持稳定的分辨率并保持视频质量 在准备分享视频的过程中,在尽可能长的时间内显示。

共享流水线

图 1 显示了分享视频的典型流程:

分享视频流水线 图 1. 视频分享流水线。

流水线包括以下步骤:

  1. 拍摄视频并对视频进行编码,可能会在拍摄过程中添加效果。 或者,用户可以跳过此步骤,从存储空间中选择视频 从其他应用预先录制的内容
  2. 对视频进行编辑、过滤、修饰或以其他方式处理。
  3. 缩放视频或调整其大小,以准备进行转码。
  4. 对视频进行转码以便分享。第 2 步中的过滤通常在 这一步。

流水线中有两个步骤,您可以在这两个步骤中设置 决定视频质量的参数:在初始 录制和转码此外,您可能需要 在完成最终转码步骤之前重新调整视频的尺寸,这也会影响画质。

建议

表 1 显示了决定视频质量的五个主要参数, 指示哪些步骤可以使用它们。

参数 截图/录像 共享
个人资料 Y Y
分辨率 Y Y
比特率 Y Y
量化参数 (QP) (很少) Y
B 帧 Y

表 1. 决定视频画质的主要参数

个人资料

为了获得更好的结果,请使用 编解码器。对于 AVC 编码,请选择 High profile 和 level 4。

分辨率、剪裁和缩放

您可以在缩放步骤中更改所拍摄视频的初始分辨率 但缩放会降低 视频。我们建议您不要进行缩放,并为初始图片选择分辨率 以供在整个流水线中使用。还要记住 剪裁会导致图片质量不佳,尤其是在放大剪裁后的图片 图片。请遵循以下准则:

  • 选择分辨率至少与最终分享分辨率一样大。
  • 拍摄分辨率不应大大超过分享分辨率 除非所有的中间步骤都是为了支持 分辨率(例如在初始捕获期间使用更高的比特率)。

    • 如果共享编码生成的分辨率为 720x1280,我们建议使用 720x1280 拍摄分辨率。
    • 如果拍摄和共享之间的中间步骤包括剪裁,请使用 更高的捕获分辨率(如 1080x1920),并增加 捕获码率以处理额外的像素。
  • 过度剪裁会导致图片质量不佳,尤其是在剪裁 放大图片。

  • 避免从较低分辨率放大到较高分辨率。提升尝试次数 创建不存在的细节。支持所需的更高分辨率 从头开始。

  • 如果您必须提高分辨率,请调整编码参数。例如,如果 分辨率会是原来的两倍,像素数是比特率的两倍。

分辨率和比特率是相互关联的。例如,携带高分辨率的 通过最终转码为低比特率的共享管道 与开始时分辨率较低相比,生成的图像质量较差。作为 比特率降低,但在一些交叉点上,较小的分辨率 来取得更理想的成效:

比特率 分辨率
5 Mbps 以上 1080x1920
1.5 - 5+ Mbps 720x1280
不超过 1.5 Mbps 相当于标清。在宽高比为 9:16 时,相同的像素数约为 416x736

表 2. 比特率与分辨率

许多热门应用会以 720p 或更低的分辨率分享视频。数据显示 720p 分辨率适合在 1.5 以内 5 Mbps。

比特率

录制

使用较高的编码比特率有助于最大限度地提升视频品质 质量。建议您选择适合原生相机应用的码率。对于 分辨率为 720x1280,我们建议捕获比特率为 10 Mbps。

由于捕获编码是在设备上完成的,因此你可以使用更高的比特率 以极小的负向量来补偿大多数共享步骤转换 影响。生成的较大文件仅用于设备端操作。

您可以在最后的转码步骤降低比特率,如表 2 所示。

分享

比特率在分享时影响最大,因为它与 将要上传的视频的尺寸。您需要权衡 质量、文件传输时间和云端存储费用。

编码配置文件、B 帧和 QP 边界值的选择也更多 这比拍摄期间非常重要。

我们建议比特率在 4-5 Mbps 之间(适用于 720x1280 分辨率)以确保良好 视觉质量

量化参数 (QP)

在 Android 12 及更高版本中,QP 密钥是标准化的,可在 MediaFormat API 和 NDK 媒体库。 在较低的 Android 版本中,QP 操作只能通过框架实现 函数。MediaFormat

录制

在视频拍摄过程中,请使用码率控制而非 QP 设置, 。

我们不建议针对 10Mbps 的拍摄比特率调整 QP 设置 (适用于 720x1280)。如果捕获比特率明显较低,低于 5 Mbps 720x1280,QP 设置为 40 是 而不会强迫编解码器过于频繁地超过目标比特率。

分享

我们建议的最大 QP 边界值为 40,尤其是在比特率低于 4 Mbps 时。 虽然这样可以确保编码视频达到最低质量, 产生更高的比特率码率的提升取决于 视频的复杂性尽管分享应用可能会容忍 所生成视频的比特率,则可能无法容忍高于 特定阈值

您可以对视频重新编码,以便与 限制更加宽松(更高)的最大 QP 边界。这使得编解码器可以更自由地 牺牲质量并保留视频的其他部分。您可以将 因为这是一项转码操作;你已经 捕获了您想要分享的视频

但其缺点在于 参数会增加分享视频所需的时间。有助于减少 此延迟时间是为了检查部分转码视频 您不应超过比特率上限如果不是,您可以停止 转码并使用更合适的 QP 参数重试。

B 帧和编码配置文件

建议仅在共享步骤中使用 B 帧,并且仅在运行时 Android 10 或更高版本。

应用应使用 CodecCapabilities、 因为并非所有设备都支持主要配置文件或高配置文件使用最高级别的配置文件 支持:High >主要 >基准。为了最安全,请不要 配置 B 帧 (KEY_LATENCYKEY_MAX_B_FRAMES) 使用基准组合时的 因为有些编码器的配置可能会失败

以下代码段假定了一个 'MediaFormat format',用于 配置 AVC 编码器

Android 10

API 29 或更高版本

请使用支持的最高配置文件,并将 B 帧参数设置为 1:

format.setInt32(KEY_PROFILE, AVCProfileHigh);
format.setInt32(KEY_MAX_B_FRAMES, 1);

在这种情况下,请勿设置 KEY_LATENCY

Android 8、8.1 和 9

API 26、27、28

使用支持的最高配置文件,但停用生成 B 帧的功能。这个 纳入了 以下系统版本中的 MediaMuxer

format.setInt32(KEY_PROFILE, AVCProfileHigh);
format.setInt32(KEY_LATENCY, 1);

KEY_LATENCY 值会禁止编解码器生成 B 帧,但仍 充分利用其他编解码器效率

如果您的应用不使用 MediaMuxer 来组建最终输出文件,您可以 通过将 KEY_LATENCY 值设置为 2(而不是 1)来启用 B 帧。这应该 允许编解码器生成 B 帧。

Android 7.1 及更低版本

API 25 及更早版本

使用基准配置文件以获得最安全的结果。

format.setInt32(KEY_PROFILE, AVCProfileBaseline);

在版本 7 之前,Android AOSP 仅支持基准配置文件。不过, OEM 可能在某些设备上启用了主配置文件/高配置文件, 使用供应商专用的配置文件

如果您的应用不使用 MediaMuxer,则在以下情况下,您可以使用主配置文件或高配置文件: 编解码器支持它没有公共格式密钥可以控制 B- 帧。

使用转换器模块将 HDR 转码为 SDR

从 Android 13(API 级别 33)开始,我们建议使用 Jetpack Media3 转换器 模块,以便将 HDR 内容分享到符合以下条件的应用、服务和设备: 支持 HDR。Transformer 模块的工作原理是对 将 HDR 视频流输入 SDR 并将结果保存为 MP4 能够在不丢失细节或图像亮度的情况下成功播放。

注意:在以 Android 12(API 级别 32)之间的系统版本为目标平台的设备上 低至 Android 7.0(API 级别 24),则 Transformer 模块的工作原理有所不同。如果 设备支持 HDR,您的应用在播放内容时不会进行色调映射。 如果设备不支持 HDR,则会抛出错误,指明 HDR 不支持色调映射。

以下代码设置一个转换器,用于将输入映射到 SDR 的色调, 将其重新编码为输入格式(如 H.264/AVC):

Kotlin

val transformer = Transformer.Builder(context)
    .setTransformationRequest(
        TransformationRequest.Builder()
            .setHdrMode(TransformationRequest.HDR_MODE_TONE_MAP_HDR_TO_SDR)
            .build())
    .addListener(/* ... */)
    .build()

Java

Transformer transformer = new Transformer.Builder(context)
    .setTransformationRequest(
        new TransformationRequest.Builder()
            .setHdrMode(TransformationRequest.HDR_MODE_TONE_MAP_HDR_TO_SDR)
            .build())
    .addListener(/* ... */)
    .build();

如需试用色调映射功能,请参阅 Transformer 演示应用

您还可以使用 MediaCodec,尽管实现的 更为复杂。有关详情,请参阅 MediaCodec 参考文档。