0

AVPlayerItem has this property forwardPlaybackEndTime

The value indicated the time at which playback should end when the playback rate is positive (see AVPlayer’s rate property).

The default value is kCMTimeInvalid, which indicates that no end time for forward playback is specified. In this case, the effective end time for forward playback is the item’s duration.

But I don't know why it does not work. I tried to set it in AVPlayerItemStatusReadyToPlay, duration available callback, ... but it does not have any effect, it just plays to the end

I think that forwardPlaybackEndTime is used to restrict the playhead, right? In my app, I want to play from the beginning to the half of the movie only

My code looks like this

- (void)playURL:(NSURL *)URL
{
    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:URL];

    if (self.avPlayer) {
        if (self.avPlayer.currentItem && self.avPlayer.currentItem != playerItem) {
            [self.avPlayer replaceCurrentItemWithPlayerItem:playerItem];
        }
    } else {
        [self setupAVPlayerWithPlayerItem:playerItem];
    }

    playerItem.forwardPlaybackEndTime = CMTimeMake(5, 1);

    // Play
    [self.avPlayer play];
}

How to make forwardPlaybackEndTime work?

onmyway133
  • 45,645
  • 31
  • 257
  • 263

4 Answers4

0

Try this

   AVPlayerItem.forwardPlaybackEndTime = CMTimeMake(5, 1);
   Here 5 is the time till the AVPlayerItem will play.
falcon143
  • 702
  • 4
  • 19
  • I already set that, but the player still plays to the end of the movie. I aslo `CMTimeShow(avplayerItem.forwardPlaybackEndTime)` and see that my configure was right – onmyway133 Sep 08 '14 at 07:03
  • check this `AVCaptureConnection *conn = [output connectionWithMediaType:AVMediaTypeVideo]; CMTimeShow(conn.videoMinFrameDuration); CMTimeShow(conn.videoMaxFrameDuration); if (conn.supportsVideoMinFrameDuration) conn.videoMinFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND); if (conn.supportsVideoMaxFrameDuration) conn.videoMaxFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND); CMTimeShow(conn.videoMinFrameDuration); CMTimeShow(conn.videoMaxFrameDuration);` – falcon143 Sep 08 '14 at 07:19
  • u have to set maximum and minimum duration – falcon143 Sep 08 '14 at 07:22
  • AVPlayerItem does not have maximum/minimum properties ?! – onmyway133 Sep 08 '14 at 07:34
  • it is live streaming video or video play from local – falcon143 Sep 08 '14 at 08:11
  • it is live streaming/progressive download – onmyway133 Sep 08 '14 at 08:23
  • try this `Float64 dur = CMTimeGetSeconds([avPlayer currentTime])-2.0; CMTime newTime = CMTimeMakeWithSeconds(dur, avPlayer.currentTime.timescale); [avPlayer seekToTime:newTime];` – falcon143 Sep 08 '14 at 08:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/60871/discussion-between-onmyway133-and-ramesh-kumar). – onmyway133 Sep 09 '14 at 08:18
0

Set the following on your AVPlayer

AVPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;

Then set your notification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidPlayToEndTime:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];

with the method obviously

- (void) playerItemDidPlayToEndTime:(NSNotification*)notification
{
// do something here
}

then set your forwardPlaybackEndTime

AVPlayer.currentItem.forwardPlaybackEndTime = CMTimeAdd(AVPlayer.currentItem.currentTime, CMTimeMake(5.0, 1));

and start your avplayer playing

AVPlayer.rate = 1.0;

the notification will be triggered and your track will continue playing. In your handler you can stop it and do a seekToTime or whatever.

Alternatively you can just set a boundary observer

NSArray *array = [NSArray arrayWithObject:[NSValue valueWithCMTime:CMTimeMakeWithSeconds(5.0, 1)]];


    __weak OTHD_AVPlayer* weakself = self;
    self.observer_End = [self addBoundaryTimeObserverForTimes:array queue:NULL usingBlock:^{ if( weakself.rate >= 0.0 )     [weakself endBoundaryHit]; }];
amergin
  • 3,106
  • 32
  • 44
  • why ``actionAtItemEnd``, ``AVPlayerItemDidPlayToEndTimeNotification``? I think forwardPlaybackEndTime is used to restrict the playhead? Say I only want to play from the beginning to the half of the movie, how can I do that with ``forwardPlaybackEndTime`` – onmyway133 Sep 09 '14 at 08:14
  • actionAtItemEnd tells the AVPlayer what to do when it hits the end - you want it to do nothing. The AVPlayerItemDidPlayToEndTimeNotification is triggered when the AVPlayer hits your forwardPlaybackEndTime so you want to be watching for this. – amergin Sep 09 '14 at 12:15
  • This approach seems logical, but it just doesn't work for me. The video ends; the event triggers; and I'm able to set the new rate and forwardPlaybackEndTime, but the video always restarts at the beginning instead of continuing from where it stopped Is that the expected behavior? – Axeva Oct 06 '14 at 21:25
  • @Axeva - yes that's the expected behaviour. If you need it to play on from a point just having changed the rate I'd suggest my alternative of using a boundary observer. – amergin Oct 06 '14 at 21:51
  • I don't really care about changing the rate. That was just a tip I found somewhere else that didn't work. I really just want to play the video to a certain point, stop it until a user action happens, then resume. Boundary observers are a lot more messy than forwardPlaybackEndTime, and not as precise. Is that really the only option? – Axeva Oct 06 '14 at 22:01
  • @Axeva - in your playerItemDidPlayToEndTime: method you could call the AVPlayer seekToTime: method with your new start time and set your rate to 1.0 (or call play) in the completionHandler. – amergin Oct 06 '14 at 22:11
  • I think I may have found the answer. `seekToTime` isn't enough. You need `seekToTime:toleranceBefore:toleranceAfter`. See also [Resume AVPlayer after forwardPlaybackEndTime](http://stackoverflow.com/questions/26225334/resume-avplayer-after-forwardplaybackendtime) – Axeva Oct 06 '14 at 22:18
0

I have checked below code its running and streaming stops at specified time:

- (void)playURL
{

NSURL *url = [NSURL URLWithString:@"http://clips.vorwaerts-gmbh.de/VfE_html5.mp4"];

self.playerItem = [AVPlayerItem playerItemWithURL:url];

self.playerItem.forwardPlaybackEndTime = CMTimeMake(10, 1);

self.avPlayer = [AVPlayer playerWithPlayerItem:self.playerItem];

[videoView setPlayer:self.avPlayer];

// Play
[self.avPlayer play];
}

I hope this will help you.

Also please check these tutorials: AVFoundation Framework

Omer Waqas Khan
  • 2,423
  • 4
  • 33
  • 62
  • your video URL works, it seems forwardPlaybackEndTime only works for certain URLs/streams – onmyway133 Sep 10 '14 at 03:49
  • No, it should work with all streams, previously I had to stream video clips from S3, and those worked fine, even I had to stream multiple files without any gap in between them. – Omer Waqas Khan Sep 10 '14 at 06:49
0

I think that you have to update avPlayer's current playerItem.

So,

 playerItem.forwardPlaybackEndTime = CMTimeMake(5, 1);

it should be:

 self.avPlayer.currentItem.forwardPlaybackEndTime = CMTimeMake(5, 1);
Yu's Way
  • 142
  • 3
  • I think ""self.avPlayer.playerItem.forwardPlaybackEndTime = CMTimeMake(5, 1);"" creates a new playerItem and assigns the new playerItem to self.avplayer. But, ""playerItem.forwardPlaybackEndTime = CMTimeMake(5, 1);"" just creates a new playerItem. It doesn't assign the new playerItem to self.avPlayer. So self.avPlayer doesn't know the new playerItem, it will still play the old playerItem. I think that probably playerItem is called by value not by reference. – Yu's Way Feb 24 '15 at 14:23
  • Instead of "self.avPlayer.playerItem.forwardPlaybackEndTime = CMTimeMake(5, 1);", It should be "self.avPlayer.currentItem.forwardPlaybackEndTime = CMTimeMake(5, 1);". – Yu's Way Oct 03 '15 at 03:56