ExoPlayerは、Googleが開発したAndroid向けのオープンソースメディアプレーヤーライブラリで、組み込みのMediaPlayerに代わるものです。ExoPlayerは、DASH、HLS、SmoothStreaming、通常のメディアファイルなど、さまざまな形式でのオーディオおよびビデオ再生を、アダプティブストリーミングをサポートする単一のAPIを通じて提供します。Google I/O(2024)によると、ExoPlayerはYouTube、Google TV、Netflixを含む6万以上のAndroidアプリケーションで使用されています。
主要ポイント
ExoPlayerは、Android向けのオープンソース(Apache 2.0)マルチメディア再生ライブラリであり、最初のバージョンは2014年にGoogleによってリリースされました。システムメディアコーデック(MediaCodec)の薄いラッパーである組み込みのMediaPlayerとは異なり、ExoPlayerはJava/Kotlinレベルで完全に実装されており、開発者は再生の各段階を完全に制御できます。
アーキテクチャ的には、ExoPlayerはモジュラー原理に基づいて構築されています。再生の各側面は個別のコンポーネントによって実装されています。コアモジュール(exoplayer-core)には、プレーヤー、レンダラー、トラックセレクター、バッファ管理が含まれます。追加モジュール(exoplayer-dash、exoplayer-hls、exoplayer-rtsp、exoplayer-smoothstreaming)は、対応するストリーミングプロトコルのサポートを追加します。このアーキテクチャにより、アプリケーションは必要なコンポーネントのみを含めることができ、APKサイズを最小限に抑えられます。
ExoPlayer 2(現在のメジャーバージョン)は2018年にリリースされ、APIの抜本的な見直しをもたらしました。Player Interfaceの導入、AndroidX Media3によるComposeサポート、改善されたエラーハンドリング、適応型トラック選択アルゴリズムなどです。バージョン2.19(2024)以降、ExoPlayerはAndroidX Mediaライブラリの一部となり、標準のAndroid依存関係マネージャーによる統合と更新が簡素化されました。
ExoPlayerの中核はExoPlayerImplコンポーネントであり、再生ライフサイクルを管理します。これにはMediaSource(メディアソース)、TrackSelector(トラック選択)、LoadControl(バッファリング管理)、Rendererのリスト(ビデオ、オーディオ、字幕、メタデータ用のレンダラー)が含まれます。各コンポーネントは、Builderまたはファクトリメソッドを通じてカスタム実装に置き換えることができます。
ビデオレンダリングには、ExoPlayerはSurfaceView、TextureView、またはSphericalSurfaceView(360度ビデオ用)を使用します。推奨されるオプションはSurfaceViewで、ハードウェアアクセラレーションと最小限の電力消費を提供します。Jetpack Composeの場合、AndroidX Media3ライブラリはSurfaceViewをラップする`AndroidView`コンポーネントと、ネイティブCompose統合を備えた実験的な`Media3Compose`を提供します。
ExoPlayerは、通常のメディアプレーヤーを超える幅広い機能を提供します。主な機能には、すべての一般的なストリーミングプロトコルのサポート、柔軟なDRMシステム、適応型ビットレート切替(ABR)、再生分析ツールが含まれます。
| 機能 | 説明 | モジュール |
|---|---|---|
| DASH | MPEG標準による適応型ストリーミング | exoplayer-dash |
| HLS | AppleのHTTP Live Streaming | exoplayer-hls |
| SmoothStreaming | Microsoftの適応型ストリーミング | exoplayer-smoothstreaming |
| RTSP | ライブ向けリアルタイムストリーミングプロトコル | exoplayer-rtsp |
| Widevine | DRMコンテンツ保護 | exoplayer-drm |
| Concatenation | 複数のメディアファイルの結合 | exoplayer-core |
| Ads | 広告のためのIMA SDK統合 | exoplayer-ima |
ExoPlayerのABR(Adaptive Bitrate)は、AdaptiveTrackSelectionインターフェースを通じて実装されています。デフォルトでは、AdaptiveTrackSelectionFactoryが使用され、ネットワーク帯域幅とバッファサイズを考慮したバランスの取れたアルゴリズムであるDefaultAdaptiveTrackSelectionを作成します。特定のシナリオでは、代替実装をプラグインできます。BOLA(切替の最小化)、RandomAdaptiveTrackSelection(テスト)、またはTrackSelectionインターフェースを通じたカスタム実装などです。
BandwidthMeter — ネットワーク帯域幅の測定を担当するもう1つの主要コンポーネント。デフォルトでは、プレーヤーのすべてのHTTPリクエストの統計を収集するDefaultBandwidthMeterが使用されます。開発者は、ネットワークタイプ(Wi-Fi、4G、5G)、携帯電話基地局の信号、ユーザーのデータコストなどの追加要素を考慮するように拡張できます。
ExoPlayerは、Widevine(L1、L3)、PlayReady、ClearKey DRMをサポートしています。ライセンス取得は、ライセンスサーバーと対話するDrmSessionManagerを通じて設定されます。プレミアムビデオ(4K HDR)には、チップレベルの保護を提供し画面キャプチャを防ぐWidevine L1のハードウェアサポートが必要です。DRMシステムの選択はターゲットプラットフォームによって異なります。WidevineはAndroidとChromecast、PlayReadyはXboxとWindows、FairPlayはiOSとApple TVで使用されます。ExoPlayerはMPDファイルに基づいて利用可能なDRMシステムを自動的に判別し、基本的なシナリオでは手動設定は必要ありません。
ExoPlayerのAndroidプロジェクトへの接続は、Gradle依存関係を通じて行われます。バージョン2.19以降、ExoPlayerはAndroidX Media(androidx.media3)の一部となり、Jetpack Composeおよび他のAndroidXコンポーネントとの互換性を確保しています。Kotlinでのステップバイステップの統合を見てみましょう。
build.gradleファイル(Module)にExoPlayerモジュールを追加します。最小セットには、core、ui、および必要なストリーミングプロトコルのモジュールが含まれます。DASHコンテンツの再生にはexoplayer-dash、HLSにはexoplayer-hlsが必要です。
dependencies {
implementation "androidx.media3:media3-exoplayer:1.5.0"
implementation "androidx.media3:media3-ui:1.5.0"
implementation "androidx.media3:media3-exoplayer-dash:1.5.0"
implementation "androidx.media3:media3-exoplayer-hls:1.5.0"
}
ActivityまたはFragmentでのプレーヤーの作成と設定。ExoPlayerはビデオと組み込みコントロールを表示するためにPlayerView(またはカスタマイズ用のStyledPlayerView)を使用します。最小構成には、ExoPlayer.Builderを介したプレーヤーの作成と、ソースURIを持つMediaItemの受け渡しが含まれます。
class PlayerActivity : AppCompatActivity() {
private var player: ExoPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player)
player = ExoPlayer.Builder(this).build()
val playerView = findViewById<StyledPlayerView>(R.id.playerView)
playerView.player = player
val mediaItem = MediaItem
.Builder()
.setUri("https://example.com/video.mp4")
.build()
player?.setMediaItem(mediaItem)
player?.prepare()
}
override fun onDestroy() {
player?.release()
super.onDestroy()
}
}
プロダクションアプリケーションでは、ネットワーク障害、サポートされていない形式、DRMライセンスエラーなど、考えられる再生エラーの処理が必要です。ExoPlayerは、onPlayerError、onPlaybackStateChanged、onPlayWhenReadyChangedメソッドを持つPlayer.Listenerインターフェースを提供します。ユーザーには、再試行オプション付きの情報的なエラーメッセージを表示することをお勧めします。
ExoPlayerと組み込みのMediaPlayerの選択は、Androidアプリケーション開発時の一般的な質問です。MediaPlayerはバージョン1.0からAndroid SDKの一部ですが、ExoPlayerはGradle依存関係を必要とするライブラリです。主要な基準に従ってそれらの違いを見てみましょう。
| 基準 | ExoPlayer | MediaPlayer |
|---|---|---|
| アーキテクチャ | モジュラー式、完全にJava/Kotlin | システムC++コンポーネントのラッパー |
| ストリーミング | DASH、HLS、SmoothStreaming、RTSP | ローカルファイルのみとHLS(Android 9+) |
| カスタマイズ | 完全(任意のコンポーネントを交換可能) | 最小限(パラメータのみ) |
| アップデート | Google PlayまたはAPK経由(OS非依存) | Androidアップデート(OTA)のみ |
| APKサイズ | +1~3 MB(モジュールによる) | 0(OSの一部) |
| 最小SDK | API 16+(Android 4.1) | API 1+ |
| DRM | Widevine、PlayReady、ClearKey | Widevine(制限付き) |
ExoPlayerが優れているのは、ストリーミング(DASH、HLS)、UIカスタマイズ、DRMサポート、Androidバージョンからの独立性が必要なシナリオです。MediaPlayerは、APKサイズが重要でアダプティブストリーミングの要件がないローカルメディアファイルを再生するシンプルなアプリケーションに適しています。ネットワークからのコンテンツを使用する最新のアプリケーションでは、ExoPlayerが明確な選択肢です。
例外 — API 16(Android 4.1)未満の最小SDKを持つアプリケーションは、市場にはほとんど存在しません。targetSdk 33+および最小SDK 21+のすべてのアプリケーションでは、ExoPlayerは推奨されるだけでなく、適切な拡張機能を通じてAV1やDolby Visionなどの最新フォーマットをサポートするために必要です。
プロダクションアプリケーションでは、ExoPlayerの基本的な統合に追加の設定がしばしば必要です。キャッシュ管理、モバイルネットワーク向けのバッファ最適化、分析との統合、オーディオトラック選択のカスタマイズなどです。高度な使用シナリオを見てみましょう。
CacheDataSourceFactoryを使用すると、ダウンロードしたセグメントをローカルストレージにキャッシュでき、繰り返し視聴時のトラフィックを節約し、オフライン再生を可能にします。ExoPlayerは、exoplayer-casライブラリのSimpleCache — LRU追出しサポートとサイズ制限付きのファイルベースキャッシュを使用します。
val cache = SimpleCache(
cacheDir,
LeastRecentlyUsedCacheEvictor(50 * 1024 * 1024),
AppDatabaseProvider(this)
)
val cacheDataSourceFactory = CacheDataSource
.Factory()
.setCache(cache)
val player = ExoPlayer.Builder(this)
.setMediaSourceFactory(
DefaultMediaSourceFactory(cacheDataSourceFactory)
)
.build()
モバイルアプリケーションでは、Wi-Fiとセルラーネットワーク間の切替の処理が重要です。ExoPlayerはネットワーク状態を追跡するためのConnectivityManagerを提供します。接続が失われた場合、プレーヤーを停止するのではなく、位置を保持したPAUSED状態にすることが推奨されます。接続が復元されたら、セグメントを再読み込みして再生を再開します。
AndroidX Media3のリリースにより、ライブラリはJetpack Composeの実験的サポートを獲得しました。`AndroidView`コンポーネントはSurfaceViewまたはPlayerViewをラップし、Compose階層との互換性を確保します。より深い統合には、`androidx.media3:media3-ui-compose`ライブラリが使用され、Compose互換のプレーヤーコントロールを提供します。
@Composable
fun VideoPlayer(uri: String) {
val context = LocalContext.current
val player = remember {
ExoPlayer.Builder(context).build()
.also { it.setMediaItem(MediaItem.fromUri(uri)) }
}
DisposableEffect(key = null) {
player.prepare()
onDispose { player.release() }
}
AndroidView(
factory = { StyledPlayerView(context).also { it.player = player } }
)
}
よくある質問
ExoPlayerはAndroid API 16+(Android 4.1 Jelly Bean)をサポートしています。ただし、fMP4セグメントを使用したDASHおよびHLSには、API 21+(Android 5.0 Lollipop)が推奨されます。DRMモジュール(Widevine)にはAPI 19+が必要で、ハードウェアHEVCデコードはAPI 21から利用可能です。
はい、ExoPlayerはオーディオに最適です。オーディオのみの再生には、SurfaceViewやPlayerViewは必要ありません。ExoPlayerは自動的にオーディオレンダラーを選択し、バックグラウンドで動作します。バックグラウンド再生には、システムコントロールとの統合のためにMediaSessionServiceを使用することをお勧めします。
ExoPlayerのTrackSelectorがオーディオトラックの選択を管理します。切り替えるには、player.getCurrentTracks().groupsと、優先オーディオ言語を指定したplayer.setTrackSelectionParameters()を使用します。複数のオーディオトラックを持つDASHおよびHLSストリームの場合、切替は再生を中断せずに行われます。
はい、ExoPlayerは埋め込み(MP4、WebMコンテナ内)および外部字幕をTTML、SRT、VTT、CEA-608形式でサポートしています。外部字幕には、ビデオストリームとマージするためにSingleSampleMediaSourceまたはMergingMediaSourceを使用します。スタイル付き字幕の表示はCaptionStyleCompatを通じて設定されます。
低遅延ストリーミングの場合は、より小さなターゲットバッファ値でLoadControlを設定します。HLS LLおよびDASH LLには、DefaultLoadControl.Builder().setTargetBufferBytes(1024 * 512).setBufferDurationsMs(500, 2000, 500, 1000)を使用します。また、ライブ配信に遅れた場合のバッファの加速充填のためにminPlaybackSpeed = 1.02を設定します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。