6

I am trying to pan and seek forwards and backwards in my AVPlayer. It is kind of working but the basic math of determining where the pan is translated to the length of the asset is wrong. Can any one offer assistance?

- (void) handlePanGesture:(UIPanGestureRecognizer*)pan{

    CGPoint translate = [pan translationInView:self.view];
    CGFloat xCoord = translate.x;
    double diff = (xCoord);
    //NSLog(@"%F",diff);

    CMTime duration = self.avPlayer.currentItem.asset.duration;
    float seconds = CMTimeGetSeconds(duration);
    NSLog(@"duration: %.2f", seconds);

    CGFloat gh = 0;

    if (diff>=0) {
        //If the difference is positive
        NSLog(@"%f",diff);
        gh = diff;
    } else {
        //If the difference is negative
        NSLog(@"%f",diff*-1);
        gh = diff*-1;
    }

    float minValue = 0;
    float maxValue = 1024;
    float value = gh;

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

    [_avPlayer seekToTime:CMTimeMakeWithSeconds(time, 10) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
    //[_avPlayer seekToTime:CMTimeMakeWithSeconds(seconds*(Float64)diff , 1024) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];

}
malaki1974
  • 1,605
  • 3
  • 16
  • 32
  • What do you see happening when you pan? You say the translation between the pan and the length of the asset is wrong but what exactly are you seeing happening? Pictures or a short video clip would also be helpful. – Austen Chongpison Sep 30 '14 at 15:15
  • Can you provide more details ? what's your expected results ? what's the result you get ? why it's wrong ? – Tran Quan Oct 07 '14 at 08:04
  • @malaki1974 I'm having the same issue as you were here and posted a question on SO: http://stackoverflow.com/questions/40363371/pan-gesture-with-avplayer. Could you please post the code here or in my question with the solution to this? That would be extremely helpful! Thank you for your time. – JEL Nov 02 '16 at 14:33

2 Answers2

3

You are not normalizing the touch location and the corresponding time values. Is there a 1:1 relationship between the two? That's not possible.

Take the minimum and maximum touch location values of the pan gesture and the minimum and maximum values of the asset's duration (obviously, from zero to the length of the video), and then apply the following formula to translate the touch location to the seek time:

// Map
#define map(x, in_min, in_max, out_min, out_max) ((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)

Here's the code I wrote that uses that formula:

- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)sender {
        if (sender.state == UIGestureRecognizerStateChanged){
            CGPoint location = [sender locationInView:self];
            float nlx = ((location.x / ((CGRectGetMidX(self.frame) / (self.frame.size.width / 2.0)))) / (self.frame.size.width / 2.0)) - 1.0;
            //float nly = ((location.y / ((CGRectGetMidY(self.view.frame) / (self.view.frame.size.width / 2.0)))) / (self.view.frame.size.width / 2.0)) - 1.0;
            nlx = nlx * 2.0;
            [self.delegate setRate:nlx];
        }
}

I culled the label that displays the rate, and the Play icon that appears while you're scrubbing, and which changes sizes depending on how fast or slow you are panning the video. Although you didn't ask for that, if you want it, just ask.

Oh, the "times-two" factor is intended to add an acceleration curve to the pan gesture value sent to the delegate's setRate method. You can use any formula for that, even an actual curve, like pow(nlx, 2.0) or whatever...

James Bush
  • 1,485
  • 14
  • 19
  • I got this algorithm working well when panning forward, however when letting go and panning backwards the video "skips" towards the beginning. Is this formula meant to work backwards also? FYI minimum touch values can be negative – Walter Martin Vargas-Pena Aug 24 '16 at 19:54
  • 1
    The formula is just a standard normalization formula; it's math, and therefore perfect. If you're having issues with AVPlayer, that's an entirely different question. You can try two things, one of which is to cancel any pending seek operations before submitting a new one. The skipping is caused by interrupting one seek operation in lieu of another. One of two solutions, which I have used, is at https://developer.apple.com/library/ios/qa/qa1820/_index.html Another is to ensure that the finished property equals YES in the completion block of the prior seek before submitting a subsequent seek. – James Bush Aug 24 '16 at 20:37
  • Agree with you completely. The issue that I am experiencing is due to the fact that I am not accounting for the video's current time which of course can cause skipping issues. I am struggling to figure out how to have the function account for the current time of the video – Walter Martin Vargas-Pena Sep 06 '16 at 16:09
  • @WalterMartinVargas-Pena Just use the code supplied by the link I provided; you're attempting nothing different from that. 'x' will always be the current time. – James Bush Sep 06 '16 at 16:13
  • To note: Im using 0 for minDuration, is that the correct input in my situation? – Walter Martin Vargas-Pena Sep 06 '16 at 16:17
  • http://stackoverflow.com/questions/39353645/accounting-for-current-time-when-panning-to-scrub-video More detail :) – Walter Martin Vargas-Pena Sep 07 '16 at 11:02
  • @WalterMartinVargas-Pena No. kCMTimeZero. – James Bush Sep 07 '16 at 11:34
  • thank you for your guidance, still giving me the same issue though. Im not communicating my setup properly. Ive written more detail here http://stackoverflow.com/questions/39353645/accounting-for-current-time-when-panning-to-scrub-video. (Shameless i know :) ) – Walter Martin Vargas-Pena Sep 07 '16 at 15:32
  • 1
    @WalterMartinVargas-Pena I updated my answer to this question, and the question you linked to. That code should get you started, no? If not, send me your project. I'll add it for you... – James Bush Sep 09 '16 at 08:25
  • By the way, what is a minimum duration? Do you mean start time? – James Bush Sep 20 '16 at 12:02
  • @JamesBush This is a great answer but I'm having some troubles on my own. Could you please check out my question here: http://stackoverflow.com/questions/40363371/pan-gesture-with-avplayer – JEL Nov 01 '16 at 15:58
0

If you want to make it more precise and useful you should implement different "levels of sensitivity".

Apple does that with their slider: if you drag away from the slider and then to the sides, that pace at which the video moves changes. The farther your are from the slider the more precise it gets/the less you can reach.

Rivera
  • 10,792
  • 3
  • 58
  • 102
  • Actually did this with one of my apps to my: if anyone is interested in the code, I can dig it up and send it to you. Just let me know. It also would be a perfect, working example of what the questioner is looking for, in that it employs the normalization equation I mentioned to scale the playback rates of -2 to +2 against the width of the screen, 0 to ??? (depends on the orientation and size of a given iPhone). – James Bush Sep 07 '16 at 08:03
  • @JamesBush I'd be keen to look at your code for the slider sensitivity. I want to eventually add the functionality to my avplayer. Can email me at ashramsey@gmail.com. Thanks. – user1012802 Sep 24 '16 at 11:13
  • @user1012802 Just sent it. The Xcode project is Xcode 3.2-compatible; but, you may be required to open it (or compile it) with Xcode 8.1 beta; you must, of course, run it from an actual device—not a simulator. If your device does not support OpenGL 3.0, let me know; I have one version of this app for every possible "player" configuration: AVAssetReader/AVSampleBufferDisplayLayer, AVPlayer/AVPlayerLayer, and an OpenGL 2.0 (and, that, using both kinds of layers). That's a total of six versions to workaround device issues. Aside from those two considerations, the rest should be straightforward. – James Bush Sep 24 '16 at 15:55
  • @user1012802 One other thing: Install Mac OS X Sierra 10.12.1 Beta before installing Xcode 8.1 beta. – James Bush Sep 24 '16 at 15:57
  • @user1012802 There are no visible player controls; they are supposed to be intuitive enough to obviate the need. To use the playback rate slider, simply slide your fingertip from left to right and vice versa. The further from the center, the faster the forward/rewind rate. Slide your finger towards the center to slow the rate. The play icon that appears while adjusting the rate will increase or decrease in size to reflect the rate. Also: To stop or play, tap. When stopped, tap the right or left edge of the screen to advance one step in either direction (i.e., slim frame-by-frame). – James Bush Sep 24 '16 at 16:06
  • @user1012802 If you don't receive it in e-mail, download it from https://www.dropbox.com/s/bufwe3vx5qly7tg/GLSkimmer%20%28Page%20Control%20Version%29.zip?dl=0 – James Bush Sep 27 '16 at 04:32
  • @user1012802 you can also download it from [OneDrive](https://1drv.ms/u/s!AlPpuHOjzLCDjCyfqYUFe8Yr-8ur) – James Bush Sep 27 '16 at 04:41