首页 文章

如何在iOS上以及以毫秒为单位播放mp3?

提问于
浏览
0

我要求从特定时间播放mp3 [以毫秒为单位] . 经过一些研究,我的赌注是AVPlayer,这似乎是每个有类似要求的人的选择 . 不幸的是,它不起作用[代码包括在最后] . 我想知道是否还有其他任何我可以使用任何iOS支持的文件格式,使用毫秒时间刻度指定启动和停止?

这是我使用AVPlayer的代码 . 我创建了一个mp3,它在4.3秒内静音约600ms,然后噪音大约一秒钟 . 我有3个选项来创建CMTime以与seekToTime一起使用:

  • 4300值,1000时标

  • 4.3 * 60000,60000时标

  • 4.3 * mp3文件的时间刻度,带有mp3文件的时间刻度 .

不幸的是,没有一个选项适合我,它总是设置在噪音内部的某个地方 .

我试图使用较低的值,只是为了它 . 我得到3.7秒,在设定之后,在沉默之前开始一点点 . 有趣的是:如果我使用3.75,它将开始在噪音中间播放 .

Crucial parts of the code:

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);

Full code

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

Example project

您可以从这里获取我的项目,包括我用于测试的mp3文件 . 只需在文本字段中键入4.3即可 .

https://www.dropbox.com/s/7q2xmuhdu1xih75/iosAudioTest.zip?dl=0

EDIT:

更新mp3文件后 - 将其缩短 - 用于到达同一位置的值发生了变化 . 现在4.3点到其他地方:/现在我对seekToTime方法的操作完全无能为力 .

1 回答

  • 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个不同位置中的任何一个 .

相关问题