skip to Main Content

I have a basic video player that presents videos from a url. When the view appears I call player.play() and in doing so I think it causes the error below. I think I have to wait until the video is fully fetched from the url to try and play it. How can I achieve this?

Main thread blocked by synchronous property query on not-yet-loaded property (PreferredTransform) for HTTP(S) asset. This could have been a problem if this asset were being read from a slow network.

import SwiftUI
import AVKit

struct MainVideoPlayer: View {
   let url: URL
   @State var player = AVPlayer(url: URL(string: "https://www.google.com")!)
   
   var body: some View {
       ZStack {
           VideoPlayer(player: $player)
       }
        .onAppear {
           player = AVPlayer(url: url)
           self.player.play()
        }
   }
}

struct VideoPlayer : UIViewControllerRepresentable {
   @Binding var player : AVPlayer
   
   func makeUIViewController(context: UIViewControllerRepresentableContext<VideoPlayer>) -> AVPlayerViewController {

       let controller = AVPlayerViewController()
       controller.player = player
       controller.showsPlaybackControls = false
       controller.videoGravity = .resizeAspectFill
       return controller
   }
   
   func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<VideoPlayer>) { }
}

2

Answers


  1. Can’t use @State or @Binding with classes. That AVPlayerneeds to go inside your AVPlayerViewController. You need a let url and you can use updateUIViewController to start playing if the url is different from last time the representable was init, e.g. something like:

    
    let url: URL
    
    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<VideoPlayer>) { 
    
        if uiViewController.player.url != url {
            uiViewController.player = AVPlayer(url: url)
        }
    }
    
    Login or Signup to reply.
  2. You could try a different (more modern) approach, using Apple VideoPlayer, such as in this example code:

    Works well for me in my tests. On MacOS 14.3, using Xcode 15, tested on real ios 17 devices (and Previews), macCatalyst and MacOS.

    import Foundation
    import SwiftUI
    import AVKit
     
     
    struct ContentView: View {
        var body: some View {
            MainVideoPlayer(url: URL(string: "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4")!)
        }
    }
    
    struct MainVideoPlayer: View {
        let url: URL
        @State var player = AVPlayer()
        
        var body: some View {
            VideoPlayer(player: player)
                .frame(height: 300)
                .onDisappear {
                    player.pause()
                }
                .onAppear {
                    player = AVPlayer(url: url)
                    player.play()
                }
        }
    }
    

    See also: VideoPlayer

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search