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 によってキャッシュされているものの問題のようです。フェードインパラメーターを設定したときに利用できるトラックでも、シークステータスでもありません。