VKVideoplayer usage in Swift - ios

I am trying to implement VKVideoplayer in Swift. I have used it as pod and imported the library in bridge class.
Now I am using the below code to start the video player, I am getting the video player in my view however, video stream is not happening
var player:VKVideoPlayer = VKVideoPlayer()
player.view.frame = self.view.bounds
player.delegate = self
self.view.addSubview(player.view)
var videotrack:VKVideoPlayerTrack = VKVideoPlayerTrack()
videotrack.streamURL = NSURL.fileURLWithPath("https://v.cdn.vine.co/r/videos/AA3C120C521177175800441692160_38f2cbd1ffb.1.5.13763579289575020226.mp4")
videotrack.hasNext = true
player.loadVideoWithTrack(video track)
The activity indicator is loading without the video.

#IBAction func play() {
let videoURLString = "http://......."
let videoVC = VKVideoPlayerViewController()
presentViewController(videoVC, animated: true, completion: nil)
videoVC.playVideoWithStreamURL(NSURL(string: videoURLString))
}
I don't know why it does not work if I use segue to switch view controller, so I just put it by code

Related

How to recognize a tap gesture while using an MPMoviePlayerController

I am attempting to recognize a tap gesture while a video is playing so that I can dismiss it similarly to how snapchat does this, however, it says that MPMoviePlayerControllers have no members to add touch gestures, is this true or am I using the incorrect method?
var MP4 : NSData?
var MarkerLong : CLLocationDegrees?
var MarkerLat : CLLocationDegrees?
var Url : String?
var videoPlayer : MPMoviePlayerController!
private var firstAppear = true
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if firstAppear {
do {
try playVideo()
firstAppear = false
} catch AppError.InvalidResource(let name, let type) {
debugPrint("Could not find resource \(name).\(type)")
} catch {
debugPrint("Generic error")
}
}
}
private func playVideo() throws {
self.videoPlayer = MPMoviePlayerController()
self.videoPlayer.repeatMode = MPMovieRepeatMode.None
self.videoPlayer.contentURL = NSURL(string: Url!)
self.videoPlayer.controlStyle = MPMovieControlStyle.None
self.view.addSubview(self.videoPlayer.view)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PlayVideoViewController.videoPlayBackDidFinish(_:)), name: MPMoviePlayerPlaybackDidFinishNotification, object: self.videoPlayer)
self.videoPlayer.view.frame.size = CGSizeMake(640, 1136)
self.videoPlayer.view.center = self.view.center
self.videoPlayer.play()
let gesture = UITapGestureRecognizer(target: self, action: "someAction:")
self.videoPlayer.addGestureRecognizer(gesture)
}
I would reccomend using AVPlayerViewController, but make sure not to subclass it, as Apple states not to.
1) MPMoviePlayer is deprecated (Don't use this code anymore)
2) AVPlayerViewController has a much more intricate set of code to allow more customization.
If you really want to customize something, you can subclass AVPlayer and make your own customized view where the video will be played, but you will have to add your own pause/start, etc...
MPMoviePlayerController is a view controller. Gesture recognizers are added to views. You need to add this gesture to the MPMoviePlayerController's view.
(Even better, stop using MPMoviePlayerController; it is deprecated.)

AVPlayer stuck video, but audio works

I go to create AVPlayerItem through AVURLAsset, my code:
let asset = AVURLAsset(URL: safeURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
asset.loadValuesAsynchronouslyForKeys([assetKeyPlayable, self.assetKeyTracks, self.assetKeyHasProtectedContent]) {
() -> Void in
dispatch_async(dispatch_get_main_queue(), {
() -> Void in
// Use the AVAsset playable property to detect whether the asset can be played
if !asset.playable {
let localizedDescription = "Item cannot be played,Item cannot be played description"
let localizedFailureReason = "The assets tracks were loaded, but could not be made playable,Item cannot be played failure reason"
let userInfo = [NSLocalizedDescriptionKey: localizedDescription, NSLocalizedFailureReasonErrorKey: localizedFailureReason]
let error = NSError(domain: "domain", code: 0, userInfo: userInfo)
self.videoPlayerDelegate?.videoPlayer?(self, playerItemStatusDidFail: error)
self.cleanPlayer()
return
}
// At this point we're ready to set up for playback of the asset. Stop observing
if let _ = self.player?.currentItem {
self.cleanPlayer()
}
if asset.URL.absoluteString != safeURL.absoluteString {
return
}
var error: NSError?
let status = asset.statusOfValueForKey(self.assetKeyTracks, error: &error)
var playerItem = AVPlayerItem(URL: safeURL)
if status == .Loaded {
playerItem = AVPlayerItem(asset: asset)
} else {
// You should deal with the error appropriately.If Loaded fails, create an AVPlayerItem directly from the URL
playerItem = AVPlayerItem(URL: safeURL)
}
self.player = self.playerWithPlayerItem(playerItem)
self.registerMonitoring()
self.registerNotification()
self.addTimeObserver()
completionBlock?(loadURLString: playerURL.absoluteString)
})
}
Add AVPlayerLayer display video in my View, my code:
// MARK: - Property
var player: AVPlayer? {
get {
return playerLayer.player
}
set {
playerLayer.player = newValue
}
}
var playerLayer: AVPlayerLayer {
return layer as! AVPlayerLayer
}
When displaying video after completion of loading
self.videoPlayer?.loadPlayer({
[weak self](loadURLString) in
if let strongSelf = self {
strongSelf.player = strongSelf.videoPlayer?.player
strongSelf.startPlay()
}
})
Call seekToTime method to specify the play:
self.player?.currentItem?.seekToTime(CMTimeMakeWithSeconds(time, Int32(NSEC_PER_SEC)), toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero) {
[weak self] finished in
if let weakSelf = self {
if weakSelf.isPlaying {
weakSelf.videoPlayerDelegate?.videoPlayerDidplayerItemSeekToTime?(weakSelf)
}
}
}
Some pictures of the stuck interface:
In the first picture the sound is audible, but the interface is stuck.
In the second picture, the video works, but I get no sound.
My question:
When I call the seekToTime method upon completion, sometimes the video has sound, but the interface is stuck, occasionally the video works. I tried to call the CALayer setNeedsDisplay methods, to update the AVPlayerLayer picture, but that didn't help. I don't know what to do anymore, i would be grateful for every and any help.
Since this is happening for many of us in a different way and is not answered, I am answering it here, For me this was happening when I was trying to play the video in UIView using AVPlayer and AVPlayerLayer but when I used the same AVPlayer to load the video in AVPlayerViewController the video was getting stuck and audio kept on playing.
The trick is to destroy the AVPlayerLayer before using the same AVPlayer somewhere else ,Cant believe I found this enlightenment over here.
https://twitter.com/skumancer/status/294605708073263104
How I implemented this?
I created 2 view controllers in my main story board.
1) View Controller Scene
i) This has a UIView in it referenced to IBOutlet 'videoView'
ii) A button with segue navigation to 'show' AV Player View Controller Scene referenced to IBOutlet 'fullscreen'
2) AV Player View Controller Scene
// Code in your controller class.
// Make sure to reference your IBOutlet in your StoryBoard.
#IBOutlet weak var videoView : UIView!
#IBOutlet weak var fullscreen : UIButton!
var player:AVPlayer? = nil;
var playerLayer:AVPlayerLayer? = nil;
override func viewDidLoad() {
super.viewDidLoad()
// Your Url to play, could be hls type video
let url = URL(string: "https://your_url.m3u8");
let asset = AVAsset(url : url!)
let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem)
}
override func viewDidAppear(_ animated: Bool) {
playInUIView()
pauseVideo()
}
// Creates An AVPlayerLayer and adds it as a sublayer in UIView.
func playInUIView(){
// Creating player layer to render video.
playerLayer = AVPlayerLayer(player: player)
playerLayer?.frame = self.videoView.bounds
playerLayer?.videoGravity = .resizeAspect
// Adding a sub layer to display it in UIView
self.videoView.layer.addSublayer(playerLayer!)
}
// Destroyes an AVPlayerLayer and Sublayer of your UIView
func destroyPlayInView(){
self.videoView.layer.sublayers=nil
playerLayer = nil
}
// On button click open AVPlayerViewController.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destination = segue.destination as! AVPlayerViewController
// Destroy AVPlayerLayer before rendering video in AVPlayerViewController.
destroyPlayInView()
// Set same AVPlayer in AVPlayerViewController.
destination.player = self.player
self.present(destination, animated: true) {
destination.player!.play()
}
}
PS - I have not implemented any controls as of yet and there could be coding malpractices as I have just started with swift and IOS development couple of days back, so please let me know wherever I am wrong.
Try this approach as I have encountered the same issue and solve it by this kind approach.
player.pause()
player.currentItem?.seek(to: CMTime(), completionHandler: { (_) in
player.play()
})
The same code of user nferocious76 but in Objective C
[self.player pause];
AVPlayerItem *playerItem = [self.player currentItem];
__weak typeof(self) weakSelf = self;
[playerItem seekToTime:playerItem.currentTime completionHandler:^(BOOL finished){
if (finished){
[weakSelf.player play];
}
}];

AVPlayerViewController - UIButton not triggering video

I am using AVPlayerViewController in order to play a .mov file (TeethingFinal.mov) in my project. The funny thing is, I have the feature working perfectly with two other buttons on the same ViewController but for some reason will not launch the AVPlayer! The tap gesture is being recognized, because I can see the button highlight when pressed but nothing happens. I would post error message but there is not one!
#IBAction func sugarBugPlay(sender: UIButton) {
let moviePlayerController = AVPlayerViewController()
let path = NSBundle.mainBundle().pathForResource("TeethingFinal", ofType:"mov")
let url = NSURL.fileURLWithPath(path!)
let playerVC = AVPlayerViewController()
var player: AVPlayer = AVPlayer()
playerVC.player = AVPlayer(URL: url)
self.presentViewController(playerVC, animated: true, completion: nil)
}
So sometimes Xcode is funny. I created a completely new ViewController the exact same way and reattached all of my outlets and it worked!

AVPlayer Crashes on Device When Dismissing View

I'm having an issue with the AVPlayer. I've tried many solutions but it still crashes after I move to a different view.
class GuideVideo : BaseViewController{
var avPlayer: AVPlayer?
var avPlayerLayer: AVPlayerLayer?
override func viewDidLoad() {
super.viewDidLoad()
generateVideo()
}
func generateVideo () {
let videoURLWithPath = data["VideoUrl"]
let videoFilePath = NSURL(string: videoURLWithPath!)
let avAsset: AVAsset = AVAsset.assetWithURL(videoFilePath) as! AVAsset
let avPlayerItem = AVPlayerItem(asset: avAsset)
avPlayer = AVPlayer(playerItem: avPlayerItem)
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer!.frame = self.videoView.bounds
self.videoView.layer.addSublayer(avPlayerLayer)
avPlayer!.play()
}
I've also tried removing the observers from it since I assume the crash is related to a nil observer.
override func viewWillDisappear(animated: Bool) {
dispatch_async(dispatch_get_main_queue(),{
if self.avPlayerLayer != nil {
self.avPlayerLayer!.player.pause()
NSNotificationCenter.defaultCenter().removeObserver(self.avPlayerLayer!)
self.avPlayerLayer!.removeFromSuperlayer()
self.avPlayerLayer = nil
}
self.avPlayer!.pause()
self.avPlayer = AVPlayer()
})
super.viewWillDisappear(animated)
}
Nothing works and the crash provides no data. Either it crashes without indicating a line or a general
Thread 1: EXC_BAD_ACCESS
* Import thing to note is that this crash only happens on the iPhone 6/6+. Our iPhone 5C handles the class well.
* I only get the crash after moving to another view controller or a different navigation stack, but a few seconds after the view had been dismissed.
Thank you, been sitting on this for the better part of 2 days now.
EDIT: The issue is apparently related to the SWReveal. It deallocates instances before their lifecycle is over.
Accepted the best solution, but the problem is related to SWReveal.
Try using the MPMoviePlayerController instead of the AVPlayer, for simple solutions, the MPMoviePlayerController has an easier API.
make the MPMoviePlayerController a global instance making it accessible through the whole app, and then initialize it when you need it.
Try playing the videos locally first and check if it solves the problem

MPMoviePlayerViewController black screen after returning from background

I have a simple controller that plays a video when opened. This works, but when I put the app into the backround and return I get a blank or black screen. If I then navigate to another view and then return, the view is no longer black and the video is playing.
How can I have the video play upon returning from the background?
MyViewController:
var myMovieController : MPMoviePlayerViewController?
override func viewDidLoad() {
super.viewDidLoad()
self.initMovie()
}
func initMovie(){
let moviePath = NSBundle.mainBundle().pathForResource("my-movie", ofType: "mp4")
let movieURL = NSURL.fileURLWithPath(moviePath!)
self.myMovieController = MPMoviePlayerViewController(contentURL: movieURL)
self.myMovieController?.moviePlayer.view.frame = self.view.bounds
self.myMovieController?.moviePlayer.controlStyle = MPMovieControlStyle.None
self.myMovieController?.moviePlayer.prepareToPlay()
self.myMovieController?.moviePlayer.scalingMode = .AspectFill
self.myMovieController?.moviePlayer.fullscreen = true
self.myMovieController?.moviePlayer.repeatMode = MPMovieRepeatMode.One
self.view.insertSubview(myMovieController!.moviePlayer.view, atIndex:0)
self.myMovieController?.moviePlayer.play()
}
In applicationWillEnterForeground I got a reference to MyViewController and called play on myMovieController. Not sure if this is the correct way to go about it, but it seems to work.
func applicationWillEnterForeground(application: UIApplication) {
let mc: MyViewController = (window!.rootViewController as! MyViewController)
mc.myMovieController?.moviePlayer.prepareToPlay()
mc.myMovieController?.moviePlayer.play()
}

Resources