ExoPlayer 演示应用程序

ExoPlayer 的主要演示应用程序有两个主要目的

  1. 提供一个相对简单但功能齐全的 ExoPlayer 使用示例。该演示应用程序可以作为方便的起点,供您开发自己的应用程序。
  2. 为了方便您试用 ExoPlayer。该演示应用程序可用于测试您自己的内容的播放,除了包含的示例之外。

本页介绍如何获取、编译和运行演示应用程序。它还介绍了如何使用它来播放您自己的媒体。

获取代码

主要演示应用程序的源代码可以在我们 GitHub 项目demos/main 文件夹中找到。如果您还没有这样做,请将项目克隆到本地目录

git clone https://github.com/androidx/media.git

接下来,在 Android Studio 中打开项目。您应该在 Android 项目视图中看到以下内容(演示应用程序的相关文件夹已展开)

The project in Android Studio

编译和运行

要编译和运行演示应用程序,请在 Android Studio 中选择并运行 demo 配置。演示应用程序将安装并在连接的 Android 设备上运行。我们建议尽可能使用物理设备。如果您想使用模拟器,请阅读 支持的设备 中的模拟器部分,并确保您的虚拟设备使用 API 等级至少为 23 的系统映像。

SampleChooserActivity and PlayerActivity

演示应用程序呈现一个示例列表 (SampleChooserActivity)。选择一个示例将打开一个用于播放的第二个活动 (PlayerActivity)。该演示具有播放控制和音轨选择功能。它还使用 ExoPlayer 的 EventLogger 实用程序类将有用的调试信息输出到系统日志。可以使用以下命令查看此日志(以及其他标签的错误级别日志)

adb logcat EventLogger:V *:E

启用捆绑解码器

ExoPlayer 有许多扩展程序,允许使用捆绑的软件解码器,包括 AV1、VP9、Opus、FLAC 和 FFmpeg(仅音频)。演示应用程序可以构建为包含并使用这些扩展程序,如下所示

  1. 构建要包含的每个扩展程序。请注意,这是一个手动过程。请参阅每个扩展程序的 README.md 文件以获取说明。
  2. 在 Android Studio 的构建变体视图中,将演示模块的构建变体设置为 withDecoderExtensionsDebugwithDecoderExtensionsRelease,如以下图像所示。

    Selecting the demo `withDecoderExtensionsDebug` build variant

  3. 正常编译、安装和运行 demo 配置。

默认情况下,只有在没有合适的平台解码器时才会使用扩展解码器。可以指定应优先使用扩展解码器,如以下部分所述。

播放您自己的内容

在演示应用程序中播放您自己的内容有多种方法。

1. 编辑 assets/media.exolist.json

演示应用程序中列出的示例是从 assets/media.exolist.json 加载的。通过编辑此 JSON 文件,可以从演示应用程序中添加和删除示例。模式如下,其中 [O] 表示可选属性。

[
  {
    "name": "Name of heading",
    "samples": [
      {
        "name": "Name of sample",
        "uri": "The URI of the sample",
        "extension": "[O] Sample type hint. Values: mpd, ism, m3u8",
        "clip_start_position_ms": "[O] A start point to which the sample should be clipped, in milliseconds"
        "clip_end_position_ms": "[O] An end point from which the sample should be clipped, in milliseconds"
        "drm_scheme": "[O] Drm scheme if protected. Values: widevine, playready, clearkey",
        "drm_license_uri": "[O] URI of the license server if protected",
        "drm_force_default_license_uri": "[O] Whether to force use of "drm_license_uri" for key requests that include their own license URI",
        "drm_key_request_properties": "[O] Key request headers if protected",
        "drm_session_for_clear_content": "[O] Whether to attach a DRM session to clear video and audio tracks"
        "drm_multi_session": "[O] Enables key rotation if protected",
        "subtitle_uri": "[O] The URI of a subtitle sidecar file",
        "subtitle_mime_type": "[O] The MIME type of subtitle_uri (required if subtitle_uri is set)",
        "subtitle_language": "[O] The BCP47 language code of the subtitle file (ignored if subtitle_uri is not set)",
        "ad_tag_uri": "[O] The URI of an ad tag to load via the IMA extension"
      },
      ...etc
    ]
  },
  ...etc
]

可以使用以下模式指定示例的播放列表

[
  {
    "name": "Name of heading",
    "samples": [
      {
        "name": "Name of playlist sample",
        "playlist": [
          {
            "uri": "The URI of the first sample in the playlist",
            "extension": "[O] Sample type hint. Values: mpd, ism, m3u8"
            "clip_start_position_ms": "[O] A start point to which the sample should be clipped, in milliseconds"
            "clip_end_position_ms": "[O] An end point from which the sample should be clipped, in milliseconds"
            "drm_scheme": "[O] Drm scheme if protected. Values: widevine, playready, clearkey",
            "drm_license_uri": "[O] URI of the license server if protected",
            "drm_force_default_license_uri": "[O] Whether to force use of "drm_license_uri" for key requests that include their own license URI",
            "drm_key_request_properties": "[O] Key request headers if protected",
            "drm_session_for_clear_content": "[O] Whether to attach a DRM session to clear video and audio tracks",
            "drm_multi_session": "[O] Enables key rotation if protected",
            "subtitle_uri": "[O] The URI of a subtitle sidecar file",
            "subtitle_mime_type": "[O] The MIME type of subtitle_uri (required if subtitle_uri is set)",
            "subtitle_language": "[O] The BCP47 language code of the subtitle file (ignored if subtitle_uri is not set)"
          },
          {
            "uri": "The URI of the second sample in the playlist",
            ...etc
          },
          ...etc
        ]
      },
      ...etc
    ]
  },
  ...etc
]

如果需要,密钥请求标头将指定为包含每个标头的字符串属性的对象

"drm_key_request_properties": {
  "name1": "value1",
  "name2": "value2",
  ...etc
}

在示例选择器活动中,溢出菜单包含用于指定是否优先使用扩展解码器的选项。

本地文件 URI 和作用域存储限制

在指定本地文件 URI 时,演示应用程序会请求读取这些文件所需的存储访问权限。但是,从 Android 13 开始,无法加载没有以典型媒体文件扩展名(如 .mp4)结尾的任意文件。如果您需要加载这样的文件,可以将其放置在演示应用程序的特定存储目录中,该目录没有访问限制。这通常位于 /sdcard/Android/data/androidx.media3.demo.main/files

2. 加载外部 exolist.json 文件

演示应用程序可以使用上述模式加载外部 JSON 文件,并根据 *.exolist.json 约定命名。例如,如果您在 https://yourdomain.com/samples.exolist.json 上托管了这样的文件,则可以使用以下方法在演示应用程序中打开它

adb shell am start -a android.intent.action.VIEW \
    -d https://yourdomain.com/samples.exolist.json

在安装了演示应用程序的设备上点击 *.exolist.json 链接(例如,在浏览器或电子邮件客户端中)也将使其在演示应用程序中打开。因此,托管 *.exolist.json JSON 文件提供了一种简单的方法来分发内容,供其他人使用演示应用程序进行尝试。

3. 触发意图

意图可用于绕过示例列表并直接启动播放。要播放单个示例,请将意图的操作设置为 androidx.media3.demo.main.action.VIEW,并将它的数据 URI 设置为要播放的示例的 URI。可以使用以下命令从终端触发此类意图

adb shell am start -a androidx.media3.demo.main.action.VIEW \
    -d https://yourdomain.com/sample.mp4

支持的单个示例意图的可选额外信息是

  • 示例配置额外信息
    • mime_type [字符串] 示例 MIME 类型提示。例如,DASH 内容的 application/dash+xml
    • clip_start_position_ms [长整型] 示例应剪切到的起点,以毫秒为单位。
    • clip_end_position_ms [长整型] 示例应剪切到的终点,以毫秒为单位。
    • drm_scheme [字符串] 如果受保护,则为 DRM 方案。有效值为 widevineplayreadyclearkey。DRM 方案 UUID 也被接受。
    • drm_license_uri [字符串] 如果受保护,则为许可证服务器的 URI。
    • drm_force_default_license_uri [布尔值] 是否强制使用 drm_license_uri 用于包含其自身许可证 URI 的密钥请求。
    • drm_key_request_properties [字符串数组] 如果受保护,则打包为 name1、value1、name2、value2 等等的密钥请求标头。
    • drm_session_for_clear_content [布尔值] 是否将 DRM 会话附加到清晰的视频和音频轨道。
    • drm_multi_session [布尔值] 如果受保护,则启用密钥轮换。
    • subtitle_uri [字符串] 字幕副标题文件的 URI。
    • subtitle_mime_type [字符串] subtitle_uri 的 MIME 类型(如果设置了 subtitle_uri,则必需)。
    • subtitle_language [字符串] 字幕文件的 BCP47 语言代码(如果未设置 subtitle_uri,则忽略)。
    • ad_tag_uri [字符串] 使用 [IMA 扩展][ ] 加载的广告标签的 URI。
    • prefer_extension_decoders [布尔值] 是否优先使用扩展解码器而不是平台解码器。

当使用 adb shell am start 触发意图时,可以使用 --es 设置可选字符串额外信息(例如,--es extension mpd)。可以使用 --ez 设置可选布尔值额外信息(例如,--ez prefer_extension_decoders TRUE)。可以使用 --el 设置可选长整型额外信息(例如,--el clip_start_position_ms 5000)。可以使用 --esa 设置可选字符串数组额外信息(例如,--esa drm_key_request_properties name1,value1)。

要播放示例的播放列表,请将意图的操作设置为 androidx.media3.demo.main.action.VIEW_LIST。示例配置额外信息与 androidx.media3.demo.main.action.VIEW 的额外信息相同,但有两个区别

  • 额外信息的键应该带有下划线和示例的 0 为基的索引作为后缀。例如,extension_0 将提示第一个示例的示例类型。 drm_scheme_1 将设置第二个示例的 DRM 方案。
  • 示例的 URI 作为额外信息传递,键为 uri_<sample-index>

其他与示例无关的额外信息不会改变。例如,您可以在终端中运行以下命令来播放包含两个项目的播放列表,覆盖第二个项目的扩展名

adb shell am start -a androidx.media3.demo.main.action.VIEW_LIST \
    --es uri_0 https://a.com/sample1.mp4 \
    --es uri_1 https://b.com/sample2.fake_mpd \
    --es extension_1 mpd