AVPlayer HLS прямой эфир IOS - PullRequest
       16

AVPlayer HLS прямой эфир IOS

0 голосов
/ 25 апреля 2018

Я пытаюсь использовать HLS для прямой трансляции, но получаю ошибку:

ошибка: необязательная («Операция не может быть завершена»), ошибка: Необязательно (ошибка домена = код AVFoundationErrorDomain = -11800 "мультимедиа формат - описание образца неверно (например, неверный размер) " UserInfo = {NSUnderlyingError = 0x60000005b510 {Ошибка Domain = NSOSStatusErrorDomain Code = -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)")
} }

Вот особенности видео: enter image description here

Также тот же поток работает в приложениях для Android и в Интернете

1 Ответ

0 голосов
/ 23 января 2019

Я оставляю здесь свой ответ на случай, если кому-то еще это понадобится.После исследования, проб и ошибок я наконец-то нашел способ заставить 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

На стороне сервера я настраиваю базовый RTMP NginxHLS на Ubuntu 18.10, который можно узнать, как в Google.Обратите внимание, что я перекомпилирую последнюю версию ffmpeg с помощью fdk_aac.

В RTMP есть 2 приложения: одно для приема в восходящем направлении, а другое для транскодирования HLS, что также типично.

Чтобы устранить проблему с метаданными, я настроилКоманда транскодирования ffmpeg с базовым профилем, добавив: -profile:v baseline -level 3.0.Это приведет к ошибке из-за неправильного формата цвета, поэтому я также добавил: -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()
...