iOS在特定时间停止音频播放(AVAudioPlayer结束时间)

6
我想播放音频文件的一部分。这个音频文件包含232个口语单词,我有一个字典,里面包含每个单词的开始时间。所以我有开始和结束时间,只是找不到在给定时间停止或播放一定时长的方法。如果有任何建议和/或示例代码可以帮助我,将不胜感激,谢谢Jason。
所以我已经找到了一个解决方案,我得到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];
}
3个回答

12

这应该能够满足你的需求。你不需要一个反复触发的定时器来干扰播放器。

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设置为特定间隔的想法很好,对于其他人做类似事情的人来说,如果您实现了一个scrub-bar或任何在播放过程中更改currentTime值的东西,您需要清除并重置NSTimer事件到新的偏移量,这相当于wordEndsAt-mplayer.currentTime。 - JamesB
这仍然不是理想的,因为 NSTimer 可能会在时间上滑动并错过停止点。传入的间隔只有近似保证。对于音频来说,微秒时间很重要。 - chakrit
当然,这是一种实用的解决方案,并不是在每种情况下都是理想的。有时候你必须权衡所需的努力和找到完美解决方案所带来的收益,当一些能够处理98%的情况的东西已经足够了。 - unsynchronized
你也可以使用GCD:dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((wordEndsAt-wordStartsAt) * NSEC_PER_SEC)), self.playerQueue, ^ { [weakSelf.audioPlayer stop]; }); - Massmaker

5

-4

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];
    }
}

我建议您使用数组或其他机制来自动切换到下一个单词。也许您还可以添加上一个和下一个按钮来处理用户输入。
如果这对您有用,请告诉我。
希望能帮到您。

是的,playAtTime是一个很棒的方法,可以做出很多有趣的效果,但在这种情况下,它无法帮助实现OP想要做的事情。playAtTime不是一个属性,而是一个命令,告诉播放器何时相对于设备时钟从媒体文件的开头(默认)或先前分配给currentTime属性的时间开始播放。要停止它,只需调用prepareToPlay,然后从定时器发送到播放器的stop方法中发出单个触发即可。将其设置为自动释放,定时器将保留播放器直到触发,然后...消失。请参见我的答案。 - unsynchronized

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接