4

我遇到了AVPlayerItem和的问题AVQueuePlayer。目前我有很多 1-2 秒长的音乐文件和一个用于按顺序播放它们的队列播放器。

我想知道音乐文件何时开始播放,而不是何时完成播放(通过AVPlayerItemDidPlayToEndTimeNotification)。

这是因为我想在加载和播放新文件时运行一个函数。

我的代码:

 for (NSUInteger i = 0; i < [matchedAddr count]; i++)
{
    NSString *firstVideoPath = [[NSBundle mainBundle] pathForResource:[matchedAddr objectAtIndex:i] ofType:@"wav"];
    //NSLog(@"file %@",firstVideoPath);
    avitem=[AVPlayerItem playerItemWithURL:[NSURL fileURLWithPath:firstVideoPath]];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(currentItemIs:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:avitem];

    [filelist addObject:avitem];
}
 player = [AVQueuePlayer queuePlayerWithItems:filelist];
[player play];


- (void)currentItemIs:(NSNotification *)notification
{
    NSString *asd=[seqArray objectAtIndex:currentColor];
    currentColor=currentColor+1;
    AVPlayerItem *p = [notification object];
    [p seekToTime:kCMTimeZero];

    if([asd isEqual:@"1"])
    {
        [UIView animateWithDuration:0.01 animations:^{
           one.alpha = 0;
        } completion:^(BOOL finished) {

            [UIView animateWithDuration:0.01 animations:^{
               one.alpha = 1;
            }];
        }];
    }
}

如您所见,currentItemIsvoid 被调用,但它在曲目播放完毕时运行。我想在曲目开始时被调用。

编辑: 温斯顿片段的更新版本:

NSString * const kStatusKey         = @"status";

        [avitem addObserver:self
                              forKeyPath:kStatusKey
                                 options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                                 context:@"AVPlayerStatus"];
- (void)observeValueForKeyPath:(NSString *)path
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {

    if (context == @"AVPlayerStatus") {

        AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        switch (status) {
            case AVPlayerStatusUnknown: {

            }
                break;

            case AVPlayerStatusReadyToPlay: {
                // audio will begin to play now.
                NSLog(@"PLAU");
                [self playa];
            }
                break;
        }
    }
}
4

2 回答 2

5

首先,您需要将您的注册AVPlayerItem观察者

[self.yourPlayerItem addObserver:self
                      forKeyPath:kStatus
                         options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                         context:AVPlayerStatus];

然后在您的播放器Key Value Observer方法上,您需要检查AVPlayerStatusReadyToPlay status,如下所示:

- (void)observeValueForKeyPath:(NSString *)path
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {

     if (context == AVPlayerStatus) {

        AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        switch (status) {
            case AVPlayerStatusUnknown: {

            }
            break;

            case AVPlayerStatusReadyToPlay: {
                // audio will begin to play now.
            }
            break;
   }
}
于 2014-04-16T19:40:01.327 回答
3

以下应该工作:

观察玩家的状态:

let playerItem: AVPlayerItem = AVPlayerItem(asset: videoPlusSubtitles, automaticallyLoadedAssetKeys: requiredAssetKeys)

playerItem.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [], context: nil)

player = AVPlayer(playerItem: playerItem)

响应状态变化:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == #keyPath(AVPlayerItem.status) {
        let status: AVPlayerItem.Status

        if let statusNumber = change?[.newKey] as? NSNumber {
            status = AVPlayerItem.Status(rawValue: statusNumber.intValue)!
        } else {
            status = .unknown
        }

        // Switch over status value
        switch status {
        case .readyToPlay:
            print("Player item is ready to play.")
            break
        case .failed:
            print("Player item failed. See error")
            break
        case .unknown:
            print("Player item is not yet ready")
            break
        @unknown default:
            fatalError()
        }
    }
}
于 2020-03-07T07:53:25.940 回答