ios – AVPlayer在更新进度滑块时导致崩溃,其中Assertion失败 – [AVPlayerPeriodicCaller initWithPlayer:interval:queue:blo
2019年07月06日
作者:佚名
我在应用程序中收到错误
" 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滑块.我对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在更新进度滑块时导致崩溃,其中Assertion失败 – [AVPlayerPeriodicCaller initWithPlayer:interval:queue:block:]全部内容,希望文章能够帮你解决ios – AVPlayer在更新进度滑块时导致崩溃,其中Assertion失败 – [AVPlayerPeriodicCaller initWithPlayer:interval:queue:block:]所遇到的程序开发问题。
如果觉得来客网网站内容还不错,欢迎将来客网网站推荐给程序员好友。