skip to Main Content

When using AVPlayer,

the only way I know to detect the end of a video being reached,

is to use the notification, just as you would when detecting the end of a video from the view controller. Eg,

class FancyAVPlayer: AVQueuePlayer {
    
    override init() {
        super.init()
        NotificationCenter.default.addObserver(self,
           selector: #selector(innerEnd),
           name: .AVPlayerItemDidPlayToEndTime, object: nil)
    }
    
    @objc func innerEnd() {
        print("AVPlayer subclass, tape ended")
    }

    override func insert ..etc
    override func remove ..etc
}

I have always wondered, there must be a more sensible way to do this, by overriding something in AVPlayer.

Has anyone solved this issue?

2

Answers


  1. Unfortunately, no.

    In AVFoundation, the notification AVPlayerItemDidPlayToEndTime is indeed the common and recommended way to detect when a video playback has reached its end.

    Overriding methods in AVPlayer or AVQueuePlayer to detect the end of playback without using Key-Value Observing (KVO) or notifications isn’t supported directly by the API.

    Login or Signup to reply.
  2. you can build one for yourself:

    class CustomPlayerItem: AVPlayerItem {
        override init(asset: AVAsset, automaticallyLoadedAssetKeys: [String]?) {
            super.init(asset: asset, automaticallyLoadedAssetKeys: automaticallyLoadedAssetKeys)
            NotificationCenter.default.addObserver(
                self,
                selector: #selector(didFinishPlay),
                name: Self.didPlayToEndTimeNotification,
                object: self
            )
        }
    
        @objc func didFinishPlay(_ notification: Notification) {
            print(#function) /* Perfotm actions here */
        }
    }
    

    You can go further and pass the action from outside like:

    class CustomPlayerItem: AVPlayerItem {
        func addFinishAction(on queue: OperationQueue? = nil, action: @escaping (Notification) -> Void)  {
            NotificationCenter.default.addObserver(
                forName: Self.didPlayToEndTimeNotification,
                object: self,
                queue: queue,
                using: action
            )
        }
    }
    

    So you can add the action from the outside like:

    let item = CustomPlayerItem(url: playerItemURL)
    item.addFinishAction { notification in
        print(notification) /* Perfotm actions here */
    }
    let player = AVPlayer(playerItem: item)
    

    ⚠️ Don’t forget to remove observers when you done. For example you can do something like:

    class CustomPlayerItem: AVPlayerItem {
        ,,,
    
        deinit {
            NotificationCenter.default.removeObserver(self)
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search