When I try to play video on my Apple Vision Pro simulator using a custom view with an AVPlayerLayer (as seen in my below VideoPlayerView), nothing displays but a black screen while the audio for the video i'm trying to play plays in the background. I've tried everything I can think of to resolve this issue, but to no avail.
import SwiftUI import AVFoundation import AVKit struct VideoPlayerView: UIViewRepresentable { var player: AVPlayer func makeUIView(context: Context) -> UIView { let view = UIView(frame: .zero) let playerLayer = AVPlayerLayer(player: player) playerLayer.videoGravity = .resizeAspect view.layer.addSublayer(playerLayer) return view } func updateUIView(_ uiView: UIView, context: Context) { if let layer = uiView.layer.sublayers?.first as? AVPlayerLayer { layer.frame = uiView.bounds } } }
I have noticed however that if i use the default VideoPlayer (as demonstrated below), and not my custom VideoPlayerView, the video displays just fine, but any modifiers I use on that VideoPlayer (like the ones in my above custom struct), cause the video to display black while the audio plays in the background.
import SwiftUI import AVKit struct MyView: View { var player: AVPlayer var body: some View { ZStack { VideoPlayer(player: player)
Does anyone know a solution to this problem to make it so that video is able to display properly and not just appear as a black screen with audio playing in the background?
SOLVED:
It took me literal months to figure this out but alas, there is actually a solution to this problem. If you ever use an AVPlayer in a visionOS app and find that your video is displaying as a black screen whilst the audio plays in the background, use some variant of this implementation below.
The solution: create a custom view for your AVPlayer as is done below
import SwiftUI import AVKit // Define a UIView subclass to host the AVPlayerLayer class PlayerView: UIView { private var playerLayer = AVPlayerLayer() // Initialize with an AVPlayer init(player: AVPlayer) { super.init(frame: .zero) playerLayer.player = player playerLayer.videoGravity = .resizeAspect // Adjust as needed layer.addSublayer(playerLayer) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() playerLayer.frame = bounds } } // UIViewRepresentable wrapper for the PlayerView struct VideoPlayerView: UIViewRepresentable { var player: AVPlayer func makeUIView(context: Context) -> PlayerView { return PlayerView(player: player) } func updateUIView(_ uiView: PlayerView, context: Context) { // No need to update anything for now; the PlayerView handles resizing } }
Then use this custom view in your program wherever needed like this:
struct ContentView: View { var player: AVPlayer var body: some View { VideoPlayerView(player: player) } }