iOS - 如何在AVPlayer中实现seektotime(从URL播放歌曲)?

时间:2015-08-20 12:49:47

标签: ios objective-c avplayer

我想在AVPlayer中实现Scrubber(UISlider)。我已经尝试但是我没有完全成功(有时滑块显示不正确的值或有时进度计时栏)。任何建议都会很棒。

-(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];

// 此代码无法正常工作(滑块值不断恢复)请帮助

}

4 个答案:

答案 0 :(得分:0)

您必须知道音乐/视频的确切长度(以秒为单位)。 然后,您可以使用UISlider计算您想要开始播放音乐/视频的时间(以秒为单位)。 最后在.seekToTime(CMTimeMake(valueInSecond, 1))对象上使用了AVPlayer

答案 1 :(得分:0)

如果您正在使用HLS(m3u8)视频点播流并想要向前搜索,则需要等待所有下载的时间范围。这意味着如果你想要向前寻找60秒,这个60秒的所有时间范围都应由AVPlayer加载。您可以这样检查:

- (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;
}

答案 2 :(得分:0)

您可以使用我实施的方法。这段代码工作正常。

        #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);
         }

答案 3 :(得分:0)

对于提前10秒钟移动视频,我已经使用了此代码,并且对我有用

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

CMTime targetTime = CMTimeMakeWithSeconds(tempTime,NSEC_PER_SEC);

[player seekToTime:targetTime];