Getting started guide

Create AVDoris player

let player = AVPlayer()
let playerViewController = AVPlayerViewController()
playerViewController.player = player
let config = AVDorisConfig(uiType: .native(playerViewController: playerViewController), playerConfig: .default, adsConfig: nil)
let avDoris = AVDorisFactory.create(player: player, config: config, output: self)

Load a stream with URL

let source = DorisSource(type: .url(URL(string: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!))
avDoris.load(source: source)

Take control

avDoris.play()
avDoris.pause()
avDoris.seek(.position(50, isAccurate: false)) //seek to 00:50
avDoris.seek(.offset(10, isAccurate: false)) //add +10 sec to current time
avDoris.unload() //replace current player item with nil

Listen for Player Events

extension ViewController: DorisPlayerOutputProtocol {
    func onPlayerEvent(_ event: AVDoris.DorisPlayerEvent) {
        switch event {
        case .currentTimeChanged(let contentPosition, let streamPosition, let date): break
        case .itemDurationChanged(let contentDuration, let streamDuration): break
        case .streamTypeRecognized(let streamType): break
        case .seekableTimeRangesChanged(let contentSeekableRanges, let streamSeekableRanges): break
        case .readyToPlay: break
        default: break
        }
    }
}

All possible events with more details about associated values can be found here DorisPlayerEvent

Rely on player states

AVDoris provides simple meaningfull states for AVPlayer

extension ViewController: DorisPlayerOutputProtocol {
    func onPlayerStateChanged(old: AVDoris.DorisPlayerState, new: AVDoris.DorisPlayerState) {
        switch new {
        case .buffering: break
        case .failed: break
        case .initialization: break
        case .loaded: break
        case .loading: break
        case .paused: break
        case .playing: break
        case .waitingForNetwork: break
        @unknown default: break
        }
    }
}

Configure lock screen controls

//update NowPlayingInfo
let metadata = DorisPlayerMediaMetadata(
    title: "Title",
    artist: "Artist",
    albumTitle: "album",
    image: nil,
    remoteImageUrl: URL(string: "https://via.placeholder.com/300x200"))

avDoris.updateMetadata(metadata)

Note

In case of using native UI(AVPlayerViewController) make sure you set AVPlayerViewController.updatesNowPlayingInfoCenter = false to avoid system override DorisPlayerMediaMetadata

Configure lock screen playback controls (MPRemoteCommandCenter)
var lockScreenConfig = DorisRemoteCommandsConfig()
lockScreenConfig.isPlayEnabled = true
lockScreenConfig.isPauseEnabled = true
lockScreenConfig.isPlayPauseEnabled = true
lockScreenConfig.isSkipBackwardEnabled = true
lockScreenConfig.isSkipForwardEnabled = true
lockScreenConfig.isChangePositionEnabled = false

avDoris.updateRemoteCommands(with: lockScreenConfig)
//avDoris.updateRemoteCommands(with: .default)
Listen to lock screen playback controls events
extension ViewController: DorisPlayerOutputProtocol {
    func onRemoteCommandEvent(_ event: AVDoris.DorisRemoteCommandEvent) {
        switch event {
        case .play: break
        case .pause: break
        case .playPause: break
        case .stop: break
        case .skipBackward(let value): break
        case .skipForward(let value): break
        case .previousTrack: break
        case .nextTrack: break
        case .changePosition(let value): break
        @unknown default: break
        }
    }
}
Changing subtitles/audiotracks
var allSubtitles = [DorisMediaSelection]()
var allAudioTracks = [DorisMediaSelection]()

extension ViewController: DorisPlayerOutputProtocol {
    func onPlayerEvent(_ event: AVDoris.DorisPlayerEvent) {
        switch event {
        case .availableMediaSelectionLoaded(let subtitles, let audioTracks):
            allSubtitles = subtitles
            allAudioTracks = audioTracks
        default: break
        }
    }

    func someUIEvent() {
        for subtitle in allSubtitles {
            switch subtitle {
            case .option(let title, let languageCode, let isDefault):
                if languageCode == "eng" {
                    avDoris?.selectSubtitles(code: languageCode)
//                    avDoris?.selectSubtitles(title: title)
                }
            case .empty: break
            @unknown default: break
            }
        }
        for audioTrack in allAudioTracks {
            switch audioTrack {
            case .option(let title, let languageCode, let isDefault):
                if languageCode == "eng" {
                    avDoris?.selectAudioTrack(code: languageCode)
//                    avDoris?.selectAudioTrack(title: title)
                }
            case .empty: break
            @unknown default: break
            }
        }
    }
}
Picture in Picture(PIP)

AVDoris provides picture in picture mode for the player with custom UI, player will switch to picture in picture mode when your app is backgrounded

Note

you can disable defult behaviour with toggle avDoris.allowsPictureInPicturePlayback = false Note: this is only available starting from iOS 14 Note: this is only available with custom UI

Doris