MPMoviePlayerController switching videos - ios

I'm playing a video:
let path = NSBundle.mainBundle().pathForResource("Video", ofType:"mp4")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = moviePlayer {
player.view.frame = self.view.bounds
player.prepareToPlay()
player.scalingMode = .AspectFill
player.controlStyle = .None
self.view.addSubview(player.view)
}
and I want to replace this with another video when a button is pressed:
#IBAction func aButtonIsPressed(sender: AnyObject) {
let path = NSBundle.mainBundle().pathForResource("Another Video", ofType:"mp4")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = moviePlayer {
player.view.frame = self.view.bounds
player.prepareToPlay()
player.scalingMode = .AspectFill
player.controlStyle = .None
self.view.addSubview(player.view)
}
}
When I tap the button the video plays, but there seems to be a delay adding the new video, which gives it a choppy transition. Is there any way to minimize this delay? I could try adding another MPMoviePlayerController to preload the second video maybe but from some testing I found the line causing the chop is here.
self.view.addSubview(player.view)
Can I keep the first video playing until the line above 'didFinish'? That would be great.

You are creating new MPMoviePlayerController object that's why you are getting this issue, you should use same object and which is already playing an object and just set contentURL property to new resource's URL,
If you set this property while a movie is playing, that movie pauses
and the new movie begins loading. The new movie starts playing at the
beginning
For more detail visit this link

Related

Play several videos using AVPlayer in a view

I have an UIView which contains some some texts and views. in each view I need to play a video with AVPlayer , but my problem is only the first view shows the video :
Here is my code :
func playVideo(name:String , onView:UIView) {
let path = Bundle.main.path(forResource: name, ofType: "mp4")
let videoURL = URL(fileURLWithPath: path!)
let player = AVPlayer(url: videoURL)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = onView.frame
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
onView.layer.addSublayer(playerLayer)
player.play()
}
Using the function :
override func viewDidLoad() {
super.viewDidLoad()
//ScrollView
scrollView.contentSize = menuView.frame.size
scrollView.addSubview(menuView)
//Play videos
playVideo(name: "pizza", onView: videoView1)
playVideo(name: "salad", onView: videoView2)
playVideo(name: "fries", onView: videoView3)
}
when I run the app video only play in videoView1 , any suggestion why this happens ?
I also put my code in viewWillAppear , viewDidLayoutSubviews
According to Apple doc:
class AVPlayer
Note
AVPlayer is intended for playing a single media asset at a time.
I just found an alternative solution , I replaced UIView with UIContainerView and then link them with Embed to other view controller and play video in each view controller. Now it works perfectly as I expected.

AVPlayerLayer shows black screen but sound is working

Im trying to display a local recorded video in a AVPlayerLayer which works sometimes. I can hear the audio from the recorded video but can't see the video. Sometimes both video and audio is working, sometimes only audio.
I've tried both with a AVPlayerLayer and AVPlayerViewController but the same issue occurs in both cases. So it's not because of the frames being wrong.
Example code AVPlayerViewController:
let player = AVPlayer(url: url)
let playerController = AVPlayerViewController()
playerController.player = player
self.present(playerController, animated: true) {
player.play()
}
Example code AVPlayerLayer:
let asset = AVAsset(url: url)
let item = AVPlayerItem(asset: asset)
self.player = AVPlayer(playerItem: item)
self.player?.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions(), context: nil)
self.playerLayer = AVPlayerLayer(player: self.player!)
self.playerLayer?.frame = imageView.bounds
imageView.layer.addSublayer(self.playerLayer!)
Edit 1:
When observing the status of the player, error is nil and the status is readyToPlay
Edit 2:
Works fine if the URL is remote.
Edit 3:
Seems to work if I wait a couple of seconds after the video has completed the export. Could it be something to have with the file not 100% written to the filesystem?
Edit 4:
Video of the problem, in this case it played the 3rd time.
Here's how I set a AVPlayerLayer with the video working (I think what you're missing is the videoGravity parameter).
let bundle = Bundle.main
let moviePath = bundle.path(forResource: "myVideo", ofType: "mp4")
let moviePlayer = AVPlayer(url: URL(fileURLWithPath: moviePath!))
playerLayer = AVPlayerLayer(player: moviePlayer)
playerLayer.frame = movieView.bounds
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect
movieView.layer.addSublayer(playerLayer)
playerLayer.player?.play()
It's the frame height or width is equal to zero
i have the same issues as you did. the reason is in iOS 10.xx , if you export video with animationTool .
You will meet the trouble like that .
try to fix them by remove this code .
something like that
mainComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentlayer)
Hope to help you
What caused this issue for me was I was changing assets to play a new video. The problem was I was reinitializing the same AVPlayer and setting setting it to the playerLayer which was previously set
Incorrect
player = AVPlayer()
playerLayer = AVPlayerLayer(player: player)
// ...
player?.replaceCurrentItem(with: playerItem)
Correct
if player == nil {
player = AVPlayer()
playerLayer = AVPlayerLayer(player: player)
// ...
}
player?.replaceCurrentItem(with: playerItem)
Or better yet I should've just called this by itself
player?.replaceCurrentItem(with: playerItem)

AVPlayer automatically zoom in video in IOS + Swift

I've used AVPlayer and AVPlayerViewController.
let playerController = AVPlayerViewController()
var player = AVPlayer()
self.player = AVPlayer(URL: NSURL(fileURLWithPath:videoPath))
self.playerController.player = self.player
self.playerController.showsPlaybackControls = false
self.addChildViewController(self.playerController)
self.view.addSubview(self.playerController.view)
self.playerController.view.frame = ...
I can play video with controls but when video finish I have to hide controls.
I found the event if video finished and at that time I hide the control
func playerDidFinishPlaying(note: NSNotification) {
self.playerController.showsPlaybackControls = false
}
Problem: If user zoom out video and video finished then hide control so Is there any possibilty to back to original frame
Thank you so much in adv.

Issue with reusing AVPlayer instance for playing video

I am to play same video in two screens with keeping seek time. So that I am reusing AVPlayer instance in these screen. For first time AVPlayer works fine, but whenever it is reused frame of player animates from top-left to fit target view on start of play.
like,
https://www.dropbox.com/s/8ieb4bnb0rsn9ig/ezgif.com-gif-maker.gif?dl=0
code looks like,
if myObj._playerResult != nil {
_player = myObj._playerResult //reuse player instance
} else {
// First create an AVPlayerItem
let playerItem : AVPlayerItem = AVPlayerItem(URL: NSURL(string:sVideoUrl as String))
_player = AVPlayer(playerItem: playerItem)
}
playerController = AVPlayerViewController()
playerController?.showsPlaybackControls = false
playerController?.player = _player
playerController!.view.frame = targetView.bounds
targetView.addSubview(playerController!.view)
_player?.play()

How do I prevent the video from zooming in/out in iOS with Swift?

I'm a beginner iOS Swift developer, and new to StackOverflow. I'm trying to develop my first game, and I wanted to use a video as an intro. I got the video playing and working properly, but a problem I am having is when I double tap the screen the video zooms in and out. Is there any way to prevent this?
Here is my code:
func playVideo() {
if let
path = NSBundle.mainBundle().pathForResource("wakyIntro", ofType:"mp4"),
url = NSURL(fileURLWithPath: path),
moviePlayer = MPMoviePlayerController(contentURL: url) {
self.moviePlayer = moviePlayer
moviePlayer.view.frame = self.view.bounds
moviePlayer.prepareToPlay()
moviePlayer.scalingMode = .AspectFill
self.view.addSubview(moviePlayer.view)
moviePlayer.fullscreen = true
moviePlayer.controlStyle = MPMovieControlStyle.None
moviePlayer.movieSourceType = MPMovieSourceType.File
moviePlayer.play()
println("Video loaded successfully")
} else {
debugPrintln("Ops, something wrong when playing the video")
}
}
Then I call it from a separate ViewController that I use for my Main Menu
func mainMenuViewControllerDidPressVideo(mainMenuViewController: MainMenuViewController) {
playVideo()
}
Set moviePlayer.view.userInteractionEnabled to false.
moviePlayer.view.userInteractionEnabled = false
Or set controlStyle to Full Screen
moviePlayer.controlStyle = MPMovieControlStyleFullscreen
Just disable the user interaction. That will not cause the video to zoom in/out and it will ignore all user interaction in movie player view.
moviePlayer.view.userInteractionEnabled = false
Hope this helps.... :)
You can use MPMoviePlayerViewController instead of MPMoviePlayerController:
movieViewController = MPMoviePlayerViewController(contentURL: url)
movieViewController?.moviePlayer.fullscreen = true
movieViewController?.moviePlayer.controlStyle = .Embedded
moviePlayer.view.userInteractionEnabled = false
self.presentMoviePlayerViewControllerAnimated(movieViewController)

Resources