Демо-приложение ExoPlayer

Основное демонстрационное приложение ExoPlayer выполняет две основные функции:

  1. Цель данного примера — продемонстрировать относительно простое, но полнофункциональное использование ExoPlayer. Демонстрационное приложение может служить удобной отправной точкой для разработки собственного приложения.
  2. Чтобы упростить тестирование ExoPlayer, в демо-версии приложения, помимо включенных в комплект примеров, можно проверить воспроизведение собственного контента.

На этой странице описано, как получить, скомпилировать и запустить демонстрационное приложение. Также описано, как использовать его для воспроизведения собственных медиафайлов.

Получение кода

Исходный код основного демонстрационного приложения можно найти в папке demos/main нашего проекта на GitHub . Если вы еще этого не сделали, клонируйте проект в локальную директорию:

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

Далее откройте проект в Android Studio. В окне проекта Android вы должны увидеть следующее (соответствующие папки демонстрационного приложения развернуты):

Проект в Android Studio

Компиляция и запуск

Для компиляции и запуска демонстрационного приложения выберите и запустите конфигурацию demo в Android Studio. Демонстрационное приложение будет установлено и запущено на подключенном устройстве Android. Мы рекомендуем использовать физическое устройство, если это возможно. Если вы хотите использовать эмулятор, пожалуйста, ознакомьтесь с разделом «Поддерживаемые устройства» в разделе «Эмуляторы» и убедитесь, что ваше виртуальное устройство использует образ системы с уровнем API не ниже 23.

SampleChooserActivity и PlayerActivity

Демонстрационное приложение отображает список сэмплов ( SampleChooserActivity ). Выбор сэмпла откроет второе окно ( PlayerActivity ) для воспроизведения. Демонстрационное приложение включает элементы управления воспроизведением и функцию выбора треков. Оно также использует вспомогательный класс EventLogger из ExoPlayer для вывода полезной отладочной информации в системный журнал. Этот журнал (а также журнал ошибок для других тегов) можно просмотреть с помощью команды:

adb logcat EventLogger:V *:E

Включение встроенных декодеров

ExoPlayer имеет ряд расширений, позволяющих использовать встроенные программные декодеры, включая AV1, VP9, ​​Opus, FLAC и FFmpeg (только аудио). Демонстрационное приложение можно собрать с учетом этих расширений следующим образом:

  1. Соберите каждое из расширений, которые вы хотите включить. Обратите внимание, что это ручной процесс. Инструкции см. в файле README.md каждого расширения.
  2. В окне «Варианты сборки» в Android Studio установите вариант сборки для демонстрационного модуля на withDecoderExtensionsDebug или withDecoderExtensionsRelease как показано на следующем изображении.

    Выбор варианта сборки demo `withDecoderExtensionsDebug`

  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. Cannot be combined with mime_type. 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",
        "mime_type": "[O] The MIME type of the sample. Cannot be combined with extension.",
        "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. Cannot be combined with mime_type. 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",
            "mime_type": "[O] The MIME type of the sample. Cannot be combined with extension.",
            "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 (например, в браузере или почтовом клиенте) на устройстве с установленным демонстрационным приложением также откроет её в демонстрационном приложении. Таким образом, размещение JSON-файла *.exolist.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 [String] Пример подсказки типа MIME. Например, application/dash+xml для содержимого DASH.
    • clip_start_position_ms [Long] Начальная точка, до которой следует обрезать сэмпл, в миллисекундах.
    • clip_end_position_ms [Long] Конечная точка, от которой следует обрезать сэмпл, в миллисекундах.
    • drm_scheme [String] Схема DRM, если она защищена. Допустимые значения: widevine , playready и clearkey . Также принимаются UUID схем DRM.
    • drm_license_uri [String] 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.
    • drm_multi_session [Логическое значение] Включает ротацию клавиш, если она защищена.
    • subtitle_uri [String] URI файла-дополнения к субтитрам.
    • subtitle_mime_type [String] MIME-тип subtitle_uri (обязательно, если subtitle_uri задан).
    • subtitle_language [String] Языковой код BCP47 файла субтитров (игнорируется, если subtitle_uri не задан).
    • ad_tag_uri [Строка] URI рекламного тега для загрузки с использованием [расширения IMA][].
    • prefer_extension_decoders [Boolean] Указывает, какие декодеры расширений предпочтительнее, чем декодеры платформы.

При использовании adb shell am start для запуска интента можно задать необязательный строковый параметр с помощью --es (например, --es extension mpd ). Необязательный логический параметр можно задать с помощью --ez (например, --ez prefer_extension_decoders TRUE ). Необязательный параметр типа long можно задать с помощью --el (например, --el clip_start_position_ms 5000 ). Необязательный параметр типа string array можно задать с помощью --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
,

Основное демонстрационное приложение ExoPlayer выполняет две основные функции:

  1. Цель данного примера — продемонстрировать относительно простое, но полнофункциональное использование ExoPlayer. Демонстрационное приложение может служить удобной отправной точкой для разработки собственного приложения.
  2. Чтобы упростить тестирование ExoPlayer, в демо-версии приложения, помимо включенных в комплект примеров, можно проверить воспроизведение собственного контента.

На этой странице описано, как получить, скомпилировать и запустить демонстрационное приложение. Также описано, как использовать его для воспроизведения собственных медиафайлов.

Получение кода

Исходный код основного демонстрационного приложения можно найти в папке demos/main нашего проекта на GitHub . Если вы еще этого не сделали, клонируйте проект в локальную директорию:

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

Далее откройте проект в Android Studio. В окне проекта Android вы должны увидеть следующее (соответствующие папки демонстрационного приложения развернуты):

Проект в Android Studio

Компиляция и запуск

Для компиляции и запуска демонстрационного приложения выберите и запустите конфигурацию demo в Android Studio. Демонстрационное приложение будет установлено и запущено на подключенном устройстве Android. Мы рекомендуем использовать физическое устройство, если это возможно. Если вы хотите использовать эмулятор, пожалуйста, ознакомьтесь с разделом «Поддерживаемые устройства» в разделе «Эмуляторы» и убедитесь, что ваше виртуальное устройство использует образ системы с уровнем API не ниже 23.

SampleChooserActivity и PlayerActivity

Демонстрационное приложение отображает список сэмплов ( SampleChooserActivity ). Выбор сэмпла откроет второе окно ( PlayerActivity ) для воспроизведения. Демонстрационное приложение включает элементы управления воспроизведением и функцию выбора треков. Оно также использует вспомогательный класс EventLogger из ExoPlayer для вывода полезной отладочной информации в системный журнал. Этот журнал (а также журнал ошибок для других тегов) можно просмотреть с помощью команды:

adb logcat EventLogger:V *:E

Включение встроенных декодеров

ExoPlayer имеет ряд расширений, позволяющих использовать встроенные программные декодеры, включая AV1, VP9, ​​Opus, FLAC и FFmpeg (только аудио). Демонстрационное приложение можно собрать с учетом этих расширений следующим образом:

  1. Соберите каждое из расширений, которые вы хотите включить. Обратите внимание, что это ручной процесс. Инструкции см. в файле README.md каждого расширения.
  2. В окне «Варианты сборки» в Android Studio установите вариант сборки для демонстрационного модуля на withDecoderExtensionsDebug или withDecoderExtensionsRelease как показано на следующем изображении.

    Выбор варианта сборки demo `withDecoderExtensionsDebug`

  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. Cannot be combined with mime_type. 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",
        "mime_type": "[O] The MIME type of the sample. Cannot be combined with extension.",
        "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. Cannot be combined with mime_type. 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",
            "mime_type": "[O] The MIME type of the sample. Cannot be combined with extension.",
            "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 (например, в браузере или почтовом клиенте) на устройстве с установленным демонстрационным приложением также откроет её в демонстрационном приложении. Таким образом, размещение JSON-файла *.exolist.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 [String] Пример подсказки типа MIME. Например, application/dash+xml для содержимого DASH.
    • clip_start_position_ms [Long] Начальная точка, до которой следует обрезать сэмпл, в миллисекундах.
    • clip_end_position_ms [Long] Конечная точка, от которой следует обрезать сэмпл, в миллисекундах.
    • drm_scheme [String] Схема DRM, если она защищена. Допустимые значения: widevine , playready и clearkey . Также принимаются UUID схем DRM.
    • drm_license_uri [String] 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.
    • drm_multi_session [Логическое значение] Включает ротацию клавиш, если она защищена.
    • subtitle_uri [String] URI файла-дополнения к субтитрам.
    • subtitle_mime_type [String] MIME-тип subtitle_uri (обязательно, если subtitle_uri задан).
    • subtitle_language [String] Языковой код BCP47 файла субтитров (игнорируется, если subtitle_uri не задан).
    • ad_tag_uri [Строка] URI рекламного тега для загрузки с использованием [расширения IMA][].
    • prefer_extension_decoders [Boolean] Указывает, какие декодеры расширений предпочтительнее, чем декодеры платформы.

При использовании adb shell am start для запуска интента можно задать необязательный строковый параметр с помощью --es (например, --es extension mpd ). Необязательный логический параметр можно задать с помощью --ez (например, --ez prefer_extension_decoders TRUE ). Необязательный параметр типа long можно задать с помощью --el (например, --el clip_start_position_ms 5000 ). Необязательный параметр типа string array можно задать с помощью --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