Reputation: 39
I’m working on an iOS application that uses AVPlayer to play an HLS stream. My goal is to dynamically append custom parameters to each segment URL (e.g., .ts files) during playback.
Example:
Given an HLS playlist with the following format:
bash
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:5.672333,
ad2_segment_0000.ts
#EXTINF:2.585922,
ad2_segment_0001.ts
#EXTINF:6.756744,
ad2_segment_0002.ts
#EXTINF:3.461789,
ad2_segment_0003.ts
#EXTINF:2.210544,
ad2_segment_0004.ts
#EXTINF:3.712044,
ad2_segment_0005.ts
#EXT-X-ENDLIST
The goal is to modify each segment URL to include custom parameters, like so:
ruby
http://example.com/path/to/ad_segment_0000.ts?paramKey1=paramValue1¶mKey2=paramValue2
Here’s my current approach using AVAssetResourceLoaderDelegate:
import AVFoundation
import UIKit
class ViewController: UIViewController {
var player: AVPlayer?
var playerLayer: AVPlayerLayer?
override func viewDidLoad() {
super.viewDidLoad()
setupPlayer()
}
func setupPlayer() {
// Initialize the asset with the HLS stream URL
guard let url = URL(string: "https://your_hls_stream_url.m3u8") else {
print("Invalid URL")
return
}
let asset = AVURLAsset(url: url)
let resourceLoader = asset.resourceLoader
let loaderDelegate = CustomResourceLoaderDelegate()
// Set the custom resource loader delegate
resourceLoader.setDelegate(loaderDelegate, queue: DispatchQueue.main)
// Create the player item and player
let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem)
// Setup player layer
playerLayer = AVPlayerLayer(player: player)
playerLayer?.frame = self.view.bounds
playerLayer?.videoGravity = .resizeAspect
if let playerLayer = playerLayer {
self.view.layer.addSublayer(playerLayer)
}
// Start playing
player?.play()
}
}
class CustomResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate {
func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
guard let originalURL = loadingRequest.request.url else {
return false
}
// Check if the request is for a .ts segment file
if originalURL.pathExtension == "ts" {
// Append custom parameters
var urlComponents = URLComponents(url: originalURL, resolvingAgainstBaseURL: false)
// Add the parameters you want to include for each .ts request
let customParameters = [
URLQueryItem(name: "param1", value: "value1"),
URLQueryItem(name: "param2", value: "value2")
]
urlComponents?.queryItems = (urlComponents?.queryItems ?? []) + customParameters
// Replace the URL in the request with the modified one
if let modifiedURL = urlComponents?.url {
let redirectedRequest = URLRequest(url: modifiedURL)
loadingRequest.redirect = redirectedRequest
}
}
// Complete the request
loadingRequest.finishLoading()
return true
}
}
Problem:
The above code doesn't seem to work as expected, and I'm unable to modify the segment URLs with custom parameters during playback. Has anyone successfully implemented a similar solution? Any guidance on this approach would be highly appreciated.
Upvotes: 1
Views: 41