iOS 在特定时间停止音频播放(AVAudioPlayer 结束时间)
Posted
技术标签:
【中文标题】iOS 在特定时间停止音频播放(AVAudioPlayer 结束时间)【英文标题】:iOS Stop Audio Playback At Certain Time (AVAudioPlayer End Time) 【发布时间】:2011-08-18 10:14:01 【问题描述】:我只想播放音频文件的一部分。这个音频文件包含 232 个口语单词,我有一本字典,其中包含每个单词的开始时间。所以我有开始和停止时间,我只是找不到在给定时间停止或播放文件一段时间的方法。任何可以帮助我的建议和/或示例代码将不胜感激,谢谢杰森。
所以我找到了解决方案,我如何获得 endTime 存在问题,但我确定我可以解决它。
//Prepare to play
[audioPlayer prepareToPlay];
//Get current time from the array using selected word
audioPlayer.currentTime = [[wordsDict objectForKey:selectedWord] floatValue];
//Find end time - this is a little messy for now
int currentIndex = 0;
int count = 0;
for (NSString* item in wordsKeys)
if ([item isEqualToString: selectedWord])
currentIndex = count+1;
count++;
//Store found end time
endTime = [[wordsDict objectForKey:[wordsKeys objectAtIndex:currentIndex]] floatValue];
//Start Timer
NSTimer * myAudioTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(checkCurrentTime)
userInfo:nil
repeats:YES]
//Now play audio
[audioPlayer play];
//Stop at endTime
- (void) checkCurrentTime
if(audioPlayer.playing && audioPlayer.currentTime >= endTime)
[audioPlayer stop];
【问题讨论】:
【参考方案1】:这应该做你想做的事。你不需要一个重复的计时器来让玩家崩溃。
NSString *myAudioFileInBundle = @"words.mp3";
NSTimeInterval wordStartsAt = 1.8;
NSTimeInterval wordEndsAt = 6.5;
NSString *filePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:myAudioFileInBundle];
NSURL *myFileURL = [NSURL fileURLWithPath:filePath];
AVAudioPlayer *myPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:myFileURL error:nil];
if (myPlayer)
[myPlayer setCurrentTime:wordStartsAt];
[myPlayer prepareToPlay];
[myPlayer play];
[NSTimer scheduledTimerWithTimeInterval:wordEndsAt-wordStartsAt target:myPlayer.autorelease selector:@selector(stop) userInfo:nil repeats:NO];
【讨论】:
这种将 NSTimer 设置为特定间隔的想法很好,对于其他任何做类似事情的人来说,如果您在播放期间实现一个擦洗条或任何改变 currentTime 值的东西,您将需要清除和重置NSTimer 事件到新的偏移量,相当于 wordEndsAt-mplayer.currentTime 这仍然不理想,因为 NSTimer 可能会及时滑倒并错过停止点。传入的间隔只能得到近似保证。对于音频,微秒时间很重要。 当然,这是一个实用的解决方案,但在任何情况下都不是理想的。有时您只需要权衡所需的努力与找到教科书式完美解决方案所获得的好处,而处理 98% 的情况就足够了。 你也可以使用 GCD:dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((wordEndsAt-wordStartsAt) * NSEC_PER_SEC)), self.playerQueue, ^ [weakSelf.audioPlayer stop]; );
【参考方案2】:
尝试使用 AVPlayer 并利用
addBoundaryTimeObserverForTimes:queue:usingBlock:
它的作用:在正常播放期间遍历指定时间时请求调用块。
https://developer.apple.com/library/prerelease/ios/documentation/AVFoundation/Reference/AVPlayer_Class/index.html#//apple_ref/occ/instm/AVPlayer/addBoundaryTimeObserverForTimes:queue:usingBlock:
【讨论】:
【参考方案3】:AVAudioPlayer
为您提供了一些可以使用的简洁属性:
currentTime
:在播放过程中,您可以依赖此属性。
playAtTime
:从预定义的时间开始播放。
但首先我会为此编写一些帮助程序:
@interface Word
double startTime;
double endTime;
@property double startTime;
@property double endTime;
@end
这只是一个简单地使用以下方法的类。
- (void)playWord:(Word *)aWord
self.avPlayer.playAtTime = aWord.startTime;
[avPlayer prepareToPlay];
[avPlayer play];
while (avPlayer.playing)
/*
This while loop could be dangerous as it could go on for a long time.
But because we're just evaluating words, it won't be as much power draining
*/
if(avPlayer.currentTime >= aWord.endTime;
[avPlayer stop];
我建议您使用数组或任何其他机制来自动切换到下一个单词。也许您还可以添加上一个和下一个按钮来处理用户输入。
如果这对你有用,请告诉我。
HTH
【讨论】:
是的,playAtTime 确实是一个漂亮的 METHOD,它可以做一些巧妙的技巧,但在这种情况下,它无助于实现 OP 想要做的事情。 playAtTime 不是一个属性,而是一个命令,它告诉播放器什么时候,相对于它的设备时钟,从媒体文件的开头(默认)开始播放,或者从之前分配给 currentTime 属性的时间开始播放。要停止它,只要您调用了 prepareToPlay,从发送到播放器停止方法的计时器中发出的一次信号就足够了。让它自动释放,计时器将保留播放器,直到它触发,然后……goneburger。看我的回答。以上是关于iOS 在特定时间停止音频播放(AVAudioPlayer 结束时间)的主要内容,如果未能解决你的问题,请参考以下文章