How to play AVPlayerItems immediately
Swift 5
You just need to use the automaticallyWaitsToMinimizeStalling property.
player.automaticallyWaitsToMinimizeStalling = false
player.playImmediately(atRate: 1.0)
How to make AVPlayer appear instantly instead of after video ends?
The answer was we had an incorrectly composed video in the first place, as described here: AVAssetExportSession export fails non-deterministically with error: "Operation Stopped, NSLocalizedFailureReason=The video could not be composed.".
The other part of the question (audio playing long before images/video appears) was answered here: Long delay before seeing video when AVPlayer created in exportAsynchronouslyWithCompletionHandler
Hope these help someone avoid the suffering we endured! :)
Knowing when AVPlayer object is ready to play
You are playing a remote file. It may take some time for the AVPlayer
to buffer enough data and be ready to play the file (see AV Foundation Programming Guide)
But you don't seem to wait for the player to be ready before tapping the play button. What I would to is disable this button and enable it only when the player is ready.
Using KVO, it's possible to be notified for changes of the player status:
playButton.enabled = NO;
player = [AVPlayer playerWithURL:fileURL];
[player addObserver:self forKeyPath:@"status" options:0 context:nil];
This method will be called when the status changes:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
if (object == player && [keyPath isEqualToString:@"status"]) {
if (player.status == AVPlayerStatusReadyToPlay) {
playButton.enabled = YES;
} else if (player.status == AVPlayerStatusFailed) {
// something went wrong. player.error should contain some information
}
}
}
How to know when AVPlayerItem is playing
First you need to register your AVPlayerItem
as an observer:
[self.yourPlayerItem addObserver:self
forKeyPath:kStatus
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:AVPlayerStatus];
Then on your player Key Value Observer method you need to check for AVPlayerStatusReadyToPlay
status, like so:
- (void)observeValueForKeyPath:(NSString *)path
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (context == AVPlayerStatus) {
AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
switch (status) {
case AVPlayerStatusUnknown: {
}
break;
case AVPlayerStatusReadyToPlay: {
// audio will begin to play now.
}
break;
}
}
Replaying AVPlayerItem / AVPlayer without re-downloading
You can call the seekToTime method when your player received AVPlayerItemDidPlayToEndTimeNotification
func itemDidFinishPlaying() {
self.player.seek(to: CMTime.zero)
self.player.play()
}
Related Topics
Setting Arkit Orientation via Swift
How to Star a Repo with Github API
What Is the Slice Compare Logic in Swift
Having Trouble with Nstimer (Swift)
How to I Turn Off the Ambient Light in Scene Kit (With Swift)
Swiftui: Navigationlink Not Working If Not in a List
Spritekit Particle Emitter Multi Image
How to Check If Airpods Are Connected to Iphone
How to Make JSON Data Persistent for Offline Use (Swift 4)
Shared Cookies with Wkprocesspool for Wkwebview in Swift
How to Get a Double Value Up to 2 Decimal Places
Refreshing Auth Token with Moya
Is This Safe to Call Wait() of Dispatchsemaphore Several Times at One Time
Converting Audiobuffer to Cmsamplebuffer with Accurate Cmtime
Create a Swift Dictionary Subclass