Reputation: 16619
I am trying to make a short .mp4 video as a splash screen to show it when starting the app.
is there any example for that ?
Upvotes: 6
Views: 20022
Reputation: 5015
In my App I have such a scenario. I'll post the individual steps here. As an information to the video (YourLogoVideo.mov): It should be stored in the root
of the project, same location as i.Ex the Main.storyboard
is located. And its format should be QuickTime
in the .mov
format.
Required Framework:
import AVKit
Define this in your GameViewController
(no need to be static):
static var videoPlayer : AVPlayer!
static var videoView : AVPlayerViewController!
Here is the Setup Function - call it in viewDidLoad
(at the very end of viewDidLoad
):
func setupLogoVideoSequence() {
// Logo Video
let filePath = Bundle.main.path(forResource: "YourLogoVideo", ofType: "mov") // Video duration 10.0 sec
let fileURL = URL.init(fileURLWithPath: filePath!)
GameViewController.videoPlayer = AVPlayer(url: fileURL) // Init Player
GameViewController.videoView = AVPlayerViewController() // Init View
GameViewController.videoView.player = GameViewController.videoPlayer
GameViewController.videoView.player?.isMuted = false
GameViewController.videoView.player?.volume = 0.25
GameViewController.videoView.player?.automaticallyWaitsToMinimizeStalling = true
GameViewController.videoView.player?.actionAtItemEnd = .none
GameViewController.videoView.view.frame = view.frame
GameViewController.videoView.showsPlaybackControls = false
GameViewController.videoView.videoGravity = .resizeAspectFill
// Add the VideoView to the View like so
view.addSubview(GameViewController.videoView.view)
// Schedule Cleanup of Video Stuff using observer
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: GameViewController.videoPlayer.currentItem, queue: .main) { _ in self.deinitLogoVideo() }
}
Here is the Video deinit
function:
func deinitLogoVideo() {
guard isAppStartUp else { return }
DispatchQueue.main.async {
if GameViewController.videoView != nil {
GameViewController.videoView.view.removeFromSuperview()
GameViewController.videoView = nil
print("Logo Video deinitialized - videoView")
}
if GameViewController.videoPlayer != nil {
GameViewController.videoPlayer.replaceCurrentItem(with: nil)
GameViewController.videoPlayer = nil
print("Logo Video deinitialized - videoPlayer")
}
}
}
Here comes the moment to play the Video. Call it like from viewDidAppear
:
DispatchQueue.main.async { GameViewController.videoView.player?.play() }
Make sure no other view covers the videoView!
Hope this will help someone.
Upvotes: 1
Reputation: 12648
Simply use it on your first or main screen. Naturally, delay all processing in your app until the video is complete.
class SplashVidView: UIIView {
var playerRef: AVPlayer?
private lazy var pl: AVPlayerLayer = {
//prevent background music woes courtesy @AnaLlera ...
do {
try AVAudioSession.sharedInstance().setCategory(.ambient)
} catch { }
let path = Bundle.main.path(forResource: "name", ofType: "mp4")!
let plr = AVPlayer(url: URL(filePath: path))
let playerLayer = AVPlayerLayer(player: plr)
playerLayer.videoGravity = .resizeAspectFill
playerLayer.zPosition = -1
layer.addSublayer(playerLayer)
plr.seek(to: CMTime.zero)
plr.play()
playerRef = plr
return playerLayer
}()
override func layoutSubviews() {
backgroundColor = .clear
super.layoutSubviews()
pl.frame = bounds
}
}
Upvotes: 2
Reputation: 1916
You can create a custom ViewController for "Main Interface" and use it after the LaunchScreen with use AVPlayer inside. In swift will be something like this:
var player: AVPlayer?
override func viewDidLoad() {
super.viewDidLoad()
loadVideo()
}
private func loadVideo() {
//this line is important to prevent background music stop
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
} catch { }
let path = NSBundle.mainBundle().pathForResource("your path", ofType:"mp4")
player = AVPlayer(URL: NSURL(fileURLWithPath: path!))
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.frame
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
playerLayer.zPosition = -1
self.view.layer.addSublayer(playerLayer)
player?.seekToTime(kCMTimeZero)
player?.play()
}
Upvotes: 4
Reputation: 598
See the answer below by DarkDust in Emulating splash video in iOS application.
I Think one solution for you is show a Splash (IMG) and than you play the video you like.
To play videos in swift use AV Foundation https://developer.apple.com/av-foundation/
You cannot get rid of the static splash image. While it is shown, the OS is loading the application and instantiating stuff until it is ready to call your UIApplicationDelegate. So all you can do is either use no splash (black screen for a few seconds) or make your movie start exactly with the shown splash screen so it looks like the static image would suddenly animate.
To get rid of the black screen while the movie loads, you can try to make the player transparent and have an UIImageView behind the player that shows the splash image. The behavior would be this:
Splash screen is shown (static image). Application is loaded. You see the UIImageView, also showing the splash screen. On top of it is the transparent movie player. Movie player finally has loaded the move and starts playing it. At least in theory, this should cause the effect that the static image suddenly starts animating.
But if you don't use a splash screen at all (a lot of games do that), then it doesn't matter that the movie player is showing a black screen at first, you wouldn't notice.
Regarding showing the splash screen in an UIImageView: unfortunately, you have to test the interface rotation and load the image manually, there's no way to query which splash screen was shown. If you only support one interface orientation (again, a lot of games do this) you don't have this problem, of course.
Upvotes: 11