Swift4+iOS11+环境下AVPlayer无法播放HLS流问题求助
Hey there, let's work through this HLS streaming problem you're hitting. First off, those console logs you're seeing are probably red herrings:
- The AVOutputDeviceDiscoverySession log is just about route discovery (like detecting AirPlay devices) and has nothing to do with playback failure.
- The CUICatalog "invalid asset name" warning is likely a minor UI asset issue in AVPlayerViewController, not the root cause of your HLS problem.
Here are actionable steps to diagnose and fix the issue:
1. Verify Your HLS Stream is Valid
First, rule out the stream itself being the problem:
- Open the HLS URL (
.m3u8) directly in Safari on your iOS device or Mac. If it doesn't play here, the stream is broken and needs fixing on the server side. - Use Apple's official
mediastreamvalidatorcommand-line tool to check compliance with HLS standards. Run this in Terminal:
This tool will flag issues like invalid encoding, missing media segments, or incompatible bitrates—all common reasons AVPlayer refuses to play a stream.mediastreamvalidator https://your-stream-url.m3u8
2. Add AVPlayer Status & Error Monitoring (It's Not "Old"—It's Necessary!)
I get why you might think KVO is outdated, but for asynchronous resource loading like HLS, it's still the recommended way to catch issues. AVPlayer doesn't throw errors directly; you need to listen for its status changes and error notifications to get concrete details.
Modify your remote stream code to add monitoring:
else { let playerItem = AVPlayerItem(url: vidUrl) // Listen for status changes via KVO playerItem.addObserver(self, forKeyPath: "status", options: [.new, .initial], context: nil) // Listen for playback failure notifications NotificationCenter.default.addObserver( self, selector: #selector(handlePlaybackFailure(_:)), name: .AVPlayerItemFailedToPlayToEndTime, object: playerItem ) vc.player = AVPlayer(playerItem: playerItem) vc.player?.play() }
Then implement the handler methods in your view controller:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard let playerItem = object as? AVPlayerItem, keyPath == "status" else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } switch playerItem.status { case .readyToPlay: print("HLS stream loaded successfully!") case .failed: print("Playback failed with error: \(playerItem.error?.localizedDescription ?? "Unknown error")") // This error message will tell you exactly what's wrong (e.g., network issue, invalid stream) case .unknown: print("Player is still loading the stream...") @unknown default: break } } @objc private func handlePlaybackFailure(_ notification: Notification) { if let error = notification.userInfo?[AVPlayerItemFailedToPlayToEndTimeErrorKey] as? Error { print("Critical playback failure: \(error.localizedDescription)") } }
Don't forget to remove observers when your view controller is deallocated to avoid memory leaks!
3. Check App Transport Security (ATS) Settings
iOS 11+ enforces strict ATS rules by default. If your HLS stream uses HTTP (not HTTPS), or if the HTTPS certificate is invalid (expired, mismatched domain), AVPlayer will block playback.
- To fix this, add an ATS exception in your
Info.plist:- Add a
NSAppTransportSecuritydictionary. - Inside it, add
NSExceptionDomainsas another dictionary. - Add your stream's domain as a key, then set
NSIncludesSubdomainstoYESandNSExceptionAllowsInsecureHTTPLoadstoYES(if using HTTP) orNSExceptionRequiresForwardSecrecytoNO(if your certificate doesn't support forward secrecy).
- Add a
Avoid setting NSAllowsArbitraryLoads to YES unless absolutely necessary—it's not recommended for production apps.
4. Validate Stream Encoding
AVPlayer requires HLS streams to use Apple-supported codecs:
- Video: H.264 (Baseline/Main/High profile) or H.265 (HEVC)
- Audio: AAC-LC, HE-AAC, MP3, or Apple Lossless
If your stream uses unsupported codecs (like VP9), AVPlayer won't play it. The mediastreamvalidator tool we mentioned earlier will flag this.
5. Double-Check AVPlayerViewController Setup
Make sure you're presenting/pushing the AVPlayerViewController correctly:
- Avoid calling
play()before the view controller is fully loaded. If you're initializing it inviewDidLoad, try moving theplay()call toviewDidAppear(_:)instead. - Ensure you're not overriding any AVPlayerViewController properties that might interfere with playback (like custom player layers or playback controls).
Start with validating the stream and adding error monitoring—those two steps will almost certainly point you to the root cause.
内容的提问来源于stack exchange,提问作者Lee Probert

