6

我正在尝试实现基于 AVPlayer + AVAudioMix + AVAudioMixInputParameters 的淡入效果。它基本上可以工作,除非在启动我的应用程序后第一次播放音频时,开始时会单击。后续的播放虽然完美,但第一次出现的故障非常稳定且可重现。

我的播放按钮仅在 AVPlayerItemstatus设置为就绪后启用,因此在播放器未就绪时无法触发播放方法。事实上,在加载音频文件并构建所有对象后等待多长时间并不重要。

这发生在 OS X 上,我还没有在 iOS 上测试过。

请注意,对于此测试,您需要一个以声音而不是静音开头的音频文件。这是我没有 GUI 部分的精简代码(testFadeIn是入口点):

static AVPlayer* player;
static void* PlayerItemStatusObserverContext = &PlayerItemStatusObserverContext;

- (void)testFadeIn
{
    AVURLAsset* asset = [AVURLAsset.alloc initWithURL:[NSURL fileURLWithPath:@"Helicopter.m4a"] options:@{AVURLAssetPreferPreciseDurationAndTimingKey: @YES}];
    AVPlayerItem* item = [AVPlayerItem playerItemWithAsset:asset];
    player = [AVPlayer playerWithPlayerItem:item];
    [item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:PlayerItemStatusObserverContext];
}

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
    if (context == PlayerItemStatusObserverContext)
    {
        AVPlayerStatus status = (AVPlayerStatus)[[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        if (status == AVPlayerStatusReadyToPlay)
        {
            [self applyFadeIn];
            [self performSelector:@selector(play:) withObject:nil afterDelay:1.0];
        }
    }
}

- (void)applyFadeIn
{
    assert(player.currentItem.tracks.firstObject);
    AVMutableAudioMixInputParameters* fadeIn = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:player.currentItem.tracks.firstObject];
    [fadeIn setVolume:0 atTime:kCMTimeZero];
    [fadeIn setVolume:1 atTime:CMTimeMake(2, 1)];
    NSMutableArray* paramsArray = [NSMutableArray new];
    [paramsArray addObject:fadeIn];
    AVMutableAudioMix* audioMix = [AVMutableAudioMix audioMix];
    audioMix.inputParameters = paramsArray;
    player.currentItem.audioMix = audioMix;
}

- (void)play:(id)unused
{
    [player play];
}

点击!这有什么问题?

编辑

我目前使用的一个明显的解决方法是:当播放器报告它准备好时,我在音量=0 的情况下进行短暂的 100 毫秒播放,然后恢复 currentTime 和音量,然后我才向主应用程序报告播放器准备好。这样就没有点击。有趣的是,任何小于 100 毫秒的时间仍然会发出咔嗒声。

这似乎是 AVFoundation 在第一次播放后缓存的问题。它既不是轨道,因为它们在我设置参数淡入时可用,也不是搜索状态。

4

0 回答 0