AVPlayer 使用平移手势快进/后退

Posted

技术标签:

【中文标题】AVPlayer 使用平移手势快进/后退【英文标题】:AVPlayer fast forward/backward skipping with pan gesture 【发布时间】:2017-01-25 14:05:19 【问题描述】:

在过去的两天里,我一直在用一个恼人的小故障敲我的头,希望有人能解释一下。

基本设置:我有一个带有播放器的 AVPlayerLayer,视图中有一个平移手势识别器,我希望用户能够来回滑动手指,视频会相应地搜索。

关键:我希望用户抬起手指并再次将其放在屏幕上的任何位置,以便快进或快退以完全相同相同的方式恢复从它停止的地方开始,然后从那里继续前进。

我见过这两个问题: Pan Gesture with AVPlayer 和 Pan to seek 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;

任何帮助将不胜感激!

【问题讨论】:

如果您在 3.00 秒开始平移并说平移 2 px 然后抬起,它应该再次以 5.00 或 3.00 播放? @SeanLintern88应该又能玩3.0了,抱歉清理了 好吧,澄清一下,你会在 3.0,正在平移和前后擦洗,然后在 .end 恢复到 3.0?但是在擦洗视频期间,视频会根据平移顺利来回吗?如果是这样,这个问题到底是什么? 【参考方案1】:

UIGestureRecognizerStateBegan 上从AVPlayer 保存CMTime,然后进行增量更改平移,然后在UIGestureRecognizerStateEnded 上只寻找原始保存的时间?

只是为了更流畅地寻找注意不要暂停视频,将速率设置为 0。

【讨论】:

您确实是正确的,我在阅读您的评论后注意到了问题,如果您查看我的示例代码,我将初始查找时间设置在 UIGestureRecognizerStateChanged 而不是 UIGestureRecognizerStateBegan 下,因此我看到了用户开始滑动时的初始混蛋。 也使用速率来暂停而不是暂停,这使得搜索更加流畅。 回复。暂停/速率差异,仅提一下截至今天official docs 说它们完全相同:调用此方法与将速率设置为 0.0 相同。

以上是关于AVPlayer 使用平移手势快进/后退的主要内容,如果未能解决你的问题,请参考以下文章

同时播放两个 AVPlayer 音频文件时出现音频故障

UIView 中的 AVPlayer 视图缺少控件

如何为 UINavigationController 启用全屏平移

如何在 swift 3 中将滑动手势添加到 AVPlayer

vue-video-player怎么禁止快进 可以后退?

在 UIWebView 中向后/向前滑动手势?