テクニカル Q&A QA1820 AVPlayer seekToTime: でスムーズなビデオ スクラビングを実現するにはどうすればよいですか?
Q: 私のアプリでは、AVPlayer seekToTime: と組み合わせてスライダー コントロールを使用して、ユーザーがビデオ ファイルをスクラブできますが、ビデオ フレームの表示にかなりの遅延があります。よりスムーズなスクラブを実現するにはどうすればよいですか?
A: AVPlayer seekToTime: を立て続けに呼び出すことは避けてください。これにより、進行中のシークがキャンセルされ、多くのシークが行われ、ターゲット フレームがあまり表示されなくなります。代わりに、AVPlayer seekToTime: の完了ハンドラー バリアントを使用し、進行中のシークが完了するのを待ってから、別のシークを発行します。リスト 1 とリスト 2 に、この手法の例を示します (注: これらの例では、有効なプレイヤー オブジェクトが作成され、プレイヤーの現在のアイテム ステータスがキー値の監視によって維持されていることを前提としています。詳細については、AV Foundation プログラミング ガイドを参照してください)。
AVPlayer seekToTime: の完了ハンドラー バリアントを使用して、よりスムーズなスクラブ (Objective-C) を行います。
@import AVFoundation;
@interface MyClass ()
{
AVPlayer player;
BOOL isSeekInProgress;
CMTime chaseTime;
AVPlayerStatus playerCurrentItemStatus; // your player.currentItem.status
...
}
@implementation MyClass
...
- (void)stopPlayingAndSeekSmoothlyToTime:(CMTime)newChaseTime
{
[self->player pause];
if (CMTIME_COMPARE_INLINE(newChaseTime, !=, self->chaseTime))
{
self->chaseTime = newChaseTime;
if (!self->isSeekInProgress)
[self trySeekToChaseTime];
}
}
- (void)trySeekToChaseTime
{
if (playerCurrentItemStatus == AVPlayerItemStatusUnknown)
{
// wait until item becomes ready (KVO player.currentItem.status)
}
else if (playerCurrentItemStatus == AVPlayerItemStatusReadyToPlay)
{
[self actuallySeekToTime];
}
}
- (void)actuallySeekToTime
{
self->isSeekInProgress = YES;
CMTime seekTimeInProgress = self->chaseTime;
[self->player seekToTime:seekTimeInProgress toleranceBefore:kCMTimeZero
toleranceAfter:kCMTimeZero completionHandler:
^(BOOL isFinished)
{
if (CMTIME_COMPARE_INLINE(seekTimeInProgress, ==, self->chaseTime))
self->isSeekInProgress = NO;
else
[self trySeekToChaseTime];
}];
}
@end