How do i make a looping video in swift

2020-07-27 05:44发布

问题:

How would i go about making a local .mp4 file with no sound play on a loop, so it would only take up part of the screen and have no user controls. Just a looping video, sort of like a gif. I am using xcode, swift2.

class ViewController: UIViewController {

    var playerViewController = AVPlayerViewController()
    var playerView = AVPlayer()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    }

    override func viewDidAppear(animated: Bool) {
        var fileURL = NSURL(fileURLWithPath: "/Users/Mantas/Desktop/123/123/video-1453562323.mp4.mp4")
        playerView = AVPlayer(URL: fileURL)

        playerViewController.player = playerView

        self.presentViewController(playerViewController, animated: true){

            self.playerViewController.player?.play()

        }
    }
}

I have made this, it plays the video, but in full screen, i dont know how to make it only take up part of the screen and how to make it loop

回答1:

Adding observer when video going to finish you can make replay the video

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear()

    var fileURL = NSURL(fileURLWithPath: "/Users/Mantas/Desktop/123/123/video-1453562323.mp4.mp4")
    playerView = AVPlayer(URL: fileURL)

    NSNotificationCenter.defaultCenter().addObserver(self,
    selector: "playerItemDidReachEnd:",
    name: AVPlayerItemDidPlayToEndTimeNotification,
    object: self.playerView.currentItem) // Add observer

    playerViewController.player = playerView

    //amend the frame of the view
    self.playerViewController.player.frame = CGRectMake(0, 0, 200, 200)
    //reset the layer's frame, and re-add it to the view
    var playerLayer: AVPlayerLayer =   AVPlayerLayer.playerLayerWithPlayer(self.playerView)
    playerLayer.frame = videoHolderView.bounds
    videoHolderView.layer.addSublayer(playerLayer)

    /* Full Screen
    self.presentViewController(playerViewController, animated: true){

        self.playerViewController.player?.play()

    }  */
}

func playerItemDidReachEnd(notification: NSNotification) {
   self.playerView.seekToTime(kCMTimeZero)
   self.playerView.play()
}


回答2:

Alternate version in Swift 3.0:

Add these properties:

fileprivate var player: AVPlayer? {
    didSet { player?.play() }
}

fileprivate var playerObserver: Any?

Add this to your deinit:

deinit {
    guard let observer = playerObserver else { return }
    NotificationCenter.default.removeObserver(observer)
}

Add this function:

func videoPlayerLayer() -> AVPlayerLayer {
    let fileURL = URL(fileURLWithPath: mediaPath)
    let player = AVPlayer(url: fileURL)
    let resetPlayer = {
        player.seek(to: kCMTimeZero)
        player.play()
    }
    playerObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: nil) { notification in
        resetPlayer()
    }
    self.player = player
    return AVPlayerLayer(player: player)
}

Then add to your layer wherever you feel like (viewDidLoad, viewDidAppear, viewDidFinishLayingOutSubviews):

let playerLayer = videoPlayerLayer()
playerLayer.frame = view.bounds
view.layer.insertSublayer(playerLayer, at: 0)


回答3:

For a seemless repeating video without a black flash. Use the AVPlayerLooper like so:

private var player: AVQueuePlayer!
private var playerLayer: AVPlayerLayer!
private var playerItem: AVPlayerItem!
private var playerLooper: AVPlayerLooper!

override func viewDidLoad(){
    super.viewDidLoad()

    let path = Bundle.main.path(forResource: "background_cloudy", ofType: "mov")
    let pathURL = URL(fileURLWithPath: path!)
    let duration = Int64( ( (Float64(CMTimeGetSeconds(AVAsset(url: pathURL).duration)) *  10.0) - 1) / 10.0 )

    player = AVQueuePlayer()
    playerLayer = AVPlayerLayer(player: player)
    playerItem = AVPlayerItem(url: pathURL)
    playerLooper = AVPlayerLooper(player: player, templateItem: playerItem,
                                  timeRange: CMTimeRange(start: kCMTimeZero, end: CMTimeMake(duration, 1)) )
    playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
    playerLayer.frame = view.layer.bounds
    view.layer.insertSublayer(playerLayer, at: 1)
}