Aplicativo de demonstração do ExoPlayer

O principal app de demonstração do ExoPlayer tem dois propósitos principais:

  1. Para fornecer um exemplo relativamente simples, mas completo, do uso do ExoPlayer. O app de demonstração pode ser usado como um ponto de partida conveniente para desenvolver seu próprio app.
  2. Para facilitar o teste do ExoPlayer. O app de demonstração pode ser usado para testar a reprodução do seu próprio conteúdo, além dos exemplos incluídos.

Esta página descreve como instalar, compilar e executar o app de demonstração, além de descrever como usá-lo para reproduzir sua própria mídia.

Buscar o código

O código-fonte do app de demonstração principal pode ser encontrado na pasta demos/main do nosso projeto do GitHub. Clone o projeto em um diretório local, caso ainda não tenha feito isso:

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

Em seguida, abra o projeto no Android Studio. Você vai ver o seguinte na visualização Android Project. As pastas relevantes do app de demonstração foram expandidas:

O projeto no Android Studio

Compilação e execução

Para compilar e executar o app de demonstração, selecione e execute a configuração demo no Android Studio. O app de demonstração será instalado e executado em um dispositivo Android conectado. Recomendamos o uso de um dispositivo físico, se possível. Se você quiser usar um emulador, leia a seção de emuladores em Dispositivos com suporte e confira se o dispositivo virtual usa uma imagem do sistema com um nível de API de pelo menos 23.

SampleChooserActivity e PlayerActivity

O app de demonstração apresenta uma lista de amostras (SampleChooserActivity). Selecionar um exemplo abrirá uma segunda atividade (PlayerActivity) para reprodução. A demonstração apresenta controles de mídia e a funcionalidade de seleção de faixas. Ela também usa a classe de utilitário EventLogger do ExoPlayer para gerar informações de depuração úteis para o registro do sistema. Essa geração de registros pode ser exibida (junto com a geração de registros de nível de erro para outras tags) com o comando:

adb logcat EventLogger:V *:E

Como ativar decodificadores agrupados

O ExoPlayer tem várias extensões que permitem o uso de decodificadores de software em pacote, incluindo AV1, VP9, Opus, FLAC e FFmpeg (somente áudio). O app de demonstração pode ser criado para incluir e usar essas extensões da seguinte maneira:

  1. Crie cada uma das extensões que você quer incluir. Observe que esse é um processo manual. Consulte o arquivo README.md em cada extensão para ver as instruções.
  2. Na visualização "Build Variants" do Android Studio, defina a variante de build do módulo de demonstração como withDecoderExtensionsDebug ou withDecoderExtensionsRelease, conforme mostrado na imagem abaixo.

    Como selecionar a variante de build de demonstração "withDecoderExtensionsDebug"

  3. Compile, instale e execute a configuração demo normalmente.

Por padrão, um decodificador de extensão será usado somente se não houver um decodificador de plataforma adequado. É possível especificar que os decodificadores de extensão sejam preferidos, conforme descrito nas seções a seguir.

Como abrir seu próprio conteúdo

Existem várias maneiras de reproduzir seu conteúdo no app de demonstração.

1. Como editar assets/media.exolist.json

Os exemplos listados no app de demonstração são carregados de assets/media.exolist.json. Ao editar esse arquivo JSON, é possível adicionar e remover exemplos do app de demonstração. O esquema é o seguinte, em que [O] indica um atributo opcional.

[
  {
    "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
]

As playlists de amostras podem ser especificadas usando o esquema:

[
  {
    "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
]

Se necessário, os cabeçalhos de solicitação de chave são especificados como um objeto que contém um atributo de string para cada cabeçalho:

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

Na atividade do seletor de amostra, o menu flutuante contém opções para especificar se você prefere decodificadores de extensão.

URIs de arquivos locais e restrições de armazenamento com escopo

Ao especificar URIs de arquivos locais, o app de demonstração solicita as permissões de acesso ao armazenamento necessárias para ler esses arquivos. No entanto, no Android 13, não é possível carregar arquivos arbitrários que não terminem em uma extensão típica de arquivo de mídia (como .mp4). Se você precisar carregar esse arquivo, é possível colocá-lo no diretório de armazenamento específico do app de demonstração que não tem restrições de acesso. Normalmente, ela fica localizada em /sdcard/Android/data/androidx.media3.demo.main/files.

2. Como carregar um arquivo exolist.json externo

O app de demonstração pode carregar arquivos JSON externos usando o esquema acima e nomeados de acordo com a convenção *.exolist.json. Por exemplo, se você hospedar esse arquivo em https://yourdomain.com/samples.exolist.json, poderá abri-lo no app de demonstração usando:

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

Ao clicar em um link *.exolist.json (por exemplo, no navegador ou em um cliente de e-mail) em um dispositivo com o app de demonstração instalado, ele também será aberto no app de demonstração. Portanto, hospedar um arquivo JSON *.exolist.json oferece uma maneira simples de distribuir conteúdo para outras pessoas testarem no app.

3. Como disparar uma intent

As intents podem ser usadas para ignorar a lista de amostras e iniciar diretamente na reprodução. Para reproduzir uma única amostra, defina a ação da intent como androidx.media3.demo.main.action.VIEW e o URI de dados dela como a da amostra a ser reproduzida. Essa intent pode ser acionada a partir do terminal usando:

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

Os extras opcionais com suporte para uma única intent de exemplo são:

  • Exemplo de extras de configuração:
    • mime_type [String] Exemplo de dica de tipo MIME. Por exemplo, application/dash+xml para conteúdo DASH.
    • clip_start_position_ms [longo] Um ponto de início em que a amostra será recortada, em milissegundos.
    • clip_end_position_ms [Long] Um ponto final em que a amostra precisa ser recortada, em milissegundos.
    • drm_scheme [String] Esquema de DRM se protegido. Os valores válidos são widevine, playready e clearkey. UUIDs de esquema de DRM também são aceitos.
    • drm_license_uri [String] URI do servidor de licenças, se estiver protegido.
    • drm_force_default_license_uri [booleano] Define se o uso de drm_license_uri será forçado para solicitações de chave que incluem o próprio URI de licença.
    • drm_key_request_properties [Matriz de strings] Cabeçalhos de solicitação de chave compactados como name1, value1, name2, value2 etc. se estiverem protegidos.
    • drm_session_for_clear_content [booleano] Se uma sessão de DRM será anexada para limpar faixas de vídeo e áudio.
    • drm_multi_session [Booleano] Ativa a rotação de chaves se estiver protegida.
    • subtitle_uri [String] O URI de um arquivo secundário de legenda.
    • subtitle_mime_type [String] O tipo MIME de subtitle_uri (obrigatório se subtitle_uri estiver definido).
    • subtitle_language [String] O código de idioma BCP47 do arquivo de legenda (ignorado se subtitle_uri não estiver definido).
    • ad_tag_uri [String] O URI de uma tag de anúncio a ser carregada usando a [extensão do IMA][].
    • prefer_extension_decoders [booleano] se os decodificadores de extensão são preferidos em relação aos da plataforma.

Ao usar adb shell am start para disparar uma intent, um extra de string opcional pode ser definido com --es (por exemplo, --es extension mpd). Um booleano extra opcional pode ser definido com --ez (por exemplo, --ez prefer_extension_decoders TRUE). Um extra longo opcional pode ser definido com --el (por exemplo, --el clip_start_position_ms 5000). Um extra de matriz de string opcional pode ser definido com --esa (por exemplo, --esa drm_key_request_properties name1,value1).

Para reproduzir uma playlist de amostras, defina a ação da intent como androidx.media3.demo.main.action.VIEW_LIST. Os extras de configuração de exemplo permanecem os mesmos de androidx.media3.demo.main.action.VIEW, exceto por duas diferenças:

  • As chaves dos extras precisam ter um sublinhado e o índice baseado em 0 da amostra como sufixo. Por exemplo, extension_0 indicaria o tipo de amostra para a primeira amostra. drm_scheme_1 definiria o esquema de DRM para a segunda amostra.
  • O URI da amostra é transmitido como um extra com a chave uri_<sample-index>.

Os outros extras, que não dependem de amostra, não mudam. Por exemplo, você pode executar o seguinte comando no terminal para reproduzir uma playlist com dois itens, substituindo a extensão do segundo item:

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