AVPlayer fast forward/backward 用平移手势跳过
AVPlayer fast forward/backward skipping with pan gesture
在过去的两天里,我一直在为一个烦人的故障而烦恼,希望有人能给出一些启示。
基本设置: 我有一个带有播放器的 AVPlayerLayer,视图中有一个平移手势识别器,我希望用户能够来回滑动手指,视频会相应地寻找。
要点: 我希望如果用户抬起手指并再次放置,在屏幕上的任何位置快进或快退以在 [=37= 恢复]完全 与它停止的同一帧并从那里继续前进。
我看到了这两个问题:
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;
}
任何帮助将不胜感激!
在 UIGestureRecognizerStateBegan
上从 AVPlayer
保存 CMTime
然后做你的增量变化平移,然后在 UIGestureRecognizerStateEnded
上找回原来保存的时间?
请注意,为了更流畅,请不要暂停视频,将速率设置为 0。
在过去的两天里,我一直在为一个烦人的故障而烦恼,希望有人能给出一些启示。
基本设置: 我有一个带有播放器的 AVPlayerLayer,视图中有一个平移手势识别器,我希望用户能够来回滑动手指,视频会相应地寻找。
要点: 我希望如果用户抬起手指并再次放置,在屏幕上的任何位置快进或快退以在 [=37= 恢复]完全 与它停止的同一帧并从那里继续前进。
我看到了这两个问题: 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;
}
任何帮助将不胜感激!
在 UIGestureRecognizerStateBegan
上从 AVPlayer
保存 CMTime
然后做你的增量变化平移,然后在 UIGestureRecognizerStateEnded
上找回原来保存的时间?
请注意,为了更流畅,请不要暂停视频,将速率设置为 0。