5. Offline Playback
Describes how to play back content that has been fully downloaded to local disk.
In offline mode, instead of using a remote URL as in online streaming playback, you pass the downloaded KollusContent instance directly to the player to start playback.
All example code in this document is based on the official sample app, kollus_player_ios.
Offline playback
Obtain the downloaded content object safely through the storage manager, then inject it as the data source for the player view to start offline playback.
1. Find downloaded content
let downloaded = StorageManager.shared.contents()
.first { $0.mediaContentKey == targetMck && $0.downloaded }
2. Attach to the player
// 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)
Full integration flow
- Obtain an object from
StorageManager.shared.contents()that matches the desired media content key and satisfies the download completion condition. - Connect the obtained
KollusContentinstance to theKollusPlayerViewobject as shown in the example code above. - During playback preparation, the SDK automatically performs local DRM verification. If the license has expired or permissions are insufficient, the player stops and notifies the state via a delegate callback or player error. (See Also: 8. Download Events/Callbacks)
Offline DRM verification conditions
To pass DRM verification in an offline environment without a network connection, all four of the following DRM security restriction conditions embedded in the downloaded file must be satisfied.
| Property | Normal condition |
|---|---|
DRMExpired | Must remain false. |
DRMExpireDate | The device's current time must be before the expiration date specified in the license. |
drmTotalExpirePlayTime / DRMExpirePlayTime | No limit (== 0) or remaining allowed playback time must be > 0. |
drmExpireCountMax / drmExpireCount | No limit (== 0) or remaining allowed playback count must be > 0. |
If any one of the above four conditions is violated, local playback will fail, and you must reconnect to the network and renew the license for normal operation. (See Also: 6. DRM License Renewal)
Handle DRM-expired content
This is the business utility logic implementation pattern adopted by the sample application to determine whether content has expired in advance.
func isExpired(_ content: KollusContent) -> Bool {
// 1. Verify forced expiration flag status
if content.DRMExpired { return true }
// 2. Verify expiration date and time
if let expire = content.DRMExpireDate, expire < Date() { return true }
// 3. Verify only when cumulative playback time limit is set (drmTotalExpirePlayTime == 0 means no limit)
if content.drmTotalExpirePlayTime > 0 && content.DRMExpirePlayTime <= 0 { return true }
// 4. Verify only when playback count limit is set (drmExpireCountMax == 0 means no limit)
if content.drmExpireCountMax > 0 && content.drmExpireCount <= 0 { return true }
return false
}
If the content is determined to be expired by the verification logic above, design the UX by choosing one of the following flows.
- Run dynamic renewal process: Immediately attempt a background renewal API call and start playback upon success.
- Notify on renewal failure: If the renewal process ultimately fails, display a license expiration popup to the user and prompt them to re-download.
Display DRM expiration renewal notification
The DRMExpireRefreshPopup property is a control flag that the SDK dynamically sets by determining whether to show the renewal popup during response communication with the console server.
If this value is received as true, it is recommended to display an explicit notification according to the guide.
if content.DRMExpireRefreshPopup {
// It is recommended to display a "Would you like to renew your license?" dialog on the user's screen.
}
Handle deleted and corrupted file exceptions
This is a safe defensive code implementation pattern for when a user arbitrarily modifies or forcibly deletes local media files.
| Situation | SDK behavior and recommended handling |
|---|---|
| File exists in the list but the actual file is missing | The SDK automatically cleans it up, so no additional handling is needed by the caller (app layer). |
| File is corrupted | A player error occurs during playback preparation and the event is notified. Display a message to the user indicating the file is defective and prompting them to re-download. |
A KollusContent object with a nil mediaContentKey is found | It may be a virtual folder (directory) node rather than an actual file. If fileType == 1, handle it as a folder view branch in the UI. |