MP3队列播放器 - 加载后台线程?

时间:2017-01-20 03:49:32

标签: ios objective-c audio avplayer avqueueplayer

我有一个AVQueuePlayer,用于播放来自互联网(http)的MP3歌曲列表。我还需要知道哪首歌正在播放。当前的问题是加载歌曲会导致延迟,在等待歌曲加载时阻塞主线程(第一首歌曲以及第一首歌曲在完成首播后的连续歌曲)。

以下代码阻止主线程:

queuePlayer = [[AVQueuePlayer alloc] init];
[queuePlayer insertItem: [AVPlayerItem playerItemWithURL:url] afterItem: nil]; // etc.
[queuePlayer play]

我正在寻找一种创建MP3播放列表的方法,其中下一个要播放的文件会在后台预先加载。

我尝试了以下代码:

NSArray* tracks = [NSArray arrayWithObjects:@"http://example.com/song1.mp3", @"http://example.com/song2.mp3", @"http://example.com/song3.mp3", nil];

for (NSString* trackName in tracks)
{
    AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:[NSURL URLWithString:trackName]
                                                    options:nil];

    AVMutableCompositionTrack* audioTrack = [_composition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                      preferredTrackID:kCMPersistentTrackID_Invalid];

    NSError* error;
    [audioTrack insertTimeRange:CMTimeRangeMake([_composition duration], audioAsset.duration)
                        ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0]
                         atTime:kCMTimeZero
                          error:&error];

    if (error)
    {
        NSLog(@"%@", [error localizedDescription]);
    }

    // Store the track IDs as track name -> track ID
    [_audioMixTrackIDs setValue:[NSNumber numberWithInteger:audioTrack.trackID]
                         forKey:trackName];

}

_player = [[AVPlayer alloc] initWithPlayerItem:playerItem];

[_player play];

问题在于我不确定如何检测下一首歌何时开始播放。此外,文档不会指定是否预先加载MP3文件。

我正在寻找一个解决方案:

  • 在播放之前通过在后台预先加载MP3播放MP3(理想情况下,在当前歌曲播放完毕之前开始加载下一首歌曲,以便在当前歌曲播放完毕后立即播放)
  • 请允许我查看当前播放的歌曲。

1 个答案:

答案 0 :(得分:1)

AVFoundation有一些课程专门用于完成您正在寻找的课程。

您当前的解决方案似乎是构建一个AVPlayerItem来连接您要播放的所有MP3文件。更好的解决方案是创建一个AVQueuePlayer,其中包含您要播放的AVPlayerItem个对象数组。

NSArray* tracks = [NSArray arrayWithObjects:@"http://example.com/song1.mp3", @"http://example.com/song2.mp3", @"http://example.com/song3.mp3", nil];
NSMutableArray *playerItems = [[NSMutableArray alloc] init];

for (NSString* trackName in tracks)
{
    NSURL *assetURL = [NSURL URLWithString:trackName];
    if (!assetURL) {
        continue;
    }

    AVURLAsset* audioAsset = [[AVURLAsset alloc] initWithURL:assetURL
                                                     options:nil];
    AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:audioAsset];
    [playerItems addObject:playerItem];
}

_player = [[AVQueuePlayer alloc] initWithItems:playerItems];

[_player play];

回答你的最终总结问题:

  • 是的,AVQueuePlayer DOES 在播放当前播放列表时预先加载播放列表中的下一个项目。
  • 您可以访问currentItem媒体资源,以确定当前正在播放的AVPlayerItem