Скруббер (UISlider) в AVPlayer?

Когда вы воспроизводите удаленное видео через AVPlayer и начинаете перемотку, скруббер не работает.

Я делаю игрока на основе этого примера Apple.

Как реализовать его плавно?

Ниже приведен код из моего проекта - https://github.com/nullproduction/Player

- (void)initScrubberTimer
{
    double interval = .1f;

    CMTime playerDuration = [self playerItemDuration];
    if (CMTIME_IS_INVALID(playerDuration))
    {
        return;
    }
    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration))
    {
        CGFloat width = CGRectGetWidth([scrubberSlider bounds]);
        interval = 0.5f * duration / width;
    }

    __weak id weakSelf = self;
    CMTime intervalSeconds = CMTimeMakeWithSeconds(interval, NSEC_PER_SEC);
    mTimeObserver = [self.player addPeriodicTimeObserverForInterval:intervalSeconds
                                                              queue:dispatch_get_main_queue()
                                                         usingBlock:^(CMTime time) {
                                                             [weakSelf syncScrubber];
                                                         }];

}


- (void)syncScrubber
{
    CMTime playerDuration = [self playerItemDuration];
    if (CMTIME_IS_INVALID(playerDuration))
    {
        scrubberSlider.minimumValue = 0.0;
        return;
    }

    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration))
    {
        float minValue = [scrubberSlider minimumValue];
        float maxValue = [scrubberSlider maximumValue];
        double time = CMTimeGetSeconds([self.player currentTime]);

        [scrubberSlider setValue:(maxValue - minValue) * time / duration + minValue];
    }
}

- (IBAction)beginScrubbing:(id)sender
{
    mRestoreAfterScrubbingRate = [self.player rate];
    [self.player setRate:0.f];

    [self removePlayerTimeObserver];
}


- (IBAction)scrub:(id)sender
{
    if ([sender isKindOfClass:[UISlider class]])
    {
        UISlider* slider = sender;

        CMTime playerDuration = [self playerItemDuration];
        if (CMTIME_IS_INVALID(playerDuration))
        {
            return;
        }

        double duration = CMTimeGetSeconds(playerDuration);
        if (isfinite(duration))
        {
            float minValue = [slider minimumValue];
            float maxValue = [slider maximumValue];
            float value = [slider value];

            double time = duration * (value - minValue) / (maxValue - minValue);

            [self.player seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC)];
        }
    }
}

- (IBAction)endScrubbing:(id)sender
{
    if (!mTimeObserver)
    {
        CMTime playerDuration = [self playerItemDuration];
        if (CMTIME_IS_INVALID(playerDuration))
        {
            return;
        }

        double duration = CMTimeGetSeconds(playerDuration);
        if (isfinite(duration))
        {
            CGFloat width = CGRectGetWidth([scrubberSlider bounds]);
            double tolerance = 0.5f * duration / width;

            __weak id weakSelf = self;
            CMTime intervalSeconds = CMTimeMakeWithSeconds(tolerance, NSEC_PER_SEC);
            mTimeObserver = [self.player addPeriodicTimeObserverForInterval:intervalSeconds
                                                                      queue:dispatch_get_main_queue()
                                                                 usingBlock: ^(CMTime time) {
                                                                     [weakSelf syncScrubber];
                                                                 }];
        }
    }

    if (mRestoreAfterScrubbingRate)
    {
        [self.player setRate:mRestoreAfterScrubbingRate];
        mRestoreAfterScrubbingRate = 0.f;
    }
}

Ответ 1

Я предполагаю, что проблема заключается в том, что ваш скруббер все еще обновляется с видео, пока вы используете поисковый барьер. Внедрите его так, чтобы вы приостанавливали проигрыватель во время очистки, и у вас больше не будет этой ошибки. Оформить заказ:

Функция обновления вашего плеера:

- (IBAction)seekbarAction:(UISlider *)sender {
    CMTime videoLength = playerItem1.duration;  //gets the video duration
    float videoLengthInSeconds = videoLength.value/videoLength.timescale; //transfers the CMTime duration into seconds

    [player1 seekToTime:CMTimeMakeWithSeconds(videoLengthInSeconds*sender.value, 1)];
}

И еще одно действие с помощью "Touch down" для приостановки видео:

- (IBAction)pauseSeek:(id)sender {
    [player1 pause];
}

И еще одно действие с помощью "Touch up" для возобновления видео при отпускании скруббера. Надеюсь, это поможет.