AVPlayer быстрая перемотка вперед / назад с помощью панорамирования
Последние два дня я ломал голову над досадной ошибкой и надеялся, что кто-нибудь сможет пролить немного света.
Базовая настройка: у меня есть AVPlayerLayer с плеером, распознавателем жестов панорамирования в представлении, и я хочу, чтобы пользователь мог проводить пальцами взад и вперед, и видео будет искать соответственно.
Подвох: я хотел бы, чтобы пользователь поднял палец и снова поместил его в любом месте экрана, чтобы перемотка вперед или назад возобновилась в том же кадре, где он остановился, и продолжит движение оттуда.
Я видел эти два вопроса: Pan Gesture с AVPlayer и Pan для поиска AVPlayer
Я попробовал предложение Apple здесь: https://developer.apple.com/library/content/qa/qa1820/_index.html, но проблема в том, что всякий раз, когда я запускаю новый жест панорамирования, проигрыватель прыгает несколько кадры, а затем возобновляет.
Мой последний подход состоял в том, чтобы установить текущее время после завершения блока завершения поиска, а затем я пытаюсь добавить к нему новое время поиска.
Вот моя установка:
self.item = [AVPlayerItem playerItemWithURL:resource];
self.player = [AVPlayer playerWithPlayerItem:self.item];
self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
[self.view.layer addSublayer:self.playerLayer];
self.playerLayer.frame = self.view.bounds;
UIPanGestureRecognizer *recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
[self.view addGestureRecognizer:recognizer];
И моя обработка распознавания жестов:
- (void)swipe:(UIPanGestureRecognizer *)paramRecognizer
{
switch(paramRecognizer.state) {
// case UIGestureRecognizerStateBegan:
case UIGestureRecognizerStateChanged:
{
[self.player pause];
CGPoint translation = [paramRecognizer translationInView:self.view];
float horizontalTranslation = translation.x;
float durationInSeconds = CMTimeGetSeconds(self.player.currentItem.asset.duration);
//I'd like to be able to swipe across the whole view.
float translationLimit = self.view.bounds.size.width;
float minTranslation = 0;
float maxTranslation = translationLimit;
if (horizontalTranslation > maxTranslation) {
horizontalTranslation = maxTranslation;
}
if (horizontalTranslation < minTranslation) {
horizontalTranslation = minTranslation;
}
float timeToSeekTo = [self normalize:horizontalTranslation
andMinDelta:minTranslation
andMaxDelta:maxTranslation
andMinDuration:0
andMaxDuration:durationInSeconds];
if(CMTIME_IS_VALID(self.currentTime)){
float seconds = self.currentTime.value/self.currentTime.timescale;
[self.player seekToTime:CMTimeMakeWithSeconds(seconds+timeToSeekTo, self.player.currentTime.timescale)
toleranceBefore:kCMTimeZero
toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished)
{
if(finished)
self.currentTime = self.player.currentItem.currentTime;
}];
}
else
{
[self.player seekToTime:CMTimeMakeWithSeconds(timeToSeekTo,
self.player.currentTime.timescale) toleranceBefore:kCMTimeZero
toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
if(finished)
self.currentTime = self.player.currentItem.currentTime;
}];
}
}
break;
}
}
Метод нормализации таков:
- (float) normalize:(float)delta
andMinDelta:(float)minDelta
andMaxDelta:(float)maxDelta
andMinDuration:(float)minDuration
andMaxDuration:(float)maxDuration{
float result = ((delta - minDelta) * (maxDuration - minDuration) / (maxDelta - minDelta) + minDuration);
return result;
}
Любая помощь будет чрезвычайно ценится!
1 ответ
На UIGestureRecognizerStateBegan
спасти CMTime
через от AVPlayer
затем сделайте панорамирование изменений, затем на UIGestureRecognizerStateEnded
просто вернуться к первоначальному сэкономленному времени?
Просто заметка для более плавного поиска, не останавливайте видео, установите скорость на 0.