【问题标题】:How do i make a looping video in swift如何快速制作循环视频
【发布时间】:2016-01-25 10:17:52
【问题描述】:

我将如何制作一个本地.mp4 文件而不会在循环中播放声音,因此它只会占用屏幕的一部分并且没有用户控件。只是一个循环视频,有点像 gif。我正在使用xcodeswift2

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()

        }
    }
}

我做了这个,它播放视频,但是全屏,我不知道如何让它只占屏幕的一部分以及如何让它循环

【问题讨论】:

    标签: ios swift loops video


    【解决方案1】:

    Swift 3.0 中的替代版本:

    添加这些属性:

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

    将此添加到您的 deinit 中:

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

    添加此功能:

    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)
    }
    

    然后添加到您想要的任何位置(viewDidLoad、viewDidAppear、viewDidFinishLayingOutSubviews):

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

    【讨论】:

    • 这太棒了,谢谢!我认为我们应该将 fileURL 作为参数。 func videoPlayerLayer(fileURL: URL) -> AVPlayerLayer
    • 你太棒了!这真的很有帮助!我所要做的就是改变cell.layer.addSublayer(cell.playerLayer!)
    【解决方案2】:

    当视频结束时添加观察者可以重播视频

    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()
    }
    

    【讨论】:

    • 谢谢,我将如何添加一个框架,而不是全屏播放?
    • 更新了答案,如果有帮助,您可以接受答案
    • 它有一个窍门!但循环不是无缝的。播放之间有一些差距
    【解决方案3】:

    对于没有黑色闪光的无缝重复视频。像这样使用 AVPlayerLooper:

    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)
    }
    

    【讨论】:

      【解决方案4】:

      这是用 Swift 5 测试的,我在 https://gist.github.com/lanserxt/33fd8c479185cba181497315299e0e31 找到了

      import UIKit
      import AVFoundation
      
      class LoopedVideoPlayerView: UIView {
      
          fileprivate var videoURL: URL?
          fileprivate var queuePlayer: AVQueuePlayer?
          fileprivate var playerLayer: AVPlayerLayer?
          fileprivate var playbackLooper: AVPlayerLooper?
      
          func prepareVideo(_ videoURL: URL) {
          
              let playerItem = AVPlayerItem(url: videoURL)
                  
              self.queuePlayer = AVQueuePlayer(playerItem: playerItem)
              self.playerLayer = AVPlayerLayer(player: self.queuePlayer)
              guard let playerLayer = self.playerLayer else {return}
              guard let queuePlayer = self.queuePlayer else {return}
              self.playbackLooper = AVPlayerLooper.init(player: queuePlayer, templateItem: playerItem)
                  
              playerLayer.videoGravity = .resizeAspectFill
              playerLayer.frame = self.frame
              self.layer.addSublayer(playerLayer)
          }
      
          func play() {
              self.queuePlayer?.play()
          }
      
          func pause() {
              self.queuePlayer?.pause()
          }
      
          func stop() {
              self.queuePlayer?.pause()
              self.queuePlayer?.seek(to: CMTime.init(seconds: 0, preferredTimescale: 1))
          }
      
          func unload() {
              self.playerLayer?.removeFromSuperlayer()
              self.playerLayer = nil
              self.queuePlayer = nil
              self.playbackLooper = nil
          }
          
          override init(frame: CGRect) {
              super.init(frame: frame)
          }
      
          required init?(coder aDecoder: NSCoder) {
              super.init(coder: aDecoder)
          }
      
          override func layoutSubviews() {
              self.playerLayer?.frame = self.bounds
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-31
        • 1970-01-01
        • 2013-07-08
        • 2023-03-09
        相关资源
        最近更新 更多