ios - AVPlayer 在更新进度 slider 时导致崩溃,断言失败 -[AVPlayerPeriodicCaller initWithPlayer :interval:queue:block:]

标签 ios ios6 avfoundation avplayer

我在应用程序中遇到错误

" Assertion failure in -[AVPlayerPeriodicCaller initWithPlayer:interval:queue:block:], /SourceCache/EmbeddedAVFoundation/EmbeddedAVFoundation-461.12/Fig/AVPlayer.m:3993

 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: CMTIME_COMPARE_INLINE(interval, >, kCMTimeZero)'

知道为什么会发生这种情况吗?

我只能使用 AvPlayer,因为我需要流式传输大文件。AVaudioplayer 不是一个选项。所以我还实现了一个 scrubber slider 。我的AVplayer实现如下:

-(void)playAudioForFile:(NSString *)fileName{

    [self.suraPlayer removeTimeObserver:playbackObserver];
    [self.suraPlayer removeTimeObserver:mTimeObserver];
    self.suraPlayer = nil;

NSURL* url = [self getURLStringForFileName:fileName];

AVPlayer *player = [[AVPlayer alloc]initWithURL:url];

self.suraPlayer = player;

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playerItemDidReachEnd:)
                                             name:AVPlayerItemDidPlayToEndTimeNotification
                                           object:[suraPlayer currentItem]];


[self.suraPlayer play];



[self.suraPlayer addObserver:self forKeyPath:@"status" options:0 context:nil];

[self initScrubberTimer];

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateProgress) userInfo:nil repeats:YES];

//[self metadataForAsset:self.suraPlayer.currentItem.asset];

-(void)updateProgress {



   // NSLog(@"self.mScrubber.value %f", self.mScrubber.value);

//这是调试器有时会卡住的行

float duration = CMTimeGetSeconds(self.suraPlayer.currentItem.duration);

    if (self.suraPlayer.currentItem.status==AVPlayerStatusReadyToPlay )
        [self.mScrubber setMaximumValue:duration];


    self.mScrubber.value = CMTimeGetSeconds(self.suraPlayer.currentTime);

    int seconds = self.mScrubber.value, minutes = seconds/60,hours = minutes/60;

    int secondsRemain = self.mScrubber.maximumValue - seconds,minutesRemain = secondsRemain/60,hoursRemain = minutesRemain/60;

    seconds = seconds-minutes*60;

    minutes = minutes-hours*60;

    secondsRemain = secondsRemain - minutesRemain*60;

    minutesRemain = minutesRemain - hoursRemain*60;

    NSString *hourStr,*minuteStr,*secondStr,*hourStrRemain,*minuteStrRemain,*secondStrRemain;

    hourStr = hours > 9 ? [NSString stringWithFormat:@"%d",hours] : [NSString stringWithFormat:@"0%d",hours];

    minuteStr = minutes > 9 ? [NSString stringWithFormat:@"%d",minutes] : [NSString stringWithFormat:@"0%d",minutes];

    secondStr = seconds > 9 ? [NSString stringWithFormat:@"%d",seconds] : [NSString stringWithFormat:@"0%d",seconds];

    hourStrRemain = hoursRemain > 9 ? [NSString stringWithFormat:@"%d",hoursRemain] : [NSString stringWithFormat:@"0%d",hoursRemain];

    minuteStrRemain = minutesRemain > 9 ? [NSString stringWithFormat:@"%d",minutesRemain] : [NSString stringWithFormat:@"0%d",minutesRemain];

    secondStrRemain = secondsRemain > 9 ? [NSString stringWithFormat:@"%d",secondsRemain] : [NSString stringWithFormat:@"0%d",secondsRemain];

    self.timePlayerLabel.text = [NSString stringWithFormat:@"%@:%@:%@",hourStr,minuteStr,secondStr];

    self.timeRemainingLabel.text = [NSString stringWithFormat:@"-%@:%@:%@",hourStrRemain,minuteStrRemain,secondStrRemain];

}



-(void)initScrubberTimer
{

    double interval = .1f;

    CMTime playerDuration = self.suraPlayer.currentItem.duration;
    if (CMTIME_IS_INVALID(playerDuration))
    {
        return;
    }

    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration))
    {
        CGFloat width = CGRectGetWidth([self.mScrubber bounds]);
        interval = 0.5f * duration / width;
    }

    /* Update the scrubber during normal playback. */


    mTimeObserver = [self.suraPlayer addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC)
                                                                  queue:NULL /* If you pass NULL, the main queue is used. */
                                                             usingBlock:^(CMTime time)
                     {

                     }];
    [self syncScrubber];
}

/* Set the scrubber based on the player current time. */
- (void)syncScrubber
{
    CMTime playerDuration = self.suraPlayer.currentItem.duration;
    if (CMTIME_IS_INVALID(playerDuration))
    {
        self.mScrubber.minimumValue = 0.0;
        return;
    }

    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration))
    {
        float minValue = [self.mScrubber minimumValue];
        float maxValue = [self.mScrubber maximumValue];
        double time = CMTimeGetSeconds([self.suraPlayer currentTime]);

        [self.mScrubber setValue:(maxValue - minValue) * time / duration + minValue];
    }
}

/* The user is dragging the movie controller thumb to scrub through the movie. */

/* Set the player current time to match the scrubber position. */
- (IBAction)scrub:(id)sender
{
    if ([sender isKindOfClass:[UISlider class]])
    {
        UISlider* slider = sender;

        CMTime playerDuration = self.suraPlayer.currentItem.duration;
        if (CMTIME_IS_INVALID(playerDuration)) {
            return;
        }

        double duration = CMTimeGetSeconds(playerDuration);
        if (isfinite(duration))
        {
            float minValue = [slider minimumValue];
            float maxValue = [slider maximumValue];
            float value = [slider value];

            double time = duration * (value - minValue) / (maxValue - minValue);

            [self.suraPlayer seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC)];
        }
    }
}

- (IBAction)beginScrubbing:(id)sender {



    mRestoreAfterScrubbingRate = [self.suraPlayer rate];
    [self.suraPlayer setRate:0.f];

    /* Remove previous timer. */
    [self removePlayerTimeObserver];
}

/* The user has released the movie thumb control to stop scrubbing through the movie. */

- (IBAction)endScrubbing:(id)sender {

    __weak typeof(self) weakSelf = self;

    if (!mTimeObserver)
    {


        CMTime playerDuration = self.suraPlayer.currentItem.duration;
        if (CMTIME_IS_INVALID(playerDuration))
        {
            return;
        }

        double duration = CMTimeGetSeconds(playerDuration);
        if (isfinite(duration))
        {
            CGFloat width = CGRectGetWidth([self.mScrubber bounds]);
            double tolerance = 0.5f * duration / width;

            mTimeObserver = [self.suraPlayer addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(tolerance, NSEC_PER_SEC) queue:NULL usingBlock:
                             ^(CMTime time)
                             {
                                 [weakSelf syncScrubber];
                             }];
        }
    }

    if (mRestoreAfterScrubbingRate)
    {
        [self.suraPlayer setRate:mRestoreAfterScrubbingRate];
        mRestoreAfterScrubbingRate = 0.f;
    }

}

- (BOOL)isScrubbing
{
    return mRestoreAfterScrubbingRate != 0.f;
}

-(void)enableScrubber
{
    self.mScrubber.enabled = YES;
}

-(void)disableScrubber
{
    self.mScrubber.enabled = NO;
}


-(void)removePlayerTimeObserver
{
    if (mTimeObserver)
    {
        [self.suraPlayer removeTimeObserver:mTimeObserver];
        mTimeObserver = nil;
    }
}

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

    if (object == suraPlayer && [keyPath isEqualToString:@"status"]) {
        if (suraPlayer.status == AVPlayerStatusFailed) {
            NSLog(@"AVPlayer Failed");

        } else if (suraPlayer.status == AVPlayerStatusReadyToPlay) {
            NSLog(@"AVPlayerStatusReadyToPlay");

            //   NSLog(@"Common MetaData %@",   self.suraPlayer.currentItem.asset.commonMetadata);


            AVAsset * asset = self.suraPlayer.currentItem.asset;

            [self metadataForAsset:asset];

        } else if (suraPlayer.status == AVPlayerItemStatusUnknown) {
            NSLog(@"AVPlayer Unknown");

        }
    }
}
- (NSString *)titleForAsset:(AVAsset *)asset{

    NSArray *titles = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
    AVMetadataItem *title;
    NSString * currentTitle;

    if(titles.count>0)
    {
        title= [titles objectAtIndex:0];
        currentTitle= [title.value copyWithZone:nil];
    }

    if (self.suraPlayer.currentItem.asset != asset)
        asset = nil;

    return currentTitle;
}

- (void)metadataForAsset:(AVAsset *)asset{

    self.artWorkImage.image = [UIImage imageNamed:@"Colorful-Burst-iPad-wallpaper-ilikewallpaper_com.jpg"];

    NSArray *titles = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
    NSArray *artists = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyArtist keySpace:AVMetadataKeySpaceCommon];
    NSArray *albumNames = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyAlbumName keySpace:AVMetadataKeySpaceCommon];

    AVMetadataItem *artist;
    AVMetadataItem *title;
    AVMetadataItem *albumName;
    NSString * currentTitle;
    NSString * currentArtist;
    NSString * currentAlbumName;

    if(titles.count>0)
    {
        title= [titles objectAtIndex:0];
        currentTitle= [title.value copyWithZone:nil];
        self.audioTitle.text = currentTitle;

    }

    if(artists.count>0)
    {
        artist= [artists objectAtIndex:0];
        currentArtist   = [artist.value copyWithZone:nil];
    }

    if (albumNames.count>0){
        albumName= [albumNames objectAtIndex:0];
        currentAlbumName = [albumName.value copyWithZone:nil];

    }






    NSArray *keys = [NSArray arrayWithObjects:@"commonMetadata", nil];
    [asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
        NSArray *artworks = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata
                                                           withKey:AVMetadataCommonKeyArtwork
                                                          keySpace:AVMetadataKeySpaceCommon];

        for (AVMetadataItem *item in artworks) {
            if ([item.keySpace isEqualToString:AVMetadataKeySpaceID3]) {
                NSDictionary *d = [item.value copyWithZone:nil];
                self.artWorkImage.image  = [UIImage imageWithData:[d objectForKey:@"data"]];
            } else if ([item.keySpace isEqualToString:AVMetadataKeySpaceiTunes]) {
                self.artWorkImage.image = [UIImage imageWithData:[item.value copyWithZone:nil]];
            }
        }
    }];




}


- (void)playerItemDidReachEnd:(NSNotification *)notification {

    //  code here to play next sound file
    if (indexOfSelectedItem<self.filteredAudiosArray.count){
        indexOfSelectedItem = indexOfSelectedItem+1;
        [self playAudioForFile:[self.filteredAudiosArray objectAtIndex:indexOfSelectedItem]];
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:indexOfSelectedItem inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
    }

}

- (IBAction)sliderValueChangedForDuration:(id)sender {
    if ([sender isKindOfClass:[UISlider class]])
    {
        UISlider* slider = sender;

        CMTime playerDuration = self.suraPlayer.currentItem.duration;
        if (CMTIME_IS_INVALID(playerDuration)) {
            return;
        }

        double duration = CMTimeGetSeconds(playerDuration);
        if (isfinite(duration))
        {
            float minValue = [slider minimumValue];
            float maxValue = [slider maximumValue];
            float value = [slider value];

            double time = duration * (value - minValue) / (maxValue - minValue);

            [self.suraPlayer seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC)];
        }
    }

}

最佳答案

比赛晚了,但万一其他人遇到这个问题,我遇到了这个问题,因为我为定期观察者设置时间间隔的方式。

更改为:

CMTime interval = CMTimeMake(33, 1000);

让事情对我有用。

关于ios - AVPlayer 在更新进度 slider 时导致崩溃,断言失败 -[AVPlayerPeriodicCaller initWithPlayer :interval:queue:block:],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18224913/

相关文章:

ios - TableView Controller 中的第二个自定义单元格生成错误

objective-c - iOS、C# 中的 UI 设计

ios - 从图层重新加载 tableView 时崩溃

iphone - 在横向和水平 iPhone 位置下使用 ZBarReader 拍照时出现问题

ios6 - 如何在我的应用程序 iOS 6 中获取行车路线

iphone - 使用 AVFoundation 捕获视频不会捕获任何音频

ios - AVPlayerItem 初始 timedMetadata 未被观察(KVO)

ios - 当我使用 installTap(onBus 进行多声道音频?

iOS purgeIdleCellConnections

javascript - 如何使本地 APNS 推送通知静音?