AVPlayer中的Scrubber(UISlider)是什么?

10

当您使用AVPlayer播放远程视频并开始倒带时,滑块不稳定。

我正在基于这个苹果示例进行开发。

如何使其实现平滑操作?

以下是来自我的项目的代码 - 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个回答

8

我猜问题在于,当你使用进度条时,你的Scrubber仍在从视频中更新。用一种方法来实现,在Scrubbing期间暂停播放器,你就不会再遇到这个错误了。请查看我的解决方案:

更新播放器的函数:

- (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”操作的SeekBar动作,以便暂停视频:

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

还有一种滑动条操作是“Touch up”,当您释放滑块时,可以恢复视频播放。希望这对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接