AVPlayer - Fast Backward / Forward Stream

10,279

Solution 1

Use AVPlayer method seekToTime

AVPlayer *player=..;
 [player seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];

here is a reference

Hope it helps

Solution 2

In Swift,

fileprivate let seekDuration: Float64 = 5


@IBAction func doForwardJump(_ sender: Any) {
    guard let duration  = player.currentItem?.duration else{
        return
    }
    let playerCurrentTime = CMTimeGetSeconds(player.currentTime())
    let newTime = playerCurrentTime + seekDuration

    if newTime < CMTimeGetSeconds(duration) {

        let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
        player.seek(to: time2)
    }
}
@IBAction func doBackwardJump(_ sender: Any) {

    let playerCurrentTime = CMTimeGetSeconds(player.currentTime())
    var newTime = playerCurrentTime - seekDuration

    if newTime < 0 {
        newTime = 0
    }
    let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
    player.seek(to: time2)

}

In Objective-C,

#define seekDuration (float)5

- (IBAction)backwardButtonAction:(UIButton *)sender {
    float playerCurrentTime = [self getCurrentTime];
    float newTime = playerCurrentTime - seekDuration;

    if (newTime < 0) {
        newTime = 0;
    }
    CMTime time = CMTimeMake(newTime*1000, 1000);
    [self.player seekToTime:time completionHandler:^(BOOL finished) {
        dispatch_async(dispatch_get_main_queue(), ^{
            playerSliderisScrubbing = NO;
        });
    }];
}
- (IBAction)forwardButtonAction:(UIButton *)sender {
    float duration = [self getPlayerDuration];
    float playerCurrentTime = [self getCurrentTime];
    float newTime = playerCurrentTime + seekDuration;

    if (newTime < duration) {
        CMTime time = CMTimeMake(newTime*1000, 1000);
        [self.player seekToTime:time completionHandler:^(BOOL finished) {
            dispatch_async(dispatch_get_main_queue(), ^{
                playerSliderisScrubbing = NO;
            });
        }];

    }
}
- (float)getCurrentTime {
    float seconds = 0;
    if (_player) {
        seconds = CMTimeGetSeconds([_player currentTime]);
    }
    return seconds;
}
- (float)getPlayerDuration {
    float seconds = 0;
    if (_player) {
        seconds = CMTimeGetSeconds([[_player currentItem] duration]);
    }
    return seconds;
}

Solution 3

Swift 4, 4.2 & 5

var player : AVPlayer!

@IBAction func fastForwardBtn(_ sender: UIButton) {
        let moveForword : Float64 = 5

        if player == nil { return }
        if let duration  = player!.currentItem?.duration {
        let playerCurrentTime = CMTimeGetSeconds(player!.currentTime())
        let newTime = playerCurrentTime + moveForword
        if newTime < CMTimeGetSeconds(duration)
        {
            let selectedTime: CMTime = CMTimeMake(value: Int64(newTime * 1000 as Float64), timescale: 1000)
            player!.seek(to: selectedTime)
        }
        player?.pause()
        player?.play()
        }

    }

@IBAction func rewindBtn(_ sender: UIButton) {
            let moveBackword: Float64 = 5
            if player == nil
            {
                return
            }
            let playerCurrenTime = CMTimeGetSeconds(player!.currentTime())
            var newTime = playerCurrenTime - moveBackword
            if newTime < 0
            {
                newTime = 0
            }
            player?.pause()
            let selectedTime: CMTime = CMTimeMake(value: Int64(newTime * 1000 as Float64), timescale: 1000)
            player?.seek(to: selectedTime)
            player?.play()
        }

Solution 4

You can use avPlayer.rate to fast backward/forward

Rates: 1.0 normal 0.0 pause

But first, you should check if avPlayerItem can do one of your action

For more info: https://developer.apple.com/LIBRARY/ios/documentation/AVFoundation/Reference/AVPlayer_Class/index.html#//apple_ref/occ/instp/AVPlayer/rate

Share:
10,279
Lorenz Wöhr
Author by

Lorenz Wöhr

Updated on July 28, 2022

Comments

  • Lorenz Wöhr
    Lorenz Wöhr over 1 year

    This is my code in the viewDidLoad :

    AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://groove.wavestreamer.com:7321/listen.pls?sid=1"]];
    
    [playerItem addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionNew context:nil];
    
    music = [[AVPlayer playerWithPlayerItem:playerItem] retain];
    [music play];
    

    My question:
    How can I create a button, that fast-forwards / fast-backwards the stream 5 seconds, when it´s pressed?

    Thank you for your answers... :)

    EDIT: How can I add to my current time...

    CMTime currentTime = music.currentTime;
    

    ...the 5 seconds?

  • Lorenz Wöhr
    Lorenz Wöhr about 11 years
    Forwarding is working perfectly, but I can´t rewind with this method. Do you know why?
  • Daniel
    Daniel about 11 years
    What happens when you try to rewind?
  • Daniel
    Daniel about 11 years
    You are probsbly giving the wrong time, from what you display in your comment, you are giving it a int/float? it should be a CMTime struct
  • valbu17
    valbu17 about 9 years
    @Daniel how do you catch/detect the fast forward action?
  • Daniel
    Daniel about 9 years
    @NorthBlast you need to make your own control, a scrub bar of some sort, when its slide up/back you act accordingly
  • valbu17
    valbu17 about 9 years
    @Daniel thanks man, I just was trying not to go through the painful way lol.. But, I guess I will have to.. lol..
  • Daniel
    Daniel about 9 years
    @NorthBlast with a UISlider it should be real easy... it has a value of 0 to 1, seek time = FullMovieTime * Value which will give you the time you need to seek to
  • May Phyu
    May Phyu about 7 years
    Hello Could you please help me how can I do trick play speed in avplayer bro?
  • May Phyu
    May Phyu about 7 years
    @Daniel, Could you please help me how can I do trick play speed in avplayer bro? Do you know how to implement it?