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
Follow us on X: https://x.com/_kingdomarcade