[英]AVPlayer HLS live stream IOS
我正在嘗試使用HLS直播但我收到錯誤:
錯誤:可選(“操作無法完成”),錯誤:可選(錯誤域= AVFoundationErrorDomain代碼= -11800“媒體格式 - 樣本描述無效(例如無效大小)”UserInfo = {NSUnderlyingError = 0x60000005b510 {錯誤域= NSOSStatusErrorDomain代碼= -12714“(null)”},NSLocalizedFailureReason =發生未知錯誤(-12714),NSDebugDescription =媒體格式 - 樣本描述無效(例如無效大小),NSLocalizedDescription =操作無法完成})2018- 04-25 12:14:51.608117 + 0200 morethen2 [11681:374192]任務。<3>完成錯誤 - 代碼:-999
我不能分享鏈接到流,它的私人。
這是代碼:
class ViewController: UIViewController {
var player = AVPlayer()
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https:can-t-share-it/LIVE-008900021A-LIP-0-channelNo2_360p/manifest.m3u8")!
let asset = AVURLAsset(url: url)
let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(url: url)
let layer = AVPlayerLayer(player: player)
layer.frame = view.layer.frame
view.layer.addSublayer(layer)
self.player.addObserver(self, forKeyPath: #keyPath(AVPlayer.status), options: [.new, .initial], context: nil)
self.player.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem.status), options:[.new, .initial], context: nil)
// Watch notifications
let center = NotificationCenter.default
center.addObserver(self, selector:"newErrorLogEntry:", name: .AVPlayerItemNewErrorLogEntry, object: player.currentItem)
center.addObserver(self, selector:"failedToPlayToEndTime:", name: .AVPlayerItemFailedToPlayToEndTime, object: player.currentItem)
player.play()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func dismiss(_ sender: Any) {
UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: true, completion: nil)
}
// Observe If AVPlayerItem.status Changed to Fail
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
if let player = object as? AVPlayer, keyPath == #keyPath(AVPlayer.currentItem.status) {
let newStatus: AVPlayerItemStatus
if let newStatusAsNumber = change?[NSKeyValueChangeKey.newKey] as? NSNumber {
newStatus = AVPlayerItemStatus(rawValue: newStatusAsNumber.intValue)!
} else {
newStatus = .unknown
}
if newStatus == .failed {
NSLog("Error: \(String(describing: player.currentItem?.error?.localizedDescription)), error: \(String(describing: player.currentItem?.error))")
}
}
}
// Getting error from Notification payload
func newErrorLogEntry(_ notification: Notification) {
guard let object = notification.object, let playerItem = object as? AVPlayerItem else {
return
}
guard let errorLog: AVPlayerItemErrorLog = playerItem.errorLog() else {
return
}
NSLog("Error: \(errorLog)")
}
func failedToPlayToEndTime(_ notification: Notification) {
let error = notification.userInfo!["AVPlayerItemFailedToPlayToEndTimeErrorKey"]
NSLog("error: \(error)")
} }
同樣的流也適用於Android應用和網絡
我留下我的答案,以防其他人需要它。 經過研究,嘗試和錯誤我終於找到了讓AVPlayer與NGINX rtmp hls一起工作的方法。
發生這種情況的主要原因是服務器上視頻片段的元數據錯誤。 我們必須找到解決這個問題的方法。
這是我對macbook上游視頻的命令,這是典型的:
ffmpeg -f avfoundation -framerate 30 -i "0:0" -f flv -s 360x240 -vcodec libx264 -c:a aac -async 1 -vsync 1 -preset slower rtmp://127.0.0.1/live/xyz
在服務器端,我在Ubuntu 18.10上配置了一個基本的Nginx RTMP HLS,可以通過googling找到它。 請注意,我使用fdk_aac重新編譯最新的ffmpeg。
RTMP有2個應用程序:一個用於接收上游,另一個用於轉碼HLS,這也是典型的。
為了解決元數據問題,我通過添加: -profile:v baseline -level 3.0
調整ffmpeg transcode命令和基線配置文件。 由於顏色格式錯誤,這將導致錯誤,因此我還添加了: -vf "scale=480:trunc(ow/a/2)*2,format=yuv420p"
。
最后,我的nginx配置有效: https : //gist.github.com/chung-nguyen/d88e73e3cc8788878f5ffb8c232b4729
我的AVPlayer代碼在swift中:
let videoURL = URL(string: "http://blogchange.live/hls/xyz_low/index.m3u8")
let playerItem = AVPlayerItem(url: videoURL!)
let adID = AVMetadataItem.identifier(forKey: "X-TITLE", keySpace: .hlsDateRange)
let metadataCollector = AVPlayerItemMetadataCollector(identifiers: [adID!.rawValue], classifyingLabels: nil)
metadataCollector.setDelegate(self, queue: DispatchQueue.main)
playerItem.add(metadataCollector)
let player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
self.player = player
player.play()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.