你如何在Swift中循环AVPlayer?

时间:2015-01-06 22:24:14

标签: ios swift

简单的问题我似乎无法找到答案。

如何在Swift中循环AVPlayer?

numberOfLoops = -1仅适用于AVAudioPlayer

我确实需要它循环而没有任何延迟/黑色闪光等。这就是为什么我没有使用MPMoviePlayerViewController。

感谢您的帮助。

代码:

    let url_1 = NSURL.fileURLWithPath(outputFilePath_1)

    let asset_1 = AVAsset.assetWithURL(url_1) as? AVAsset
    let playerItem_1 = AVPlayerItem(asset: asset_1)

    let player_1 = AVPlayer(playerItem: self.playerItem_1)

    let playerLayer_1 = AVPlayerLayer(player: self.player_1)

    playerLayer_1!.frame = self.view.frame

    self.view.layer.addSublayer(self.playerLayer_1)

    player_1!.play()

8 个答案:

答案 0 :(得分:137)

Swift 4

var player: AVPlayer!

...

NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { [weak self] _ in
    self?.player?.seek(to: CMTime.zero)
    self?.player?.play()
}

Swift 3

NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { [weak self] _ in
    self?.player?.seek(to: kCMTimeZero)
    self?.player?.play()
}

Swift 2

After AVPlayerItem is configured and player is created:

var player: AVPlayer!

...

// Invoke after player is created and AVPlayerItem is specified
NSNotificationCenter.defaultCenter().addObserver(self,
    selector: "playerItemDidReachEnd:",
    name: AVPlayerItemDidPlayToEndTimeNotification,
    object: self.player.currentItem)

...

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

Don't forget to import AVFoundation

答案 1 :(得分:24)

或者,您可以使用基于块的NSNotificationCenter API:

func loopVideo(videoPlayer: AVPlayer) {
    NSNotificationCenter.defaultCenter().addObserverForName(AVPlayerItemDidPlayToEndTimeNotification, object: nil, queue: nil) { notification in
        videoPlayer.seekToTime(kCMTimeZero)
        videoPlayer.play()
    }
}

答案 2 :(得分:22)

好的,我已经解决了。感谢Msencenb用Objective C答案指引我正确的方向。

player_1?.actionAtItemEnd = .None

//set a listener for when the video ends   
NSNotificationCenter.defaultCenter().addObserver(self,
        selector: "restartVideoFromBeginning",
        name: AVPlayerItemDidPlayToEndTimeNotification,
        object: player_1?.currentItem)


//function to restart the video
func restartVideoFromBeginning()  {

    //create a CMTime for zero seconds so we can go back to the beginning
    let seconds : Int64 = 0
    let preferredTimeScale : Int32 = 1
    let seekTime : CMTime = CMTimeMake(seconds, preferredTimeScale)

    player_1!.seekToTime(seekTime)

    player_1!.play()

}

答案 3 :(得分:22)

@Christopher Pickslay的答案更新为 Swift 4

func loopVideo(videoPlayer: AVPlayer) {
    NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: nil) { notification in
        videoPlayer.seek(to: CMTime.zero)
        videoPlayer.play()
    }
}

但是,正如我在下面提到他的回答,如果你有多个玩家,请务必将对象指定为AVPlayer的玩家项目。

答案 4 :(得分:20)

从iOS 10开始,无需使用通知来循环播放视频,只需使用AVPlayerLooper,就像这样:

Scanner jass=new Scanner(System.in);
while(userChoose != 1){
    //1.Add a course
    System.out.println("\nProvide a course code:");
    String courseCodeInput=jass.nextLine();
    ArrayList<String> onlyCCArray = new ArrayList<String>();
    onlyCCArray.add(courseCodeInput);

    System.out.println("\nProvide a course name:"); 
    String courseNameInput=jass.nextLine();
    ArrayList<String> codeNArray = new ArrayList<String>();
    codeNArray.add(courseNameInput);

    System.out.println("Would you like to [A]dd a new course or [R]eturn to the previous menu? ");
    String userChoice=jass.nextLine();

    for(int q=0;q<99;q++){
        if(userChoice.equals("a")||userChoice.equals("A")){
            userChoose=0;
            break;
        }else if(userChoice.equals("r")||userChoice.equals("R")){
            userChoose=1;
            break;
        }else{
            System.out.println("Invalid Input:");
        }
    }
}

确保在函数范围之外创建此循环器,以防函数返回时停止。

答案 5 :(得分:8)

我已经设法在swift 3中为OSX创建了一个无缝的视频循环。它应该可以在iOS上运行,并且对swift 2也几乎没有任何修改。

var player : AVQueuePlayer!

// Looping video initial call
internal func selectVideoWithLoop(url : URL)
{
    let asset = AVAsset(url: url)
    player.pause()
    let playerItem1 = AVPlayerItem(asset: asset)
    let playerItem2 = AVPlayerItem(asset: asset)
    player.removeAllItems()
    player.replaceCurrentItem(with: playerItem1)
    player.insert(playerItem2, after: playerItem1)
    player.actionAtItemEnd = AVPlayerActionAtItemEnd.advance
    player.play()

    let selector = #selector(ViewController.playerItemDidReachEnd(notification:))
    let name = NSNotification.Name.AVPlayerItemDidPlayToEndTime
    // removing old observer and adding it again for sequential calls. 
    // Might not be necessary, but I like to unregister old notifications.
    NotificationCenter.default.removeObserver(self, name: name, object: nil)
    NotificationCenter.default.addObserver(self, selector: selector, name: name, object: nil)
}

// Loop video with threadmill pattern
// Called by NotificationCenter, don't call directly
func playerItemDidReachEnd(notification: Notification)
{
    let item = player.currentItem!
    player.remove(item)
    item.seek(to: kCMTimeZero)
    player.insert(item, after: nil)
}

如果您想更改视频,只需再次使用其他网址调用selectVideoWithLoop。

答案 6 :(得分:5)

Swift 3.0:

首先检查视频终点: -

NotificationCenter.default.addObserver(self, selector: #selector(LoginViewController.playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem)



func videoDidReachEnd() {

        //now use seek to make current playback time to the specified time in this case (O)
        let duration : Int64 = 0 (can be Int32 also)
        let preferredTimeScale : Int32 = 1
        let seekTime : CMTime = CMTimeMake(duration, preferredTimeScale)
        player!.seek(to: seekTime)
        player!.play()
    }

答案 7 :(得分:0)

对话可能会晚一点,但是为了提高生气(以防万一有人再次来到这里),我找到了这个答案HERE(这是SO的另一个答案)。