Reputation: 3492
I have a Xamarin iOS app that I want to stream videos from an API endpoint that supports HTTP range requests. I've reviewed many similar questions here on SO, but I cannot seem to get the AVPlayer to start playing the video file before it is downloaded fully no matter what I try. I've tried:
playbackLikelyToKeepUp
, playbackBufferEmpty
and playbackBufferEmpty
to play the video as soon as it is ReadyToPlay
AutomaticallyWaitsToMinimizeStalling
= false on the AVPlayerCanUseNetworkResourcesForLiveStreamingWhilePaused
= true, and PreferredForwardBufferDuration
= 1 on the AVPlayerItemPlayImmediatelyAtRate(1)
on the AVPlayerBut still the file is downloaded fully before the video starts to play, which causes a delay for the user.
Is it possible to get AVPlayer to start playing a video file before it has completed downloading it, similar to how the HTML video tag does it?
Here is my current code:
private void SetUpPlayer()
{
if (ViewModel.VideoStreamUrl == null)
{
return;
}
// See https://stackoverflow.com/questions/38865797/how-to-play-video-with-avplayerviewcontroller-avkit-in-xamarin-ios
_aVPlayerItem = new AVPlayerItem(ViewModel.VideoStreamUrl)
{
CanUseNetworkResourcesForLiveStreamingWhilePaused = true,
PreferredForwardBufferDuration = 1,
};
// See https://stackoverflow.com/questions/38867190/how-can-i-check-if-my-avplayer-is-buffering/38867386#38867386
_playbackLikelyToKeepUpObserver?.Dispose();
_playbackLikelyToKeepUpObserver = (NSObject)_aVPlayerItem.AddObserver("playbackLikelyToKeepUp",
NSKeyValueObservingOptions.New,
AVPlayerItem_BufferUpdated);
_playbackBufferEmptyObserver?.Dispose();
_playbackBufferEmptyObserver = (NSObject)_aVPlayerItem.AddObserver("playbackBufferEmpty",
NSKeyValueObservingOptions.New,
AVPlayerItem_BufferUpdated);
_playbackBufferFullObserver?.Dispose();
_playbackBufferFullObserver = (NSObject)_aVPlayerItem.AddObserver("playbackBufferFull",
NSKeyValueObservingOptions.New,
AVPlayerItem_BufferUpdated);
_aVPlayer = new AVPlayer(_aVPlayerItem)
{
AutomaticallyWaitsToMinimizeStalling = false,
};
var playerViewController = new AVPlayerViewController
{
Player = _aVPlayer,
};
AddChildViewController(playerViewController);
View.AddSubview(playerViewController.View);
playerViewController.View.Frame = View.Frame;
playerViewController.ShowsPlaybackControls = true;
_aVPlayer.PlayImmediatelyAtRate(1);
}
private void AVPlayerItem_BufferUpdated(NSObservedChange obj)
{
ReportVideoBuffering();
}
private void ReportVideoBuffering()
{
bool isBufferEmpty = _aVPlayerItem != null && _aVPlayerItem.PlaybackBufferEmpty;
Console.WriteLine($"Buffer empty? {isBufferEmpty}");
Console.WriteLine($"Player status? {_aVPlayer.Status}");
if (_aVPlayer.Status == AVPlayerStatus.ReadyToPlay)
{
Console.WriteLine($"Playing video.");
_aVPlayer.Play();
}
}
Upvotes: 2
Views: 696
Reputation: 3492
The simple answer to the question is no, the AVPlayer doesn't support streaming using http range requests and partial content (206) responses. In our case, we have decided to use Azure Media Services to provide a streaming endpoint which we can then use in the iPad app as well as on the web.
Upvotes: 1