我要求从特定时间播放mp3 [以毫秒为单位]。 经过一些研究,我的赌注是AVPlayer,这似乎是每个有类似要求的人的选择。 不幸的是,它不起作用[代码包括在最后]。 我想知道是否有其他任何我可以用来播放任何iOS支持的文件格式的东西,包括start&使用毫秒时间刻度指定停止?
这是我使用AVPlayer的代码。我创建了一个mp3,它在4.3秒内静音约600ms,然后噪音大约一秒钟。 我有3个选项来创建CMTime以与seekToTime一起使用:
不幸的是,没有一个选项适合我,它总是设置在噪音内的某个地方。
我试图使用较低的值,仅仅是为了它。 我得到3.7秒,在设定之后,在沉默之前开始一点点。 有趣的是:如果我使用3.75,它将在噪音中间开始播放。
代码的关键部分:
CMTime声明:
mediaAudioStart = CMTimeMake((int64_t) (floatValue * 60000), 60000);
或
int32_t timeScale = _mediaAudioPlayer.currentItem.asset.duration.timescale;
mediaAudioStart = CMTimeMake((int64_t) (floatValue * timeScale), timeScale);
或
mediaAudioStart = CMTimeMake(4300, 1000);
完整代码
seekToTime的用法:
[_mediaAudioPlayer seekToTime:mediaAudioStart toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
if (finished) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mediaAudioPlaybackFinished) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
NSLog(@"CURRENT TIME: %lld", _mediaAudioPlayer.currentTime.value);
[_mediaAudioPlayer play];
} else {
NSLog(@"Could not seek media overlay file.");
}
}];
ViewController.m
- (void)prepareMediaAudio {
NSLog(@"prepareMediaAudio");
NSString *mediaAudioPath = [[NSBundle mainBundle] pathForResource:@"boostmiddle" ofType:@"mp3"];
NSURL *mediaAudioURL = [[NSURL alloc] initFileURLWithPath:mediaAudioPath];
if (!_mediaAudioPlayer) {
AVPlayer *player = [AVPlayer playerWithURL:mediaAudioURL];
[self setMediaAudioPlayer:player];
[_mediaAudioPlayer addObserver:self forKeyPath:@"status" options:0 context:nil];
} else {
[self mediaAudioSeek];
}
}
- (void)stopMediaAudio {
NSLog(@"stopMediaAudio");
if (_mediaAudioPlayer) {
[_mediaAudioPlayer removeObserver:self forKeyPath:@"status"];
[_mediaAudioPlayer pause];
_mediaAudioPlayer = nil;
}
}
- (void)mediaAudioSeek {
NSLog(@"mediaAudioSeek %lld %d", mediaAudioStart.value, mediaAudioStart.timescale);
[_mediaAudioPlayer seekToTime:mediaAudioStart toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
if (finished) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mediaAudioPlaybackFinished) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
NSLog(@"CURRENT TIME: %lld", _mediaAudioPlayer.currentTime.value);
[_mediaAudioPlayer play];
} else {
NSLog(@"Could not seek media overlay file.");
}
}];
}
- (void)mediaAudioPlaybackFinished {
NSLog(@"mediaAudioPlaybackFinished");
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
[self stopMediaAudio];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
NSLog(@"observeValueForKeyPath");
if (object == _mediaAudioPlayer && [keyPath isEqualToString:@"status"]) {
if (_mediaAudioPlayer.status == AVPlayerStatusReadyToPlay) {
NSLog(@"READY TO PLAY");
} else if (_mediaAudioPlayer.status == AVPlayerStatusFailed) {
NSLog(@"Could not load Media Overlay audio");
}
}
}
- (IBAction)button1Action:(id)sender {
NSString *value = valueText.text;
float floatValue = [value floatValue];
NSLog(@"button1Action %f", floatValue);
mediaAudioStart = CMTimeMake((int64_t) (floatValue * 60000), 60000);
[self mediaAudioSeek];
}
- (IBAction)button2Action:(id)sender {
NSString *value = valueText.text;
float floatValue = [value floatValue];
NSLog(@"button2Action %f", floatValue);
int32_t timeScale = _mediaAudioPlayer.currentItem.asset.duration.timescale;
mediaAudioStart = CMTimeMake((int64_t) (floatValue * timeScale), timeScale);
[self prepareMediaAudio];
}
- (IBAction)button3Action:(id)sender {
NSLog(@"button3Action [4300, 1000]");
mediaAudioStart = CMTimeMake(4300, 1000);
[self prepareMediaAudio];
}
- (IBAction)stopAction:(id)sender {
[self stopMediaAudio];
}
- (IBAction)prepareAction:(id)sender {
[self prepareMediaAudio];
}
示例项目
您可以从这里获取我的项目,包括我用于测试的mp3文件。只需在文本字段中输入4.3。
https://www.dropbox.com/s/7q2xmuhdu1xih75/iosAudioTest.zip?dl=0
修改
更新mp3文件后 - 缩短 - 用于到达同一地点的值发生了变化。现在4.3点到其他地方:/现在我对seekToTime方法的操作完全无能为力。
答案 0 :(得分:1)
https://warrenmoore.net/understanding-cmtime
以上帖子对我遇到的CMTime有最清晰的描述。你在解释它是错的我害怕。如果你想要跳4.3秒,你需要CMTime为(4.3,60000),其中4.3是秒数,60000是你每秒所需的精度。
[av_player seekToTime:CMTimeMakeWithSeconds(4.3, 60000) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
会将CMTime设置为4.3秒,精度为60000 - 这意味着您可以在每秒之间跳转到60000个不同位置中的任何一个。