2. ストリーミング再生
このドキュメントは機械翻訳で作成された下書きであり、現在レビュー中です。機械翻訳の特性上、一部の内容が不正確であったり、韓国語の原文と異なる場合があります。より正確な情報については、韓国語のドキュメントをご参照ください。
JWT URL を使用してコンテンツをデバイスに直接リアルタイムストリーミング再生する方法を説明します。 ローカルにダウンロードされたコンテンツの再生とは異なり、ストリーミング時には再生のたびにお客様のサーバーから新たに発行された一回限り(One-time)の URL を使用します。
このドキュメントのすべてのサンプルコードは、公式サンプルアプリ kollus_player_v2_android をもとに作成されています。
コンテンツ配信方式
Kollus サービスはチャンネル設定に応じて、3 つの配信方式のいずれかでコンテンツを提供します。
アプリケーションクライアントレイヤーでは、同じ JWT URL を受け取り setDataSourceByUrl メソッドで再生するため、別途のコード分岐を実装する必要はありません。
ただし、配信方式によって ABR の動作方式や DRM 検証・ライセンス発行フローが異なるため、インフラのチャンネル構成を把握しておくとデバッグと最適化に役立ちます。
| 配信方式 | デフォルト | 説明 | チャンネル設定 |
|---|---|---|---|
| MP4 Progressive Download | ◯ | 単一の MP4 ファイルをリアルタイムでダウンロードしながら同時に再生します。可変ビットレート(ABR)をサポートしない単一品質方式です。 | 別途設定なし(デフォルトチャンネル) |
| HLS ストリーミング | - | マニフェスト(.m3u8)とセグメントファイルで構成されます。ネットワーク帯域幅の変化に応じてリアルタイムでビットレート品質が自動切り替え(ABR)されます。 | コンソールのチャンネル設定で HLS 出力を有効化 |
| Multi DRM (Widevine/PlayReady) | - | HLS または DASH 構造に DRM セキュリティライセンス発行フローを組み合わせた形式です。Widevine L1 / L3 デバイスセキュリティレベルを検証します。 | コンソールのチャンネル設定で DRM ポリシーを登録 |
アプリケーションのソースコードでは、mMediaPlayer.setDataSourceByUrl(jwtUrl, null) メソッドを呼び出すだけで 3 つの方式すべてを再生できます。
実際のストリーミング配信方式は Kollus サーバー側がチャンネル設定に基づいて決定し、クライアントに配信します。
配信方式の詳細比較
| 比較項目 | MP4 Progressive Download | HLS ストリーミング | Multi DRM |
|---|---|---|---|
| ABR オプション制御 | 帯域幅設定の影響なし | setInitialBandwidth などの調整オプションが正常適用 | setInitialBandwidth などの調整オプションが正常適用 |
| シーク動作 | HTTP Byte-Range リクエストベースの制御 | セグメント単位の位置シーク | セグメント単位の位置シーク |
| デバイスレベル検証 | ハードウェアセキュリティ検証ステップなし | ハードウェアセキュリティ検証ステップなし | デバイスセキュリティレベル検証(Widevine L1 仕様が必須適用のコンテンツ運用が可能) |
extraDrmParam 指定 | null で渡す | null で渡す | 通常は null を指定(トークン内部の DRM ポリシーが優先。動的パラメーターが必要な特殊環境でのみ渡す) |
ほとんどのお客様はサービス初期段階で MP4 Progressive 方式から始め、トラフィックが増加する際や可変ビットレート(ABR)環境が必要な際に HLS ストリーミングに移行します。 その後、著作権保護および DRM セキュリティが必須のコンテンツに限り Multi DRM チャンネルを追加で分離して運用するパターンが一般的です。
基本ストリーミング再生
KollusPlayer SDK の MediaPlayer インスタンスにレンダリングする画面(Surface)を指定し、発行された JWT URL を設定してリアルタイムストリーミング再生を開始します。
// Example streaming implementation inside VideoView.openVideo()
mMediaPlayer.setScreenOnWhilePlaying(true);
// 1. Surface binding based on screen component type (TextureView or SurfaceView)
if (mSurfaceView instanceof TextureView) {
TextureView tv = (TextureView) mSurfaceView;
Surface surface = new Surface(tv.getSurfaceTexture());
mMediaPlayer.setSurface(surface);
} else if (mSurfaceView instanceof SurfaceView) {
mMediaPlayer.setDisplay(((SurfaceView) mSurfaceView).getHolder());
}
// 2. Set detailed ABR control options (specify if needed)
mMediaPlayer.setInitialBandwidth(0); // 0: auto-estimate initial bandwidth
mMediaPlayer.setMinDurationForQualityIncreaseMs(1000); // Minimum stable duration (ms) required before increasing ABR bitrate quality
// 3. Set data source (JWT URL)
String extraDrmParam = null;
mMediaPlayer.setDataSourceByUrl(jwtUrl, extraDrmParam); // jwtUrl example: https://v.jp.kollus.com/s?jwt=...
mMediaPlayer.prepareAsync();
prepareAsync() メソッドが呼び出されると、プレイヤー内部の状態が STATE_PREPARING に移行し、ストリーミングの初期バッファ準備が完了した時点で OnPreparedListener.onPrepared() が呼び出されます。
レンダリング Surface の設定
| 種類 | 特徴 | 推奨シナリオ |
|---|---|---|
SurfaceView | 軽量な出力パス、低い GPU 合成コスト | 一般的な全画面再生 |
TextureView | 回転・透明度・ブレンディングなど View 変換が可能 | UI 上のオーバーレイ再生、PIP など |
// SurfaceView
mMediaPlayer.setDisplay(((SurfaceView) view).getHolder());
// TextureView
Surface surface = new Surface(((TextureView) view).getSurfaceTexture());
mMediaPlayer.setSurface(surface);
DRM コンテンツのストリーミング
受け取った JWT URL 内に DRM 制約ポリシーが含まれている場合、SDK が DRM ライセンスの検証および更新プロセスを自動的に実行します。
開発レイヤーでの別途パラメーター設定なしに setDataSourceByUrl(jwtUrl, null) メソッドの呼び出しだけで DRM ストリーミングが開始されます。
アダプティブビットレート(ABR)調整オプション
ABR オプションは HLS ストリーミングおよび Multi DRM チャンネルでのみ有効です。デフォルトの MP4 Progressive Download チャンネルでは単一の固定ビットレートでメディアが配信されるため、以下の設定値はすべて無視されます。
| API | 説 明 |
|---|---|
setInitialBandwidth(bps) | 初期マニフェストロード時点の帯域幅推定値(bps)を指定します。0 を指定すると SDK が自動的に推定します。 |
setMinDurationForQualityIncreaseMs(ms) | 上位品質に切り替えるために現在の帯域幅が安定して維持される必要がある時間(ms)です。一般的な環境では 1000ms を推奨します。 |
公式サンプルアプリは、前回の再生セッションの平均ネットワーク帯域幅データを SharedPreferences に記録しておき、
次回のストリーミング初期化時に setInitialBandwidth メソッドのパラメーターとして渡すことで、初期バッファリングの待ち時間を最適化するパターンを使用しています。
プレイヤーイベントリスナー
メディア状態変化イベントおよびプレイヤー制御シグナルを受信するために、MediaPlayer インスタンスにリスナーオブジェクトを登録します。
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnInfoListener(mInfoListener);
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
mMediaPlayer.setOnTimedTextDetectListener(mOnTimedTextDetectListener);
mMediaPlayer.setOnTimedTextListener(mOnTimedTextListener);
mMediaPlayer.setOnExternalDisplayDetectListener(mOnExternalDisplayDetectListener);
mMediaPlayer.setKollusPlayerBookmarkListener(mKollusPlayerBookmarkListener);
mMediaPlayer.setCaptureDetectListener(mCaptureDetectListener);
mMediaPlayer.setEmulatorCheckerListener(mEmulatorCheckListener);
| リスナー | 役割 |
|---|---|
OnPreparedListener | ストリーミング準備完了(start() を安全に呼び出せるタイミング) |
OnCompletionListener | コンテンツ末尾まで再生完了 |
OnErrorListener | 再生中にエラー発生(what および extra コードで原因分析) |
OnInfoListener | 付随的な状態情報の変化(バッファリング開始・終了、メディア情報変更など) |
OnBufferingUpdateListener | バッファリング進捗(0〜100) |
OnSeekCompleteListener | シーク完了 |
OnVideoSizeChangedListener | 映像解像度変更 |
OnTimedTextDetectListener / OnTimedTextListener | 字幕トラック検出 / 字幕表示 |
OnExternalDisplayDetectListener | 外部ディスプレイ接続状態の変化 |
KollusPlayerBookmarkListener | ブックマーク位置情報の検出 |
CaptureDetectListener | 画面キャプチャープログラムの起動検出 |
EmulatorCheckerListener | ルート化デバイスまたは仮想マシン(エミュレーター)環境の検出 |
再生状態の制御
MediaPlayer インスタンスのメソッドを通じて、ストリーミング再生セッションのライフサイクルをリアルタイムで直接制御します。
mMediaPlayer.start(); // Start or resume playback
mMediaPlayer.pause(); // Pause
mMediaPlayer.stop(); // Stop
mMediaPlayer.seekTo(positionMs); // Move to playback position (ms)
mMediaPlayer.release(); // Release resources (required when Activity is destroyed)
boolean playing = mMediaPlayer.isPlaying(); // Whether currently playing
int currentMs = mMediaPlayer.getCurrentPosition(); // Current playback position (ms)
int durationMs = mMediaPlayer.getDuration(); // Total content duration (ms)
再生速度の制御
デコーダーの種類によって再生速度変更のサポート有無が異なるため、再生速度変更 API を呼び出す前に supportPlaybackrateControl() メソッドを呼び出してサポート有無を確認してください。
if (mMediaPlayer.supportPlaybackrateControl()) {
// Integrate playback speed change API
}
バックグラウンド再生
長時間のバックグラウンド再生を維持するには、Android コンポーネントのライフサイクルに従う Service 構造内で MediaPlayer インスタンスを管理し、フォアグラウンドサービス(Foreground Service)として実行する必要があります。
公式サンプルアプリには、このための MoviePlayerService コンポーネントを連携する実装パターンが含まれています。
バックグラウンド再生のための制御メッセージ設計
システム状態変化に安定して対応するために、以下の 2 つの設定の関係を把握して連携コードを実装する必要があります。
MoviePlayerService.APP_BACKGROUND: アプリケーションの画面レイヤーがバックグラウンド状態に移行したことをサービス側に通知するメッセージです。このメッセージを受信するだけでは再生は停止しません。KollusConstants.SUPPORT_BACKGROUND_PLAYBACK: バックグラウンド状態での再生を許可するかどうかを判定するフラグ変数です。このプロパティ値はサービスコンポーネント内部に自動的に渡されないため、アプリレイヤーで判断した後、停止メッセージを追加で送信する必要があります。
// Example implementation pattern when the UI layer transitions to the background, such as in Activity.onStop()
mMessenger.send(Message.obtain(null, MoviePlayerService.APP_BACKGROUND));
// If background playback is not permitted, explicitly send a PAUSE message
if (!supportBackgroundPlayback) {
mMessenger.send(Message.obtain(null, MoviePlayerService.PAUSE));
}
supportBackgroundPlayback 変数は KollusConstants.SUPPORT_BACKGROUND_PLAYBACK の設定値を読み込んで初期化したローカル変数です。サービスエンジンはこの値を直接参照しないため、必ず上記のコードのようにアプリレイヤーで制御する必要があります。
外部ディスプレイ出力の制限
アプリケーション実行中に HDMI ミラーリング、Chromecast、DLNA などの状態変化が発生すると、OnExternalDisplayDetectListener コールバックを通じてイベントが即座に通知されます。
セキュリティポリシーにより外部ディスプレイ出力をブロックする必要があるコンテンツの場合、リスナーコールバックがトリガーされた時点で即座にプレイヤー停止コマンドを実行するコードを適用する必要があります。