2015-01-06 27 views
40

Câu hỏi đơn giản Tôi dường như không thể tìm thấy câu trả lời cho một số lý do.Làm thế nào để bạn lặp AVPlayer trong Swift?

Làm thế nào để bạn lặp AVPlayer trong Swift?

numberOfLoops = -1 chỉ hoạt động cho AVAudioPlayer

Tôi cần nó để lặp mà không dán đoạn/flash đen vv Đó là lý do tại sao tôi không sử dụng MPMoviePlayerViewController.

Cảm ơn bạn đã được trợ giúp.

Code:

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

AVPlayer sử dụng thông báo thay vì thuộc tính. Về cơ bản, bạn cần lắng nghe video đã kết thúc sự kiện và sau đó tìm kiếm phần đầu của video. Đây là một ví dụ (mục tiêu c, nhưng bạn có ý tưởng): http://stackoverflow.com/questions/5361145/looping-a-video-with-avfoundation-avplayer – Msencenb

Trả lời

19

OK Tôi đã làm việc nó ra. Cảm ơn Msencenb đã chỉ cho tôi đúng hướng với câu trả lời C Mục tiêu.

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

} 
85

Swift 3

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

Swift 2

Sau AVPlayerItem được cấu hình và máy nghe nhạc được tạo ra:

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

Bạn có thể thêm vào trong 'hàng đợi:.main' và sau đó bạn sẽ không cần phải gửi lên hàng đợi chính. –

+0

Câu trả lời thực sự là những câu trả lời khác không hiệu quả với tôi (nhanh chóng 3). – changbenny

+0

lần đầu tiên cuộc gọi thông báo này sau 5 giây. Làm thế nào để xử lý này? –

19

Ngoài ra, bạn có thể sử dụng block dựa trên NSNotificationCe nter API:

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

Câu trả lời hay, rất đơn giản. Nếu bạn có nhiều người chơi, hãy đảm bảo bạn chỉ định AVPlayer làm thông số "đối tượng", nếu không mọi người chơi đã đăng ký sẽ nhận được thông báo khi người chơi hoàn tất. –

+0

Tôi đang phát video trong trình phát và video đang chạy ở chế độ nền và khi tôi muốn phát một video khác nhưng không phát video của mình –

+1

Chỉnh sửa câu trả lời của @BenStahl, bạn phải chỉ định 'AVPlayerItem' là " đối tượng "thay vì' AVPlayer'. Vì vậy, nó phải là 'videoPlayer.currentItem' –

5

tôi đã quản lý để tạo ra một video liền mạch vòng lặp cho OSX trong nhanh chóng 3. Nó sẽ làm việc trên iOS và với thay đổi nhỏ trên nhanh chóng 2 là tốt.

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

Khi bạn muốn thay đổi video, chỉ cần gọi chọnVideoWithLoop với một url khác một lần nữa.

+0

Cảm ơn, điều này làm việc cho tôi! – Jagie

+0

Bạn được chào đón;) –

13

câu trả lời @Christopher Pickslay của cập nhật cho Swift 3:

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

Nhưng, như tôi đã đề cập bên dưới câu trả lời của mình, hãy chắc chắn để xác định các đối tượng như mục chơi của AVPlayer nếu bạn có nhiều người chơi.

4

Swift 3.0:

séc đầu tiên cho điểm cuối video: -

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

Bắt đầu từ iOS 10, không có nhu cầu sử dụng thông báo để lặp một đoạn video, bạn chỉ cần sử dụng một AVPlayerLooper, chỉ cần như thế này :

let asset = AVAsset(url: videoURL) 
let item = AVPlayerItem(asset: asset) 
let player = AVQueuePlayer(playerItem: item) 
videoLooper = AVPlayerLooper(player: player, templateItem: item) 

đảm bảo rằng looper này được tạo bên ngoài phạm vi chức năng, trong trường hợp nó dừng khi chức năng trả về.

+1

cảm ơn Chúa vì điều này. 'KVO' chỉ đơn giản là một cách thức làm việc. – Annjawn

Các vấn đề liên quan