How to make a video loop in Xcode swift 5? - swift

I am trying to get a video background in my app and I have written the following code. It runs one time and then stops. How do I make the video repeat forever? Thanks in advance.
#IBOutlet weak var videoLayer: UIView!
override func viewDidLoad() {
super.viewDidLoad()
playBackgroundVideo()
}
func playBackgroundVideo(){
guard let path = Bundle.main.path(forResource: "City", ofType: "MOV") else {
return
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
playerLayer.videoGravity = .resizeAspectFill
self.videoLayer.layer.addSublayer(playerLayer)
player.play()
}
#objc func playerItemDidReachEnd(notification: Notification) {
let p: AVPlayerItem = notification.object as! AVPlayerItem
p.seek(to: .zero)
}
}

Try adding a notification listener to trigger the playerItemDidReachEnd code.
You do this by involving a NotificationCenter.default.addObserver in your setup.
Did not test your code, but you want a setup like this example:
#IBOutlet weak var videoLayer: UIView!
var player: AVPlayer!
override func viewDidLoad()
{
super.viewDidLoad()
playBackgroundVideo()
}
func playBackgroundVideo()
{
guard let path = Bundle.main.path(forResource: "City", ofType: "MOV") else{ return }
player = AVPlayer(url: URL(fileURLWithPath: path))
let playerLayer = AVPlayerLayer(player: player)
//# add a Listener
NotificationCenter.default.addObserver( self,
selector: #selector(playerItemDidReachEnd),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: nil)
playerLayer.frame = self.view.bounds
playerLayer.videoGravity = .resizeAspectFill
self.videoLayer.layer.addSublayer(playerLayer)
player.play()
}
#objc func playerItemDidReachEnd(notification: Notification)
{
player.seek(to: CMTime.zero)
player.play()
}

Related

Swift: Parse does not load a video from URL

I am trying to stream a video from backend to my device.I have a video url from backend but screen displays nothing. However, youtube url it works. Can anyone guide me why this video is not playing and how can it be played? I am using pod 'YouTubePlayer' to play the video.
let cell: VideoTableViewCell = tableView.dequeueReusableCell(withIdentifier: "VideoTableViewCell") as! VideoTableViewCell
var query = PFQuery(className:"Videos")
query.getObjectInBackground(withId: "83kli72i62") { (parseObject, error) -> Void in
let videoFile = parseObject!["Question"] as! PFFileObject
self.videoUrl = videoFile.url
let url = NSURL(string: self.videoUrl! )
cell.playerView.loadVideoURL(url as! URL)
}
i have an app that is pulling videos from firebase and playing them with the avplayer, check out my code below and see how it works
class IsoLateralLowRowViewController: UIViewController {
#IBOutlet weak var playv: UIButton!
let avPlayerViewController = AVPlayerViewController()
var avPlayer:AVPlayer?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addBackground()
let movieUrl:NSURL? = NSURL(string: "https://firebasestorage.googleapis.com/v0/b/messenger-test-d225b.appspot.com/o/test%2FTestVideo.mov?alt=media&token=bd4ccba3-b446-43bc-809e-b1152aa3c2ff")
if let url = movieUrl {
self.avPlayer = AVPlayer(url: url as URL)
self.avPlayerViewController.player = self.avPlayer
}
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: avPlayerViewController.player?.currentItem)
self.present(self.avPlayerViewController, animated: true) { () -> Void in
self.avPlayerViewController.player?.play() // Do any additional setup after loading the view.
}
}
#objc func playerDidFinishPlaying(note: NSNotification) {
self.avPlayerViewController.dismiss(animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

how to have separate videos that play with separate buttons

can anyone please help me, I am trying to add separate buttons to play separate videos in the same view controller but I don't know how to.
this is my code, how do I do this?
import UIKit
import AVKit
class ViewController: UIViewController {
#IBAction func Town(_ sender: Any) {
if let path = Bundle.main.path(forResource: "grey", ofType: "mov") {
let video = AVPlayer(url: URL(fileURLWithPath: path))
let videoPlayer = AVPlayerViewController()
videoPlayer.player = video
self.present(videoPlayer, animated: true, completion: {
video.play()
})
}
func viewDidLoad() {
super.viewDidLoad()
}
}
}
To play 2 videos simultaneously in same viewController, you need to create 2 separate views and 2 respective buttons in your Storyboard.
Remaining functionality will go inside your IBActions.
Please use following code:
class VideoPlaybackViewController: UIViewController {
#IBOutlet weak var videoView1: UIView!
#IBOutlet weak var videoView2: UIView!
#IBAction func playFirstVideo(_ sender: Any) {
guard let path = Bundle.main.path(forResource: "640", ofType: "mov") else {
print("Video Source Not Found")
return
}
playVideo(playbackURL: URL(fileURLWithPath: path), playerView: videoView1)
}
#IBAction func playSecondVideo(_ sender: Any) {
guard let path = Bundle.main.path(forResource: "720", ofType: "mov") else {
print("Video Source Not Found")
return
}
playVideo(playbackURL: URL(fileURLWithPath: path), playerView: videoView2)
}
func playVideo(playbackURL: URL, playerView: UIView) {
let player = AVPlayer(url: playbackURL)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = playerView.bounds
playerView.layer.addSublayer(playerLayer)
player.play()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
Please see the screen with this implementation
I used this code and it worked perfectly
import UIKit
import AVKit
class ViewController: UIViewController {
#IBOutlet weak var videoView1: UIButton!
#IBOutlet weak var videoView2: UIButton!
#IBAction func playFirstVideo(_ sender: Any) {
if let path = Bundle.main.path(forResource: "grey", ofType: "mov") {
let video = AVPlayer(url: URL(fileURLWithPath: path))
let videoPlayer = AVPlayerViewController()
videoPlayer.player = video
self.present(videoPlayer, animated: true, completion: {
video.play()
})
}
}
#IBAction func playSecondVideo(_ sender: Any) {
if let path = Bundle.main.path(forResource: "go", ofType: "mov") {
let video = AVPlayer(url: URL(fileURLWithPath: path))
let videoPlayer = AVPlayerViewController()
videoPlayer.player = video
self.present(videoPlayer, animated: true, completion: {
video.play()
})
}
}
}

AVPlayer ,black screen after video is over

i have black screen after video is over, but i would like to be redirect to another storyboard when video is over.
Could somebody help me with this.
Thanks you
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
playVideo()
}
private func playVideo() {
guard let path = Bundle.main.path(forResource: "Kristinka", ofType:"m4v") else {
debugPrint("video.m4v not found")
return
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerController = AVPlayerViewController()
playerController.showsPlaybackControls = false
playerController.player = player
present(playerController, animated: true) {
player.play()
}
}
}
You need to detect when the item you're playing has reached the end. To do that, you can add an observer. For example:
func finishedVideo(_ notification: NSNotification) {
print("Animation did finish")
}
private func playVideo() {
guard let path = Bundle.main.path(forResource: "Kristinka", ofType:"m4v") else {
debugPrint("video.m4v not found")
return
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerController = AVPlayerViewController()
playerController.showsPlaybackControls = false
playerController.player = player
present(playerController, animated: true) {
NotificationCenter.default.addObserver(self,
selector: #selector(finishedVideo(_:)),
name: .AVPlayerItemDidPlayToEndTime,
object: player?.currentItem)
player.play()
}
}
And I dug this code up on this very related question. There's a lot of related/duplicate answers if you do a search.

how to add CIFilters to a video at runtime

I have recorded a video using avfoundation and after clicking on the video its start to play on a new viewcontroller. The problem is, I wouldn't be able to add filter effects to a playing video. Following is the code of what i have achieved.
import UIKit
import AVFoundation
class VideoPlayback: UIViewController {
let avPlayer = AVPlayer()
var avPlayerLayer: AVPlayerLayer!
var videoURL: URL!
#IBOutlet weak var videoView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(finishVideo), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer.frame = view.bounds
avPlayerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoView.layer.insertSublayer(avPlayerLayer, at: 0)
view.layoutIfNeeded()
let playerItem = AVPlayerItem(url: videoURL as URL)
avPlayer.replaceCurrentItem(with: playerItem)
avPlayer.play()
}
#objc func finishVideo()
{
print("Video Finished")
self.performSegue(withIdentifier: "unwindToFifteenSeconds", sender: self)
}
// Remove Observer
deinit {
NotificationCenter.default.removeObserver(self)
}
}
Above code is only to play a video that was captured by the camera using AVfoundation. I only need to add CIfilters to this played video.
you can apply a filter to a video
let filter = CIFilter(name: "CIGaussianBlur")!
let asset = AVAsset(url: streamURL)
let item = AVPlayerItem(asset: asset)
item.videoComposition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in
// Clamp to avoid blurring transparent pixels at the image edges
let source = request.sourceImage.clampingToExtent()
filter.setValue(source, forKey: kCIInputImageKey)
// Vary filter parameters based on video timing
let seconds = CMTimeGetSeconds(request.compositionTime)
filter.setValue(seconds * 10.0, forKey: kCIInputRadiusKey)
// Crop the blurred output to the bounds of the original image
let output = filter.outputImage!.cropping(to: request.sourceImage.extent)
// Provide the filter output to the composition
request.finish(with: output, context: nil)
})

Play video from Download URL

I have a URL :- "http://fitnation.theclientdemos.com:9000/media/uploads/videoplayback_3_JtVCHi1"
When I run this URL on browser, My VDO starts downloads.
Please help to play this video in a view (let view name is:- vdoView)
For this I am trying below code:-
import UIKit
import AVKit
import AVFoundation
class VideoViewController: UIViewController {
#IBOutlet weak var vdoView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
getVideo()
}
func getVideo(){
let videoURL = URL(string: "http://fitnation.theclientdemos.com:9000/media/uploads/videoplayback_3_JtVCHi1")
let player = AVPlayer(url: videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.vdoView.bounds
self.vdoView.layer.addSublayer(playerLayer)
player.play()
}
First you have to import AVKit, import AVFoundation
Using AVPlayer
if let url = URL(string: "http://fitnation.theclientdemos.com:9000/media/uploads/videoplayback_3_JtVCHi1"){
let player = AVPlayer(url: url)
let controller=AVPlayerViewController()
controller.player=player
controller.view.frame = self.view.frame
self.view.addSubview(controller.view)
self.addChildViewController(controller)
player.play()
}
It's better to put this code into the method: override func viewDidAppear(_ animated: Bool) or somewhere after.
override func viewDidLoad()
{
let videoURL = NSURL(string: "http://fitnation.theclientdemos.com:9000/media/uploads/videoplayback_3_JtVCHi1")
let player = AVPlayer(url: videoURL! as URL)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
}
You should try it like this
func getVideo(){
let videoURL = URL(string: "http://fitnation.theclientdemos.com:9000/media/uploads/videoplayback_3_JtVCHi1")
// Create an AVAsset
let videoAsset = AVAsset(url: videoURL!)
// Create an AVPlayerItem with asset
let videoPlayerItem = AVPlayerItem(asset: videoAsset)
// Initialize player with the AVPlayerItem instance.
let player = AVPlayer(playerItem: videoPlayerItem)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.vdoView.bounds
self.vdoView.layer.addSublayer(playerLayer)
player.play()
}
And you should update your plist file to allow the contents from http: Refer here
*All you need is change your code to this:
import AVFoundation
class your class name
var player: AVPlayer?
func playAudio() {
guard let url = URL.init(string: "http://192.168.100.184:9050/uploads/sound/file/1/a1b19343-f785-4d48-b7d5-1abe26c03ff3.mp3" ) else { return }
player = AVPlayer.init(url: url)
}
and at the end call the func in IBAction body*
just like the code below:
#IBAction play (sender: Any) {
playAudio()
}