top of page
Matt

Creating a Video Background View Controller in Swift for iOS: A Step-by-Step Guide

Updated: Feb 19

In this tutorial we will show how to create a ViewController in iOS swift, that has a video background playing on repeat.


Contents


The below example shows a simple Menu with a looping background video of a Tokyo night scene:




Pros & Cons

First let's explore why we would want to do this, but if you want to go straight to the code, click [here]


Pros

  • Aesthetic Appeal: Video backgrounds can make an app look more dynamic and engaging, enhancing the visual experience for users.

  • Brand Expression: They can be an effective way to convey a brand's identity or to create a specific atmosphere within the app.

  • User Engagement: A well-chosen video can increase user interest and engagement, potentially leading to longer session times.

  • Storytelling: Videos can be used to tell a story or convey information in a more immersive way than static images or text.

  • Contextual Information: In some cases, video backgrounds can provide useful context or information related to the app's content or functionality.


Cons

  • Performance Impact: Video playback can be resource-intensive, potentially leading to increased battery consumption and decreased app performance.

  • Increased App Size: Including video files can significantly increase the size of your app, which might be a concern for users with limited storage space.

  • Distraction: If not used carefully, video backgrounds can be distracting to users, making it hard for them to focus on important content or functionalities.

  • Data Usage: If the video is streamed or downloaded from the internet, it can consume a significant amount of data, which might not be ideal for users with limited data plans.

  • Accessibility Issues: Videos, especially those with flashing or quick-moving elements, can be problematic for users with certain disabilities or sensitivities.

  • Load Times: Incorporating video might increase the loading time of the view controller, especially if the video is not optimised for mobile use.


Best Practices

  • Ensure that the video is properly optimized for mobile devices to minimize performance and loading issues.

  • Consider offering an option to disable the video background for users who prefer a simpler interface or need to conserve battery/data.

  • Be mindful of accessibility guidelines, such as providing alternative content for users who cannot consume video content.

  • Keep the video content relevant to the app's purpose and ensure it enhances rather than detracts from the user experience.


In summary, while video backgrounds can be visually striking and engaging, it's important to balance these benefits with the potential drawbacks regarding performance, accessibility, and user experience.


Step by Step VideoViewController

1. Import Necessary Frameworks

import UIKit
import AVKit
import AVFoundation

You start by importing the necessary frameworks:

  • UIKit: This is the fundamental framework for building the iOS interface.

  • AVKit and AVFoundation: These are used for handling audio-visual media, which is essential for playing video.


2. Define the VideoViewController Class

class VideoViewController: UIViewController {
    var videoName: String

Here, you're defining a new class VideoViewController which inherits from UIViewController. You also declare a variable videoName to hold the name of the video file.


3. Define Properties for Video Playback

fileprivate var queuePlayer: AVQueuePlayer?
fileprivate var playerLayer: AVPlayerLayer?
fileprivate var playbackLooper: AVPlayerLooper?
  • queuePlayer: An AVQueuePlayer object to manage the playback queue.

  • playerLayer: An AVPlayerLayer to display the video content in your view's layer.

  • playbackLooper: An AVPlayerLooper to facilitate seamless looping of the video.


4. Initialise the Controller

init(videoName: String) {
    self.videoName = videoName
    super.init(nibName: nil, bundle: nil)
}

The initialiser sets the videoName property and calls the superclass initialiser. This custom init is necessary because you need the video name to play the correct file.


5. Override viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()
    
    playBackgroundVideo()
}

In the viewDidLoad method, you call playBackgroundVideo(). This method is executed when the view controller's view is loaded into memory.


6. Find the Video File

guard let path = Bundle.main.path(forResource: videoName, ofType: "mp4") else {
    return
}

Here, you try to find the path of the video file in the app bundle. If it doesn’t exist, the function returns early.

7. Set Up the Player

let playerItem = AVPlayerItem(url: URL(fileURLWithPath: path))
self.queuePlayer = AVQueuePlayer(playerItem: playerItem)
self.playerLayer = AVPlayerLayer(player: self.queuePlayer)

You create an AVPlayerItem with the video URL, then initialise the queuePlayer and playerLayer with it.


8. Configure Looping and Layer

guard let playerLayer = self.playerLayer else { return }
guard let queuePlayer = self.queuePlayer else { return }
self.playbackLooper = AVPlayerLooper.init(player: queuePlayer, templateItem: playerItem)
playerLayer.videoGravity = .resizeAspectFill
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
  • Configure the playbackLooper for looping the video.

  • Set the videoGravity to resizeAspectFill so the video covers the entire view area without maintaining its aspect ratio.

  • Set the frame of playerLayer to match the view's bounds.

  • Add playerLayer as a sublayer of the view's layer.


9. Start Playing the Video

queuePlayer.play()

Finally, you start playing the video.

This code results in a view controller with a full-screen video background that loops indefinitely. The video file needs to be included in your app bundle and specified by its name when creating an instance of VideoViewController.


VideoViewController:

import UIKit
import AVKit
import AVFoundation

class VideoViewController: UIViewController {
    var videoName: String
    
    fileprivate var queuePlayer: AVQueuePlayer?
    fileprivate var playerLayer: AVPlayerLayer?
    fileprivate var playbackLooper: AVPlayerLooper?
    
    init(videoName: String) {
        self.videoName = videoName
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        playBackgroundVideo()
    }

    func playBackgroundVideo() {
        guard let path = Bundle.main.path(forResource: videoName, ofType: "mp4") else {
            return
        }
        
        let playerItem = AVPlayerItem(url: URL(fileURLWithPath: path))
                
        self.queuePlayer = AVQueuePlayer(playerItem: playerItem)
        self.playerLayer = AVPlayerLayer(player: self.queuePlayer)
        guard let playerLayer = self.playerLayer else { return }
        guard let queuePlayer = self.queuePlayer else { return }
        self.playbackLooper = AVPlayerLooper.init(player: queuePlayer, templateItem: playerItem)
        
        playerLayer.videoGravity = .resizeAspectFill
        playerLayer.frame = self.view.bounds
        self.view.layer.addSublayer(playerLayer)
        
        queuePlayer.play()
    }
}

Example usage, MenuViewController:

import UIKit

class MenuViewController: VideoViewController {
    init() {
        super.init(videoName: "MenuVideo")
    }

    required init?(coder: NSCoder) {
        super.init(videoName: "MenuVideo")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        setUpButtons()
    }

    fileprivate func setUpButtons() {
        let playGameButton = UIButton()
        playGameButton.translatesAutoresizingMaskIntoConstraints = false
        playGameButton.setTitle("Play Game", for: .normal)
        playGameButton.setTitleColor(.black, for: .normal)
        playGameButton.backgroundColor = .white
        playGameButton.addTarget(self, action: #selector(playGameButtonTapped), for: .touchUpInside)
        self.view.addSubview(playGameButton)
        
        let optionsButton = UIButton()
        optionsButton.translatesAutoresizingMaskIntoConstraints = false
        optionsButton.setTitle("Options", for: .normal)
        optionsButton.setTitleColor(.black, for: .normal)
        optionsButton.backgroundColor = .white
        optionsButton.addTarget(self, action: #selector(optionsButtonTapped), for: .touchUpInside)
        self.view.addSubview(optionsButton)
        
        NSLayoutConstraint.activate([
            playGameButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            playGameButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: -30),
            playGameButton.widthAnchor.constraint(equalToConstant: 200),
            playGameButton.heightAnchor.constraint(equalToConstant: 50),

            optionsButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            optionsButton.topAnchor.constraint(equalTo: playGameButton.bottomAnchor, constant: 20),
            optionsButton.widthAnchor.constraint(equalToConstant: 200),
            optionsButton.heightAnchor.constraint(equalToConstant: 50)
        ])
    }

    @objc func playGameButtonTapped() {
        print("Play Game button pressed")
    }

    @objc func optionsButtonTapped() {
        print("Options button pressed")
    }
}

How to support

This content will always remain free, and if you find it valuable, please consider sharing it with others. Additionally, downloading our games and leaving honest reviews greatly supports us. Feel free to reach out with any questions or feedback, and we'll do our best to respond.


Download Falling Sky from the Apple App Store today: https://apps.apple.com/app/id6446787964


30 views
bottom of page