# [HowTo] Video as Background with AVFoundation

AVPlayer and AVPlayerLayer to create a video background

AVFoundation is the full featured framework for working with time-based audiovisual media on iOS, macOS, watchOS and tvOS. Using AVFoundation, you can easily play, create, and edit QuickTime movies and MPEG-4 files, play HLS streams, and build powerful media functionality into your apps.

import AVFoundation
import Combine

...

//MARK: - Properties

private var player: AVPlayer?
private var playerLayer: AVPlayerLayer?
private let notificationCenter = NotificationCenter.default
private var appEventSubsribers = [AnyCancellable]()

...

//MARK: - Life Cycle

override func viewWillAppear(_ animated: Bool) {
    observeAppEvents()
    setupPlayerIfNeeded()
    restartVideo()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    removeAppEventsSubscribers()
    removePlayer()
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    playerLayer?.frame = view.bounds
}

...

//MARK: - Helpers

private func buildPlayer() -> AVPlayer? {
    guard let filePath = Bundle.main.path(forResource: "bg_video", ofType: "mp4") else { return nil }
    let url = URL(fileURLWithPath: filePath)
    let player = AVPlayer(url: url)
    player.actionAtItemEnd = .none
    player.isMuted = true
    return player
}

private func buildPlayerLayer() -> AVPlayerLayer? {
    let layer = AVPlayerLayer(player: player)
    layer.videoGravity = .resizeAspectFill
    return layer
}

private func playVideo() {
    player?.play()
}

private func restartVideo() {
    player?.seek(to: .zero)
    playVideo()
}

private func pauseVideo() {
    player?.pause()
}

private func setupPlayerIfNeeded() {
    player = buildPlayer()
    playerLayer = buildPlayerLayer()
    
    if let layer = self.playerLayer,
        view.layer.sublayers?.contains(layer) == false {
            view.layer.insertSublayer(layer, at: 0)
        }
        
}

private func observeAppEvents() {
    
    notificationCenter.publisher(for: .AVPlayerItemDidPlayToEndTime).sink { [weak self] _ in
        self?.restartVideo()
    }.store(in: &appEventSubsribers)
    
    notificationCenter.publisher(for: UIApplication.willResignActiveNotification).sink { [weak self] _ in
        self?.pauseVideo()
    }.store(in: &appEventSubsribers)
    
    notificationCenter.publisher(for: UIApplication.didBecomeActiveNotification).sink { [weak self] _ in
        self?.playVideo()
    }.store(in: &appEventSubsribers)
}

private func removeAppEventsSubscribers() {
    appEventSubsribers.forEach { subscriber in
        subscriber.cancel()
    }
}

private func removePlayer() {
    player?.pause()
    player = nil
    
    playerLayer?.removeFromSuperlayer()
    playerLayer = nil
}

# References

Apple Developer Document (opens new window)