5. オフライン再生
ローカルディスクへのダウンロードが完了したコンテンツを再生する方法を説明します。
オフライン状態では、オンラインストリーミング再生で使用するリモート URL の代わりに、ダウンロードが完了したKollusContentインスタンスをプレイヤーにそのまま渡して再生を開始します。
このドキュメントのすべてのサンプルコードは、公式サンプルアプリkollus_player_iosをもとに作成されています。
オフライン再生
ストレージ管理者を通じて安全にダウンロー ド完了済みのコンテンツオブジェクトを取得した後、プレイヤービューのデータソースとして注入してオフライン再生を開始します。
1. ダウンロード完了コンテンツの検索
let downloaded = StorageManager.shared.contents()
.first { $0.mediaContentKey == targetMck && $0.downloaded }
2. プレイヤーへの接続(Attach)
// Method 1: Inject directly into the KollusPlayerView instance property
playerView.kollusContent = downloaded
// Method 2: Pass as a constructor parameter when initializing PlayerViewController
let vc = PlayerViewController(content: downloaded)
present(vc, animated: true)
全体の連携フロー
StorageManager.shared.contents()リストから、対象のメディアコンテンツキーおよびダウンロード完了条件を満たすオブジェクトを取得します。- 上記のサンプルコードのように、
KollusPlayerViewオブジェクトに取得したKollusContentインスタンスを接続します。 - 再生準備の過程で SDK がローカル DRM 検証を自動的に実行します。ライセンスが失効しているか権限がない場合はプレイヤーが停止し、デリゲートコールバックまたはプレイヤーエラーで状態を通知します。(参照: 8. ダウンロードイベント/コールバック)
オフライン DRM 検証条件
ネットワークに接続されていないオフライン環境でも DRM 検証をパスするには、ダウンロードファイル内部に組み込まれた以下の 4 つの DRM セキュリティ制限条件をすべて満たす必要があります。
| 属性 | 正常条件 |
|---|---|
DRMExpired | falseの状態を維持する必要があります。 |
DRMExpireDate | デバイスの現在時刻がライセンスに指定された失効日時より前である必要があります。 |
drmTotalExpirePlayTime / DRMExpirePlayTime | 制限なし(== 0)または残余再生許容時間が> 0である必要があります。 |
drmExpireCountMax / drmExpireCount | 制限なし(== 0)または残余再生許容回数が> 0である必要があります。 |
上記 4 つの条件のうち 1 つでも違反した場合はローカル再生が失敗し、正常動作のためには再度ネ ットワークに接続してライセンスを更新する必要があります。(参照: 6. DRM ライセンス更新)
DRM 失効コンテンツの処理
コンテンツの失効有無を事前に判別するために、サンプルアプリケーションが採用して使用しているビジネスユーティリティロジックの実装パターンです。
func isExpired(_ content: KollusContent) -> Bool {
// 1. Validate the forced expiration flag
if content.DRMExpired { return true }
// 2. Validate the expiration date
if let expire = content.DRMExpireDate, expire < Date() { return true }
// 3. Validate only if a cumulative playback time limit is set (drmTotalExpirePlayTime == 0 means no limit)
if content.drmTotalExpirePlayTime > 0 && content.DRMExpirePlayTime <= 0 { return true }
// 4. Validate only if a play count limit is set (drmExpireCountMax == 0 means no limit)
if content.drmExpireCountMax > 0 && content.drmExpireCount <= 0 { return true }
return false
}
上記の検証ロジックにより失効状態と判別された場合は、以下のフローのいずれかを選択して UX を設計します。
- 動的更新プロセスの実行: バックグラウンド更新 API を即時試行し、成功時に再生を実行します。
- 更新失敗時の例外案内: 更新プロセスが最終的に失敗した場合、ユーザーにライセンス失効ポップアップを表示して再ダウンロードを促します。
DRM 失効更新通知の表示
DRMExpireRefreshPopup属性は、SDK がコンソールサーバーと応答通信をやり取りする過程で、更新ポップアップの表示有無を動的に判別して設定する制御フラグです。
この値がtrueで受信された場合は、ガイドに従って明示的な通知を表示することを 推奨します。
if content.DRMExpireRefreshPopup {
// It is recommended to display a "Would you like to renew your license?" dialog to the user.
}
ファイル削除および破損ファイルの例外処理
ユーザーがローカルメディアファイルを任意に変更したり強制的に削除した場合の安全な防御コード実装パターンです。
| 状況 | SDK の判断および推奨処理方法 |
|---|---|
| リストには存在するが 実際のファイルがない場合 | SDK が自動的に整理するため、呼び出し元(アプリレイヤー)が別途処理する必要はありません。 |
| ファイルが破損している場合 | 再生準備の過程でプレイヤーエラーが発生してイベントで通知されます。ユーザーにファイルの不具合を案内し、再ダウンロードを促すメッセージを表示します。 |
mediaContentKeyがnilのKollusContentオブジェクトが確認される場合 | 実際のファイルではなく仮想のフォルダ(ディレクトリ)ノードである可能性があります。fileType == 1の場合は UI 上でフォルダビュー形式で例外分岐処理します。 |