0

I want to implement Scrubber (UISlider) in AVPlayer. I have tried but I did not success completely (sometimes slider bar show incorrect value or sometimes progress timing bar). Any suggestion will be great.

-(void)playButtonClicked
{

    // checks internet connnection : working or not

    if([InternetUtility testInternetConnection])

    {

        if (audioButton.selected)
        {
            audioButton.selected = NO;
            printf("\n\ndo audioButton.selected = NO; \n\n");

        }

        else
        {
            printf("\n\ndo audioButton.selected = YES; \n\n");
            audioButton.selected = YES;
        }

        if (!isAlredayPlaying) {
        printf("\n\nStarted song from 0\n");
        isAlredayPlaying=YES;




        NSURL *url = [NSURL URLWithString:AUDIO_FILE_URL];


        playerItem = [AVPlayerItem playerItemWithURL:url];



        player = [AVPlayer playerWithPlayerItem:playerItem];
        player.volume=5.0;
        [self.audioSliderBar setMinimumValue:0.0];
        nsTimer=[NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES];
        [player play];


    }

    else
    {
        if (isCurrentlyPlaying)

        {
            [nsTimer invalidate];
            isCurrentlyPlaying=NO;
            [player pause];


        }
        else
        {
            nsTimer=[NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES];
            isCurrentlyPlaying=YES;
            [player play];

        }

     }
}      // internet connection check funtion, ended


    else {
        [ViewUtilities showAlert:INTERNET_CONNETION_TITLE :INTERNET_CONNECTION_MESSAGE];

    }
}

    - (void)updateTime:(NSTimer *)timer {


    currentTime = CMTimeGetSeconds(playerItem.currentTime);

    duration = CMTimeGetSeconds(playerItem.duration);


    if (currentTime==duration) {
        [self itemDidFinishPlaying];

    }

    [ self.audioSliderBar setValue:(currentTime/duration)];

    float minutes = floor(currentTime/60);
    seconds =currentTime - (minutes * 60);

    float duration_minutes = floor(duration/60);
    duration_seconds =
    duration - (duration_minutes * 60);



    NSString *timeInfoString = [[NSString alloc]
                                initWithFormat:@"%0.0f:%0.0f",
                                minutes, seconds ];//],
    //duration_minutes, duration_seconds];

    if  (!(player.currentItem && player.rate != 0 )&& isCurrentlyPlaying)
    {
        if (audioPlayerWillStop) {

            isAlredayPlaying=NO;
            [nsTimer invalidate];

        }

        else {

            [player play];
            printf("\n\n\n Force to play song...");

        }


    }
    self.audioCurrentTimeLabel.text = timeInfoString;

}

- (IBAction)audioPlayerValueChanged:(UISlider *)aSlider {

 CMTime newSeekTime = CMTimeMakeWithSeconds(aSlider.value*seconds,1) ;
[player seekToTime:newSeekTime];

// This code not working fine completely (slider value goes back up continuously) Please help

}
Ravi
  • 800
  • 2
  • 12
  • 28
  • Take a look at this question http://stackoverflow.com/questions/6329706/avplayer-video-seektotime – Vig Aug 20 '15 at 13:55
  • Thank @ Vig , I have already, did implement above link you have provided, but not working fine, Let me check it again. I will share result. – Ravi Aug 21 '15 at 01:00
  • @ Vig, I did implement from above link, not working fine. Please let me another one idea ?? – Ravi Aug 21 '15 at 01:18
  • Hi all, may anybody help me please , above link not working for me. Thanks in advance... – Ravi Aug 21 '15 at 05:06
  • please help, I have to do it ASAP. Thank you. – Ravi Aug 21 '15 at 06:25
  • Please update what's not working, what you have tried so far. The chances of getting help by not posting the actual problem and code snippets are very minimum. – Vig Aug 21 '15 at 19:25

4 Answers4

1

You can use my implemented methods. This code is working fine.

        #define NSEC_PER_SEC 1000000000ull
        -(void)funSeekPlayer
        {
               CMTime playerDuration = [self playerItemDuration];
               if (CMTIME_IS_INVALID(playerDuration)) {
                 return;
               }

               float minValue = [aSlider minimumValue];
               float maxValue = [aSlider maximumValue];
               float value = [aSlider value];

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

               [player seekToTime:CMTimeMakeWithSeconds(CMTimeMakeWithSeconds(time, NSEC_PER_SEC), NSEC_PER_SEC) completionHandler:^(BOOL finished) {
                   dispatch_async(dispatch_get_main_queue(), ^{
                    // Do Your next task
                   });
               }];

         }

         - (CMTime)playerItemDuration
         {
            AVPlayerItem *playerItem = [player currentItem];
            if (playerItem.status == AVPlayerItemStatusReadyToPlay)
            {
                return([playerItem duration]);
            }

            return(kCMTimeInvalid);
         }

 

SDS
  • 211
  • 1
  • 7
0

You must know the exact length (in seconds) of your music/video. Then you can use a UISlider to calculate the time in seconds when you want to start playing your music/video. And finally used .seekToTime(CMTimeMake(valueInSecond, 1)) on you AVPlayer object.

  • thanks @ Dolwen , it is not working for me. Please help. – Ravi Aug 22 '15 at 04:32
  • thanks @ Dolwen and Vig , it is not working for me. Please help. '(IBAction)audioPlayerValueChanged:(UISlider *)aSlider { CMTime newSeekTime = CMTimeMakeWithSeconds(aSlider.value*seconds,1) ; [player seekToTime:newSeekTime]; // This code not working fine completely (slider value goes back and forward continuously, and sometimes song starts from wrong time position ) }' – Ravi Aug 22 '15 at 04:39
  • You can switch to an `AVAudioPlayer` instead and use the same logic to change position with `currentTime`. `(IBAction)audioPlayerValueChanged:(UISlider )aSlider { [audioPlayer setCurrentTime:aSlider.value]; }` hop this help :) – Jérôme Demyttenaere Aug 24 '15 at 08:09
  • @ Dowen , I have solved out this issue. but now facing a little issue . My song length is 2.46 (min). UISlider reaches a end but song is still playing . (sons is not complete yet). Even I did hard code set maximum value of sliderbar = 2.46 , but not working . On the other hand if i set value of sliderbar = 3.5 (or aruond 4) , then it works fine. Any one has idea why it is happening .Thanks in advance!!!!! – – Ravi Aug 24 '15 at 10:29
0

If you are using a HLS (m3u8) video on demand stream and want to seek forward, you need to wait for all downloaded time ranges. That means if you want to seek 60 seconds forward, all time ranges for this 60 seconds should be loaded by AVPlayer. You can check this like this:

- (double) loadedTimeRangesDuration
{
    double result = 0;
    NSArray* ranges = self.player.currentItem.loadedTimeRanges;
    if (ranges != nil && ranges.count > 0)
    {
        CMTimeRange range = [[ranges objectAtIndex:0] CMTimeRangeValue];
        double duration = CMTimeGetSeconds(range.duration);
        result = duration;
    }

    return result;
}
0

For moving video 10 sec ahead I have user this code and it worked for me

float tempTime = CMTimeGetSeconds(player.currentItem.duration) + 10;

CMTime targetTime = CMTimeMakeWithSeconds(tempTime, NSEC_PER_SEC);

[player seekToTime:targetTime];