cannot play a video loaded with AVAssetResourceLoaderDelegate

I'm trying to secure my m3u8 streaming link with a token. To achieve this, I'm using AVAssetResourceLoaderDelegate in my SwiftUI app. However, the video doesn't play in AVPlayer when I'm using the AVAssetResourceLoaderDelegate. I can see that data is being received in the resourceLoader, but the player does not start playback.

Here's the code I'm using:

    @State private var player: AVPlayer?
    @EnvironmentObject var pilot: UIPilot<AppRoute>
    var body: some View {
        VStack {
            VerticalSpacer(height: 50)
            HStack {
                Image(systemName: "arrow.left")
                    .onTapGesture {
                        pilot.pop()
                    }
                Spacer()
                Text("liveStreamData.titleShort")
                    .font(.poppins(.semibold, size: 18))
                    .lineLimit(1)
                HorizontalSpacer(width: 16)
                Spacer()
            }
            .padding(.horizontal)
            if let player = player {
                VideoPlayer(player: player)
                    .onAppear {
                        player.play()
                    }
                    .onDisappear {
                        player.pause()
                    }
            } else {
                Text("Loading video...")
            }
        }
        .onAppear {
            setupPlayer()
        }
    }

    private func setupPlayer() {
        guard let url = URL(string: "https://assets.afcdn.com/video49/20210722/v_645516.m3u8") else {
            print("Invalid URL")
            return
        }
        // Replace the scheme with a custom scheme
        var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
        components?.scheme = "customscheme" // Change the scheme to a custom one
        guard let customURL = components?.url else {
            print("Failed to create custom URL")
            return
        }
        let asset = AVURLAsset(url: customURL)
        // Set the resource loader delegate
        let resourceLoaderDelegate = VideoResourceLoaderDelegate()
        asset.resourceLoader.setDelegate(resourceLoaderDelegate, queue: DispatchQueue.main)
        let playerItem = AVPlayerItem(asset: asset)
        player = AVPlayer(playerItem: playerItem)
    }
}

class VideoResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate {
    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
        guard let url = loadingRequest.request.url else {
            print("Invalid request URL")
            return false
        }
        // Replace the custom scheme with the original HTTP/HTTPS scheme
        var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
        components?.scheme = "https" // Change the scheme back to HTTP/HTTPS
        guard let originalURL = components?.url else {
            print("Failed to convert URL back to HTTPS")
            return false
        }
        // Fetch the data from the original URL
        let urlSession = URLSession.shared
        let task = urlSession.dataTask(with: originalURL) { data, response, error in
            if let error = error {
                print("Error loading resource: \(error)")
                loadingRequest.finishLoading(with: error)
                return
            }
            if let data = data, let dataRequest = loadingRequest.dataRequest {
                print("Data loaded: \(data.count) bytes")
                dataRequest.respond(with: data)
                loadingRequest.finishLoading()
            } else {
                print("No data received")
                loadingRequest.finishLoading(with: NSError(domain: "VideoResourceLoader", code: -1, userInfo: nil))
            }
        }
        task.resume()
        return true
    }

    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, didCancel loadingRequest: AVAssetResourceLoadingRequest) {
        print("Loading request was canceled")
    }
}

Problem:

The video does not play when using AVAssetResourceLoaderDelegate. The data is being loaded correctly as confirmed by the logs, but AVPlayer fails to start playback. Without the resource loader, the video plays without any issues. Question:

What could be causing the player to not play the video when using AVAssetResourceLoaderDelegate? Are there any additional steps or configurations I need to ensure smooth playback while using a resource loader? Any help would be greatly appreciated!

Hello @Iotait, thank you for posting a code snippet. In the delegate method, you are retrieving the original URL, initiating a data task, and providing the resulting data to the dataRequest. But the data you are providing contains the stream's playlist (.m3u8) text data. Instead, your implementation needs to respond to the data requests with media data. To accomplish that, your delegate needs to first handle the contentInformationRequest, providing information about the media asset you are trying to load, and then respond to the data requests providing media data. Please see the AVARLDelegateDemo sample code project for an example implementation.

@Engineer Thanks for replaying, Actually i am not familiar with objective c, can you please help me with swift example?

cannot play a video loaded with AVAssetResourceLoaderDelegate
 
 
Q