2013-02-18 64 views
6

我使用AVQueuePlayer來播放從URL加載的電影序列。
我試圖用我需要玩的所有AVPlayerItems的數組初始化玩家實例。AVQueuePlayer播放沒有間隙和凍結

player = [[AVQueuePlayer queuePlayerWithItems:playerItemsArray] 

但是,在這種情況下AVQueuePlayer負載的每一個AVPlayerItem的開始播放前一些初始部分。它會導致令人沮喪的凍結,並且應用程序在幾秒內不會響應。

有可能僅第一AVPLayerItem添加到播放器的隊列中,觀察其狀態,並在隊列中添加第二個項目,只有當第一將達結束,但在這種情況下,會有引起的初始化和兩個項目的播放之間的間隙緩衝第二個AVPlayerItem

有什麼辦法可以組織無縫播放多個視頻而不會凍結?
我是否應該爲此目的使用其他玩家?

在此先感謝。

回答

14

找到了解決辦法。

AVQueuePlayer的隊列中添加新的AVPlayerItem時,玩家將同步等待,直到玩家項目的初始部分將被緩衝。

所以在這種情況下,玩家項目應該被異步緩衝,之後它可以被添加到隊列中。
它可以使用[AVURLAsset loadValuesAsynchronouslyForKeys: completionHandler:]

例如來完成:

AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil]; 
NSArray *keys = [NSArray arrayWithObject:@"playable"]; 

[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() 
{ 
    dispatch_async(dispatch_get_main_queue(),^
    { 
     AVPlayerItem *playerItem = [[[AVPlayerItem alloc] initWithAsset:asset] autorelease];   
     [player insertItem:playerItem afterItem:nil]; 
    }); 

}]; 

使用AVQueuePlayer的該溶液隊列可以與沒有任何間隙和凍結的物品進行填充。

+3

嗨yury.ku,我們有您已經發布有什麼相同的問題。我們創建了一個示例應用程序來測試它。一旦將它加載到didEndPlay:notification API中,我們就添加新的播放器項目。但是我們仍然面臨一些UI凍結問題。你能提供更多關於你如何解決這個問題的信息嗎? – nkd 2013-09-11 08:10:17

+4

這個解決方案對我來說也不起作用,音軌之間的差距仍然很小 – 2015-04-07 21:36:25

+1

根據[AVFoundation Programming Guide](https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/ 02_Playback.html#// apple_ref/doc/uid/TP40010188-CH3-SW3):'嘗試使用URL初始化AVURLAsset,然後加載其跟蹤密鑰。 如果曲目加載成功,則爲資產創建播放器項目。 '。所以,你應該使用'NSArray * keys = [NSArray arrayWithObject:@「tracks」];'而不是。 – 2015-10-13 21:09:53

-1

這裏是解決方案。

- (void)_makePlayer{ 
    _player = [[AVQueuePlayer alloc] initWithPlayerItem:[AVPlayerItem playerItemWithAsset:[SSMoviePreviewItemMaker generateAVMovieItem]]]; 
} 

+ (AVAsset *)generateAVMovieItem{ 
    NSArray * array = [SSMovieFileManager getAllMovieResourceURL]; 
    AVMutableComposition *composition = [[AVMutableComposition alloc] init]; 
    for (int i = 0; i < array.count; i++) { 
     AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:array[i] options:nil]; 
     [composition insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) 
          ofAsset:asset 
           atTime:composition.duration error:nil]; 

    } 
    return composition; 
} 
1

在斯威夫特2,在這裏工作:

func load() { 
    let player = AVQueuePlayer() 
    for url in urls { 
     makeItem(url) 
    } 
} 

func makeItem(url: String) { 
    let avAsset = AVURLAsset(URL: NSURL(string: url)!) 

    avAsset.loadValuesAsynchronouslyForKeys(["playable", "tracks", "duration"], completionHandler: { 
     dispatch_async(dispatch_get_main_queue(), { 
      self.enqueue(avAsset: avAsset) 
     }) 
    }) 
} 

func enqueue(avAsset: AVURLAsset) { 
    let item = AVPlayerItem(asset: avAsset) 
    self.player.insertItem(item, afterItem: nil) 
} 
+4

這個「有效」,但沒有考慮到某些資產加載速度可能比其他資產更快的可能性,因此不能保證它們的插入順序。如果回放順序不是一個問題,這很好用! – user1171911 2016-02-05 21:23:34

+0

@ user1171911我遇到了同樣的問題。你能建議一個解決方案來維持播放順序嗎?提前致謝。 – hyd00 2016-06-12 11:26:42