【发布时间】:2020-10-07 15:46:17
【问题描述】:
我有一个 Xamarin iOS 应用程序,我想从支持 HTTP 范围请求的 API 端点流式传输视频。我已经在 SO 上查看了许多类似的问题,但无论我尝试什么,我似乎都无法让 AVPlayer 在完全下载视频文件之前开始播放视频文件。 我试过了:
- KVO 在
playbackLikelyToKeepUp、playbackBufferEmpty和playbackBufferEmpty上播放视频,一旦它是ReadyToPlay - 在 AVPlayer 上设置
AutomaticallyWaitsToMinimizeStalling= false - 在 AVPlayerItem 上设置
CanUseNetworkResourcesForLiveStreamingWhilePaused= true 和PreferredForwardBufferDuration= 1 - 在 AVPlayer 上调用
PlayImmediatelyAtRate(1)
但是在视频开始播放之前文件仍然被完全下载,这会导致用户延迟。
是否可以让 AVPlayer 在完成下载之前开始播放视频文件,类似于 HTML 视频标签的做法?
这是我当前的代码:
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();
}
}
【问题讨论】:
-
您好,您的媒体流服务器使用什么类型的传输协议?如果
AVPlayer不能直接处理流数据,可以集成第三方播放器播放。比如VLC播放器。这里是关于 RTMP 的原生讨论:stackoverflow.com/questions/35312591/… -
感谢@JuniorJiang-MSFT 我正在尝试使用范围请求标头和 http 216 部分响应从 Web api 端点流式传输 mp4 文件。例如,这与 html 视频标签完美配合,但看起来 AVPlayer 不支持。我目前正在研究其他方法。
-
好吧,web api是否是
https地址? -
生产端点是 https。将 AVPlayer 直接指向我们在 Azure Blob 存储 (https) 中的资产的流式处理 url 不起作用。
-
这很奇怪。 Azure Web 服务器中 mp4 文件的大小是否很大?一般来说,iOS在玩之前需要一些时间准备。时间长短取决于文件的大小。