- 「Cleartext HTTP traffic not allowed」エラーを解決する
- 「SSLHandshakeException」、「CertPathValidatorException」、「ERR_CERT_AUTHORITY_INVALID」のエラーの修正
- 一部のメディア ファイルがシークできないのはなぜですか?
- 一部の MP3 ファイルでシーク再生が不正確になるのはなぜですか?
- 動画のシーク動作が遅いのはなぜですか?
- 一部の MPEG-TS ファイルを再生できないのはなぜですか?
- 一部の MPEG-TS ファイルで字幕が見つからないのはなぜですか?
- 一部の MP4/FMP4 ファイルが正しく再生されないのはなぜですか?
- 一部のストリームが HTTP レスポンス コード 301 または 302 で失敗するのはなぜですか?
- 一部のストリームが UnRecognizeInputFormatException で失敗するのはなぜですか?
- 一部のデバイスで setPlaybackParameters が正しく動作しないのはなぜですか?
- 「Player is access on the wrong する場合」エラーとはどういう意味ですか?
- 「予期しないステータス ライン: ICY 200 OK」の問題を解決するにはどうすればよいですか?
- 再生中のストリームがライブ ストリームかどうかを照会するにはどうすればよいですか?
- アプリがバックグラウンドで動作しているときも音声を再生したままにするにはどうすればよいですか?
- ExoPlayer ではコンテンツがサポートされているのに、ExoPlayer キャスト ライブラリではサポートされていないのはなぜですか?
- エラーが表示されないのにコンテンツを再生できないのはなぜですか?
- デコード ライブラリを読み込んで再生に使用するにはどうすればよいですか?
- ExoPlayer で YouTube 動画を直接再生できますか?
- 動画の再生が途切れる
- 不安定な API lint エラー
「Cleartext HTTP traffic not allowed」エラーを解決する
このエラーは、アプリのネットワーク セキュリティ構成で許可されていないときに、アプリがクリアテキストの HTTP トラフィック(https://
ではなく http://
)をリクエストしたときに発生します。Android 9(API レベル 28)以降をターゲットとするアプリの場合、デフォルトの構成でクリアテキストの HTTP トラフィックが無効になっています。
アプリでクリアテキストの HTTP トラフィックを処理する必要がある場合は、それを許可するネットワーク セキュリティ構成を使用する必要があります。詳しくは、Android のネットワーク セキュリティに関するドキュメントをご覧ください。すべてのクリアテキストの HTTP トラフィックを有効にするには、アプリの AndroidManifest.xml
の application
要素に android:usesCleartextTraffic="true"
を追加するだけです。
ExoPlayer デモアプリは、デフォルトのネットワーク セキュリティ構成を使用するため、クリアテキストの HTTP トラフィックは許可されません。有効にするには、上記の手順を使用します。
「SSLHandshakeException」、「CertPathValidatorException」、「ERR_CERT_AUTHORITY_INVALID」のエラーの修正
SSLHandshakeException
、CertPathValidatorException
、ERR_CERT_AUTHORITY_INVALID
はすべて、サーバーの SSL 証明書に問題があることを示します。これらのエラーは ExoPlayer に固有のものではありません。詳しくは、Android の SSL のドキュメントをご覧ください。
一部のメディア ファイルがシークできないのはなぜですか?
デフォルトでは、ExoPlayer はメディア内でのシークをサポートしていません。この場合、正確なシーク操作は、プレーヤーがファイル全体をスキャンしてインデックスに登録することだけです。ExoPlayer は、そのようなファイルをシーク不可と見なします。最新のメディア コンテナ形式の多くは、シーク用のメタデータ(サンプル インデックスなど)を含み、明確に定義されたシーク アルゴリズム(Ogg の補間二分割検索など)があるか、コンテンツが固定ビットレートであることを示します。効率的なシーク操作が可能で、そのような場合は ExoPlayer でサポートされています。
シークする必要があるが、シークできないメディアがある場合は、より適切なコンテナ形式を使用するようにコンテンツを変換することをおすすめします。MP3、ADTS、AMR ファイルについては、こちらで説明されているように、ファイルのビットレートが固定されていることを前提としています。
一部の MP3 ファイルでシーク再生が不正確になるのはなぜですか?
可変ビットレート(VBR)MP3 ファイルは、厳密にシークする必要があるユースケースには基本的に適していません。これには次の 2 つの理由があります。
- 正確なシークを行うには、コンテナ形式で、ヘッダーで正確な時間とバイト間のマッピングを提供するのが理想的です。このマッピングにより、プレーヤーはリクエストされたシーク時間を対応するバイト オフセットにマッピングし、そのオフセットからメディアのリクエスト、解析、再生を開始できます。残念ながら、MP3 でこのマッピングの指定に使用できるヘッダー(XING ヘッダーなど)は、多くの場合、不正確です。
- 正確な時間とバイトのマッピングを提供しないコンテナ形式(またはまったく時間からバイトのマッピング)がない場合でも、コンテナのストリームに絶対サンプル タイムスタンプが含まれている場合は、正確なシークを実行できます。この場合、プレーヤーはシーク時間を対応するバイト オフセットの最適な推定値にマッピングし、そのオフセットからメディアのリクエストを開始し、最初の絶対サンプル タイムスタンプを解析し、正しいサンプルが見つかるまでガイド付きのバイナリ検索を効果的にメディアに実行できます。残念ながら MP3 ではストリームに絶対サンプルのタイムスタンプが含まれていないため、このアプローチは不可能です。
このような理由から、VBR MP3 ファイルへの正確なシークを実行する唯一の方法は、ファイル全体をスキャンし、プレーヤーで時間とバイトのマッピングを手動で構築することです。この戦略を有効にするには、FLAG_ENABLE_INDEX_SEEKING
を使用します。これは、setMp3ExtractorFlags
を使用して DefaultExtractorsFactory
で設定できます。ただし、大きな MP3 ファイルには、特にユーザーが再生開始直後のストリームの終点付近までシークしようとするとき、この場合、プレーヤーはストリーム全体がダウンロードされてインデックスに登録されるまで待機してからシークを実行する必要があります。ExoPlayer では、このケースで精度よりも速度を最適化することを決定したため、FLAG_ENABLE_INDEX_SEEKING
はデフォルトで無効になっています。
再生するメディアを操作する場合は、MP4 などのより適切なコンテナ形式を使用することを強くおすすめします。MP3 が最適なメディア形式であるというユースケースは確認されていません。
動画のシーク動作が遅い理由
プレーヤーが動画の新しい再生位置までシークする場合、次の 2 つの処理を行う必要があります。
- 新しい再生位置に対応するデータをバッファに読み込みます(このデータがすでにバッファされている場合はその必要はありません)。
- ほとんどの動画圧縮形式ではフレーム内コーディングが使用されるため、動画デコーダをフラッシュし、新しい再生位置の前の I フレーム(キーフレーム)からデコードを開始します。シークを正確にする(つまり、再生がシーク位置から正確に開始する)には、先行する I フレームとシーク位置の間のすべてのフレームをデコードし、(画面に表示されないように)直ちに破棄する必要があります。
(1)によって生じるレイテンシは、プレーヤーがメモリにバッファするデータの量を増やすか、データをディスクに事前にキャッシュすることで軽減できます。
(2)によって生じるレイテンシは、ExoPlayer.setSeekParameters
を使用してシークの精度を下げるか、I フレームを頻繁に使用するように動画を再エンコードする(出力ファイルが大きくなる)ことで軽減できます。
一部の MPEG-TS ファイルを再生できないのはなぜですか?
一部の MPEG-TS ファイルにはアクセス ユニット区切り文字(AUD)が含まれていません。デフォルトでは、ExoPlayer は AUD を利用してフレーム境界を低コストで検出します。同様に、一部の MPEG-TS ファイルには IDR キーフレームが含まれていません。デフォルトでは、ExoPlayer が考慮するキーフレームのタイプはこれらのみです。
AUD または IDR キーフレームのない MPEG-TS ファイルの再生を求められた場合、ExoPlayer がバッファリング状態で停止しているように見えます。このようなファイルを再生する必要がある場合は、それぞれ FLAG_DETECT_ACCESS_UNITS
と FLAG_ALLOW_NON_IDR_KEYFRAMES
を使用します。これらのフラグは、setTsExtractorFlags
を使用して DefaultExtractorsFactory
に設定するか、コンストラクタを使用して DefaultHlsExtractorFactory
に設定できます。FLAG_DETECT_ACCESS_UNITS
の使用には、AUD ベースのフレーム境界検出と比較して計算コストが高い以外、副作用はありません。FLAG_ALLOW_NON_IDR_KEYFRAMES
を使用すると、一部の MPEG-TS ファイルの再生開始時とシーク直後の映像が一時的に破損することがあります。
一部の MPEG-TS ファイルで字幕が見つからないのはなぜですか?
一部の MPEG-TS ファイルには CEA-608 トラックが含まれていますが、コンテナ メタデータでは宣言されないため、ExoPlayer は検出できません。期待される字幕形式のリスト(MPEG-TS ストリーム内での識別に使用できるユーザー補助チャンネルを含む)のリストを DefaultExtractorsFactory
に渡すことで、字幕トラックを手動で指定できます。
Kotlin
val extractorsFactory = DefaultExtractorsFactory() .setTsSubtitleFormats( listOf( Format.Builder() .setSampleMimeType(MimeTypes.APPLICATION_CEA608) .setAccessibilityChannel(accessibilityChannel) // Set other subtitle format info, such as language. .build() ) ) val player: Player = ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, extractorsFactory)).build()
Java
DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory() .setTsSubtitleFormats( ImmutableList.of( new Format.Builder() .setSampleMimeType(MimeTypes.APPLICATION_CEA608) .setAccessibilityChannel(accessibilityChannel) // Set other subtitle format info, such as language. .build())); Player player = new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, extractorsFactory)) .build();
一部の MP4/FMP4 ファイルが正しく再生されないのはなぜですか?
一部の MP4/FMP4 ファイルには、サンプルのリストをスキップ、移動、繰り返してメディア タイムラインを書き換える編集リストが含まれています。ExoPlayer は、編集リストの適用を部分的にサポートしています。たとえば、同期サンプルで開始するサンプルのグループを遅らせたり繰り返すことはできますが、同期サンプルで開始しない編集で音声サンプルやプリロール メディアは切り捨てられません。
メディアの該当部分が予期せず欠落しているか、繰り返されている場合は、Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
または FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
を設定してみてください。設定すると、エクストラクタは編集リストを完全に無視します。これらは、setMp4ExtractorFlags
または setFragmentedMp4ExtractorFlags
を使用して DefaultExtractorsFactory
に設定できます。
一部のストリームが HTTP レスポンス コード 301 または 302 で失敗するのはなぜですか?
HTTP レスポンス コード 301 と 302 はどちらもリダイレクトを示します。簡単な説明については、ウィキペディアをご覧ください。ExoPlayer がリクエストを行い、ステータス コード 301 または 302 のレスポンスを受信すると、通常はリダイレクトに従い、通常どおり再生を開始します。クロスプロトコル リダイレクトでは、この状況がデフォルトで発生しません。プロトコル間のリダイレクトとは、HTTPS から HTTP へ、またはその逆のリダイレクトです(別のプロトコルペア間で行われることはあまり一般的ではありません)。次のように wget コマンドライン ツールを使用して、URL がプロトコルをまたいだリダイレクトを引き起こすかどうかをテストできます。
wget "https://yourserver.com/test.mp3" 2>&1 | grep Location
出力は次のようになります。
Location: https://second.com/test.mp3 [following]
Location: http://third.com/test.mp3 [following]
この例では、2 つのリダイレクトを行います。最初のリダイレクトは https://yourserver.com/test.mp3
から https://second.com/test.mp3
です。どちらも HTTPS であるため、これはクロスプロトコル リダイレクトではありません。2 つ目のリダイレクトは https://second.com/test.mp3
から http://third.com/test.mp3
です。これは HTTPS から HTTP にリダイレクトするため、プロトコルをまたいだリダイレクトを行います。ExoPlayer は、デフォルト構成でこのリダイレクトに従わないため、再生は失敗します。
必要に応じて、アプリケーションで使用される DefaultHttpDataSource.Factory
インスタンスをインスタンス化する際に、クロスプロトコル リダイレクトに従うように ExoPlayer を構成できます。ネットワーク スタックの選択と構成については、こちらをご覧ください。
一部のストリームが UnRecognizeInputFormatException で失敗するのはなぜですか?
この質問は、次の形式の再生エラーに関するものです。
UnrecognizedInputFormatException: None of the available extractors
(MatroskaExtractor, FragmentedMp4Extractor, ...) could read the stream.
このエラーには、次の 2 つの原因が考えられます。最もよくある原因は、DASH(mpd)、HLS(m3u8)、SmoothStreaming(ism、isml)コンテンツを再生しようとしたときに、プレーヤーがプログレッシブ ストリームとして再生しようとしていることです。このようなストリームを再生するには、それぞれの ExoPlayer モジュールに依存する必要があります。ストリーム URI が標準のファイル拡張子で終わっていない場合は、MimeTypes.APPLICATION_MPD
、MimeTypes.APPLICATION_M3U8
、または MimeTypes.APPLICATION_SS
を MediaItem.Builder
の setMimeType
に渡して、ストリームのタイプを明示的に指定することもできます。
あまり一般的ではありませんが、2 つ目の原因は、再生しようとしているメディアのコンテナ形式を ExoPlayer がサポートしていないことです。この場合、エラーは意図したとおりに機能していますが、コンテナ形式やテスト ストリームの詳細など、機能リクエストを Issue Tracker にお送りください。 新しい機能リクエストを送信する前に、既存の機能リクエストを検索してください。
setPlaybackParameters が一部のデバイスで正しく動作しないのはなぜですか?
Android M 以前でアプリのデバッグビルドを実行すると、setPlaybackParameters
API を使用すると、パフォーマンスの低下、アーティファクトの可聴性、CPU 使用率が高くなることがあります。これは、この API にとって重要な最適化が、これらのバージョンの Android で実行されるデバッグビルドでは無効になっているためです。
この問題はデバッグビルドにのみ影響することに注意してください。最適化が常に有効になっているリリースビルドには影響しません。したがって、エンドユーザーに提供するリリースは、この問題の影響を受けません。
「Player is access on the wrong する場合」エラーとはどういう意味ですか?
スタートガイドのスレッドに関する注意事項をご覧ください。
「予期しないステータス ライン: ICY 200 OK」の問題を解決するにはどうすればよいですか?
この問題は、サーバーのレスポンスに HTTP 準拠ではなく ICY ステータス行が含まれている場合に発生します。ICY ステータス行は非推奨であり、使用しないでください。サーバーを管理している場合は、HTTP 準拠のレスポンスを提供するようにサーバーを更新する必要があります。それができない場合は、ExoPlayer OkHttp ライブラリを使用すると ICY ステータス行を正しく処理できるため、問題を解決できます。
再生中のストリームがライブ ストリームかどうかを照会するにはどうすればよいですか?
プレーヤーの isCurrentWindowLive
メソッドをクエリできます。さらに、isCurrentWindowDynamic
をチェックすると、ウィンドウが動的である(つまり、時間の経過とともに更新されている)かどうかを確認できます。
アプリがバックグラウンドで動作しているときも音声を再生したままにするにはどうすればよいですか?
アプリがバックグラウンドで動作しているときも音声が再生され続けるようにするには、次の手順を行います。
- フォアグラウンド サービスが実行されている必要があります。これにより、リソースを解放するためにシステムがプロセスを強制終了するのを防ぐことができます。
WifiLock
とWakeLock
を保持する必要があります。これにより、システムは Wi-Fi 無線と CPU を動作させたままにします。これは、ExoPlayer
を使用してsetWakeMode
を呼び出すことによって簡単に行えます。これにより、必要なロックが適切なタイミングで自動的に取得および解放されます。
音声が再生されなくなったらすぐにロックを解除し(setWakeMode
を使用していない場合)、サービスを停止することが重要です。
ExoPlayer ではコンテンツがサポートされているのに、ExoPlayer キャスト ライブラリではサポートされていないのはなぜですか?
再生しようとしているコンテンツが CORS 対応でないことが考えられます。キャスト フレームワークでコンテンツを再生するには、CORS を有効にする必要があります。
コンテンツを再生できないのにエラーが表示されないのはなぜですか?
コンテンツを再生しているデバイスが、特定のメディア サンプル形式をサポートしていない可能性があります。これは、プレーヤーにリスナーとして EventLogger
を追加し、Logcat で次のような行を探すことで簡単に確認できます。
[ ] Track:x, id=x, mimeType=mime/type, ... , supported=NO_UNSUPPORTED_TYPE
NO_UNSUPPORTED_TYPE
は、デバイスが mimeType
で指定されたメディア サンプル形式をデコードできないことを意味します。サポートされているサンプル形式については、Android メディア形式のドキュメントをご覧ください。デコード ライブラリを読み込んで再生に使用するにはどうすればよいですか?も役に立ちます。
デコード ライブラリを読み込んで再生に使用するにはどうすればよいですか?
- ほとんどのデコーダ ライブラリには、依存関係をチェックアウトしてビルドするための手動の手順が用意されているため、関連ライブラリの README に記載されている手順を実施してください。たとえば、ExoPlayer FFmpeg ライブラリでは、libraries/decoder_ffmpeg/README.md の手順に沿って、再生する任意の形式のデコーダを有効にするための構成フラグを渡すなどを行う必要があります。
- ネイティブ コードを含むライブラリの場合、README で指定されている正しいバージョンの Android NDK を使用していることを確認し、構成中およびビルド時に表示されるエラーに注意してください。README の手順に沿って操作すると、サポートされているアーキテクチャごとに、ライブラリのパスの
libs
サブディレクトリに.so
ファイルが表示されます。 - デモ アプリケーションのライブラリを使用して再生を試すには、バンドルされたデコーダを有効にするをご覧ください。独自のアプリからライブラリを使用する手順については、ライブラリの README をご覧ください。
DefaultRenderersFactory
を使用している場合、デコーダが読み込まれると Logcat に「Loaded FfmpegAudioRenderer」のような情報レベルのログ行が表示されます。この属性がない場合は、アプリがデコード ライブラリに依存していることを確認してください。LibraryLoader
からの警告レベルのログが Logcat に表示される場合は、ライブラリのネイティブ コンポーネントの読み込みに失敗したことを示します。その場合は、ライブラリの README の手順に正しく従ったことと、手順に沿って操作してもエラーが出力されていないことを確認してください。
デコード ライブラリの使用で引き続き問題が発生する場合は、Media3 の Issue Tracker で関連する最近の問題について確認してください。新しい問題を報告する必要があり、それがライブラリのネイティブ部分のビルドに関連している場合は、問題を診断できるように、README 手順の実行によるコマンドライン出力全体を含めてください。
ExoPlayer で YouTube 動画を直接再生できますか?
いいえ。ExoPlayer は YouTube の動画(https://www.youtube.com/watch?v=...
の形式の URL など)を再生できません。代わりに、Android で YouTube 動画を再生するための正式な方法である YouTube IFrame Player API を使用してください。
動画の再生が途切れる
たとえば、コンテンツのビットレートや解像度がデバイスの能力を超えている場合、デバイスでコンテンツを十分な速さでデコードできないことがあります。このようなデバイスで良好なパフォーマンスを得るには、低品質のコンテンツの使用が必要になる場合があります。
Android 6.0(API レベル 23)から Android 11(API レベル 30)までのバージョンの Android を搭載したデバイスで、特に DRM で保護されたコンテンツや高フレームレートのコンテンツを再生する場合に、非同期バッファキューイングを有効にする方法をお試しください。
不安定な API lint エラー
Media3 は、API サーフェスのサブセットのバイナリ互換性を保証します。バイナリ互換性を保証しない部分は、@UnstableApi
でマークされます。この区別を明確にするために、不安定な API シンボルの使用は、@OptIn
アノテーションが付いていない限り、lint エラーを生成します。
@UnstableApi
アノテーションは、API の品質やパフォーマンスに関するものではなく、「API フリーズ」ではないという事実のみを意味しています。
不安定な API lint エラーを処理する方法は 2 つあります。
- 安定した API に切り替えて同じ結果を得る。
- 引き続き不安定な API を使用し、後で示すように、使用状況に
@OptIn
アノテーションを付けます。
@OptIn
アノテーションを追加する
Android Studio では、次のようにアノテーションを追加できます。
Kotlin では、特定の使用場所に手動でアノテーションを付けることもできます。
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
@OptIn(UnstableApi::class)
fun functionUsingUnstableApi() { ... }
Java の場合は次のようになります。
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
@OptIn(markerClass = UnstableApi.class)
private void methodUsingUnstableApis() { ... }
パッケージ全体をオプトインするには、package-info.java
ファイルを追加します。
@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
プロジェクト全体をオプトインするには、lint.xml
ファイルで特定の lint エラーを抑制します。
<?xml version="1.0" encoding="utf-8"?>
<lint>
<issue id="UnsafeOptInUsageError">
<option name="opt-in" value="androidx.media3.common.util.UnstableApi" />
</issue>
</lint>
使用すべきでない kotlin.OptIn
アノテーションもあります。androidx.annotation.OptIn
アノテーションを使用することが重要です。