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.

Другие вопросы по тегам