Streaming

RSS for tag

Deep dive into the technical specifications that influence seamless playback for streaming services, including bitrates, codecs, and caching mechanisms.

Streaming Documentation

Posts under Streaming subtopic

Post

Replies

Boosts

Views

Activity

How to implement Trick Play in a custom AVPlayer?
Hi. We have a custom player and would like to implement trick play(show preview thumbnail of the content as user scrubs on the slider). Stream format is .m3u8 and the manifest does have "EXT-X-I-FRAME-STREAM-INF" tag mentioned in specification. But we are clueless about how to utilise it and show thumbnail above the slider. Looking forward to the help. Thank you.
0
0
1.3k
Dec ’21
AVPlayer HLS Restirect Stream Resulotion
Hello, we have HLS stream app and we use AVPlayer for HLS stream. We want to implement dynamic resulotion feature as user's selection. For example, if user want to watch only 1080p user has to watch only 1080p but we have tried to implement "preferredMaximumResolution" and "preferredPeakBitRate" parameters and but AVPlayer does not force it which means that setting preferredMaximumResolution= CGSize(width: 1920, height: 1080) player does not only force to play 1080p profile, player drops resulotion to 720p but we do not want 720p stream if user selected 1080p resulotion. Is there any method to force it even if stream stalls? Thank you in advance
0
0
898
Oct ’24
AppleTV HLS player with metrics?
Hello, I am running some simple playback tests. I would like to playback content streamed via HLS manifest on my AppleTV device, ideally with playback metrics. I should be able to use something like the VLC app: https://www.videolan.org/vlc/download-appletv.html (open to suggestions) But as for metrics, im not 100%. Does anyone have experience on this topic? As for the specific metrics, Im just looking for something that I can use to objectively measure different tests. I was thinking anything related to buffer rates, error rates, and percentage of time playing back specific streams.
0
0
841
May ’23
iOS 16.1 Safari/Chrome with video js player 7.18 fails with Fairplay DRM playback
On updating to iOS 16.1 we started having playback failure for all our drm content on safari/chrome for ios which uses fairplay. Versions below 16.0 or earlier do not have this issue. We have tried using video js player with minimum eme plugins required to play drm/fairplay and no player customizations, that still doesn't play back. We get the media decoder saying : VIDEOJS: ERROR: (CODE:3 MEDIA_ERR_DECODE) The media playback was aborted due to a corruption problem or because the media used features your browser did not support. MediaError {code: 3, message: "The media playback was aborted due to a corruption…media used features your browser did not support."} This issue looks localized to fairplay on ios 16.1. Has there been any changes to fairplay on ios browsers?.
0
1
3.5k
Nov ’22
LL-HLS preload hint issue
Im a developer for Low-Latency HLS protocol. I found some doubts when reading contents about preload hint/blocking. Suppose that a media segment of 2 seconds long is divided into 10 partial segments, which means that each part segment is 0.2 second long. At the point the last part segment is completed, how should I provide a preload hint? Should I give a preload hint for 11-th part, although it will never generate? or first part for next media segment? How should I write a rate index file when facing this situation? https://developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls
0
0
709
Nov ’21
Issues Detecting Apple TV's HDR Playback Capability
I've been working with the eligibleforhdrplayback property to determine if HDR playback is supported. However, I've noticed an inconsistency. When the video format switches from HDR to SDR in settings menu on Apple TV, the property still returns true, indicating HDR is playable even when it's not (This seems to contradict what was mentioned around the [20:40] mark of this WWDC video). I've tried using the eligibleForHDRPlaybackDidChangeNotification and even restarted the app, but I still encounter the same issue. Are there alternative approaches to accurately determine if the app can play HDR content on Apple TV?
0
0
685
Oct ’23
New FairPlay Keys
Hello, My company has an in-store app with FPS SDK 4.x (1024) keys. We've handed those keys over to a trusted third-party and we do not have them. We've been in-store for several years. The person that created the keys in our organization mistakenly stored them encrypted to our third-party's PGP keys, so we cannot decrypt them, and the third party also has no mechanism to provide us with the keys even though it is in their runtime environment. They only have secure mechanisms for us to upload keys onto their servers. We are trying to migrate to a different third-party DRM provider, and would like to obtain new keys. Unfortunately, the developer portal won't let me create new keys, saying that we have exceeded the number of keys allowed, which I assume is one. Additionally, the new DRM provider can only support SDK 4.x keys, and it appears that we can only request SDK 5.x keys on the Apple Developer portal, as the SDK 4.0 option is grayed out. Regardless, it seems that we are not able to request any keys. We've submitted a request to the support e-mail address and received an automated e-mail that the response should take a few days, but may take longer on occasion. It's now been a month. The e-mail says that the reply address is not monitored. Is there any way we can accelerate this? Thank you, Carlos
0
1
438
Aug ’25
AVPlayer and HLS streams timeout
I find the default timeout of 1 second to download a segment is not reasonable when playing an HLS stream from a server that is transcoding. Does anyone know if it's possible to change this networking timeout? Error status: -12889, Error domain: CoreMediaErrorDomain, Error comment: No response for map in 1s. Event: <AVPlayerItemErrorLogEvent: 0x301866250> Also there is a delegate to control downloading HLS for offline viewing but no delegate for just streaming HLS.
0
0
912
Jul ’24
VTT Special Characters not displaying properly sometimes
When choosing to display a foreign audio track on some videos, the text does not render correctly. instead of a musical note I see white boxes for instance. This issue does not occur for the same content on Safari for Mac or Safari for iPad. The issue does present itself for a native mobile app (AVPlayer) on the same iPad, Safari for iPhone and the native mobile app on iPhone. Below is an image of the issue, the left is what I see on a problematic device and the right is what I would expect. Are there any known issues or workaround for this?
0
0
1.5k
Dec ’22
Couldn't able to hear audio via speaker on ios real device
This is my native module code implementation I'm getting base64 encoded string from server and passing this to my native module of pcm player to play audio App.tsx PcmPlayer.writeChunk(e.data); PcmPlayer.swift import AVFoundation @objc(PcmPlayer) class PcmPlayer: RCTEventEmitter { private var engine: AVAudioEngine? private var playerNode: AVAudioPlayerNode? private var format: AVAudioFormat? private var bufferQueue = [Data]() private var isPlaying = false private var hasEnded = false private var scheduledBufferCount = 0 private let minBufferBytes = 50000 private let pcmQueue = DispatchQueue(label: "pcm.queue") override init() { super.init() } override func supportedEvents() -> [String]! { return ["onStatus", "onMessage"] } @objc(initPlayer:channels:bitsPerSample:) func initPlayer(_ sampleRate: NSNumber, channels: NSNumber, bitsPerSample: NSNumber) { pcmQueue.async { self.stopInternal() let session = AVAudioSession.sharedInstance() do { try session.setCategory(.playback, mode: .default, options: []) try session.setActive(true, options: .notifyOthersOnDeactivation) try session.setMode(.default) print("🔈 Audio session active. Output route:", session.currentRoute.outputs) } catch { print("❌ Audio session setup failed:", error) return } self.engine = AVAudioEngine() self.playerNode = AVAudioPlayerNode() guard let engine = self.engine, let playerNode = self.playerNode else { print("❌ Engine or playerNode is nil") return } engine.attach(playerNode) self.format = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: sampleRate.doubleValue, channels: AVAudioChannelCount(channels.uintValue), interleaved: false) guard let format = self.format else { print("❌ Failed to create AVAudioFormat") return } engine.connect(playerNode, to: engine.mainMixerNode, format: format) do { try engine.start() playerNode.play() engine.mainMixerNode.outputVolume = 1.0 print("✅ AVAudioEngine started with format:", format) } catch { print("❌ Engine start failed:", error) } self.hasEnded = false } } @objc(writeChunk:) func writeChunk(_ base64Pcm: String) { pcmQueue.async { guard base64Pcm.count >= 10 else { print("⚠️ Skipping short base64 string") return } var padded = base64Pcm let mod4 = base64Pcm.count % 4 if mod4 > 0 { padded += String(repeating: "=", count: 4 - mod4) } guard let data = Data(base64Encoded: padded, options: .ignoreUnknownCharacters) else { print("❌ Failed to decode base64") return } self.bufferQueue.append(data) print("📥 Received PCM chunk (\(data.count) bytes)") print("📥 writeChunk called. isPlaying=\(self.isPlaying), bufferQueue.count=\(self.bufferQueue.count)") if !self.isPlaying { self.isPlaying = true self.waitForBufferAndStartPlayback() } else if self.scheduledBufferCount == 0 { self.isPlaying = true self.waitForBufferAndStartPlayback() } } } private func waitForBufferAndStartPlayback() { DispatchQueue.global().async { while self.queueSize() < self.minBufferBytes && !self.hasEnded { Thread.sleep(forTimeInterval: 0.01) } self.writeLoop() } } private func writeLoop() { DispatchQueue.global().async { writeLoop: while self.isPlaying { if self.bufferQueue.isEmpty { for _ in 0..<100 { Thread.sleep(forTimeInterval: 0.01) if !self.bufferQueue.isEmpty { break } } if self.bufferQueue.isEmpty { print("🔇 No more data to play after waiting") self.isPlaying = false break writeLoop } } var data: Data? self.pcmQueue.sync { if !self.bufferQueue.isEmpty { data = self.bufferQueue.removeFirst() } } guard let chunk = data else { print("⚠️ No data to process") continue } if let buffer = self.pcmBufferFromData(chunk) { self.scheduledBufferCount += 1 self.playerNode?.scheduleBuffer(buffer, completionHandler: { self.pcmQueue.async { self.scheduledBufferCount -= 1 if self.bufferQueue.isEmpty && self.scheduledBufferCount == 0 { print("ℹ️ Playback idle - waiting for more data") self.isPlaying = false } } }) } } } } private func pcmBufferFromData(_ data: Data) -> AVAudioPCMBuffer? { guard let format = self.format else { return nil } let frameCount = UInt32(data.count / 2) guard let buffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: frameCount) else { print("❌ Failed to create AVAudioPCMBuffer") return nil } buffer.frameLength = frameCount guard let floatChannelData = buffer.floatChannelData?[0] else { print("❌ floatChannelData is nil") return nil } data.withUnsafeBytes { (rawBuffer: UnsafeRawBufferPointer) in let int16Buffer = rawBuffer.bindMemory(to: Int16.self) let count = min(int16Buffer.count, Int(frameCount)) for i in 0..<count { floatChannelData[i] = Float32(int16Buffer[i]) / Float32(Int16.max) } } return buffer } @objc(stopPlayer) func stopPlayer() { pcmQueue.async { self.stopInternal() } } private func stopInternal() { print("🛑 stopInternal called") self.playerNode?.stop() self.engine?.stop() self.engine?.reset() self.playerNode = nil self.engine = nil self.format = nil self.bufferQueue.removeAll() self.isPlaying = false self.hasEnded = true self.scheduledBufferCount = 0 } @objc(canWrite:rejecter:) func canWrite(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) { pcmQueue.async { resolve(self.bufferQueue.count < 20) } } @objc(flushPlayer:rejecter:) func flushPlayer(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) { pcmQueue.async { self.bufferQueue.removeAll() resolve(nil) } } @objc static override func requiresMainQueueSetup() -> Bool { return false } private func queueSize() -> Int { return pcmQueue.sync { return self.bufferQueue.reduce(0) { $0 + $1.count } } } } I couldn't able to hear any audio via my real iOS device also it is working fine on emulator.
0
0
362
Jul ’25
FairPlay license auto-renewal (on SPC request)
Hi, is it possible to force/ensure an automatic license renewal in a Fairplay SPC response? I can find that feature in other DRM systems like Widevine (using specific parameters in the response) Searching in "FairPlay Streaming Server SDK 4.4.4" I can only find parameters related to lease/rental TLLs, but not an explicit renewal request. does this feature exists on FairPlay? Any information will be appreciated. Have a great day!
0
0
957
Jun ’23
Unknown error -12881 when using AVAssetResourceLoader
Here we are focusing to change the cookie at every 120 seconds while playing , in apple avplayer we can't modify cookie after initialisation due to that we followed the approach to using " Resource loader delegate " to pass cookie as a header value . What I notice is that the playlist file (.m3u8) gets downloaded correctly. Then video file (.m4a) some chunks also gets downloaded. I know that the .ts file is downloaded because I can see the GET request completing on the web server with status 200. I also set a breakpoint at the following line: loadingRequest.dataRequest?.respond(with: data) immediately got error from avplayer status as "The operation could not be completed. An unknown error occurred (-12881) From core media" Need confirmation on why I am unable to load HLS using resource loader. is it possible to update cookie value while paying continuously on avplayer. override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. let urlString = "localhost://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8" guard let url = URL(string: urlString) else { print("Invalid URL") return } //Create cookie to prepare for player asset let cookie = HTTPCookie(properties: [ .name: "dazn-token", .value: "cookie value", .domain: url.host() ?? "", .path: "/", .discard: true ]) //Create cookie key to set AVURLAsset let options = [AVURLAssetHTTPCookiesKey: [cookie]] let asset = AVURLAsset(url: url,options: options) proxy = ReverseProxyResourceLoader() proxy?.cookie = "exampleCookie" // Set resource loader delegate to moniter the chunks asset.resourceLoader.setDelegate(proxy, queue: DispatchQueue.global()) // Load asset keys asynchronously (e.g., "playable") let keys = ["playable"] // Initialize the AVPlayer with the URL let playerItem = AVPlayerItem(asset: asset) self.player = AVPlayer(playerItem: playerItem) playerItem.addObserver(self, forKeyPath: "status", options: [.new, .initial], context: nil) // Observe 'error' property (if needed) playerItem.addObserver(self, forKeyPath: "error", options: [.new], context: nil) let contentKeySessionDelegate = ContentKeyDelegate() // Initialize AVContentKeySession let contentKeySession = AVContentKeySession(keySystem: .clearKey) self.contentKeySession = contentKeySession contentKeySession.setDelegate(contentKeySessionDelegate, queue: DispatchQueue.main) // Associate the asset with the content key session contentKeySession.addContentKeyRecipient(asset) // Create a layer for the AVPlayer and add it to the view playerLayer = AVPlayerLayer(player: player) playerLayer?.frame = view.bounds playerLayer?.videoGravity = .resizeAspect if let playerLayer = playerLayer { view.layer.addSublayer(playerLayer) } NotificationCenter.default.addObserver( self, selector: #selector(playerDidFinishPlaying), name: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem ) // Start playback player?.play() } // Update cookie when ever needed func updateCookie() { proxy?.cookie = "update exampleCookie" } @objc private func playerDidFinishPlaying(notification: Notification) { print("Playback finished!") // Optionally, handle end-of-playback actions here } // // ReverseProxyResourceLoader.swift // HLSDemo // // Created by Gajje.Venkatarao on 12/12/24. // import Foundation import AVKit import AVFoundation class ReverseProxyResourceLoader: NSObject, AVAssetResourceLoaderDelegate { var cookie = "" func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool { resourceLoader.preloadsEligibleContentKeys = true guard let interceptedURL = loadingRequest.request.url else { loadingRequest.finishLoading(with: NSError(domain: "ReverseProxy", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])) return false } if interceptedURL.scheme == "skd" { print("Token updated Cookie:", interceptedURL ) return false } var components = URLComponents(url: interceptedURL, resolvingAgainstBaseURL: false) components?.scheme = "https" // Replace with the original scheme guard let originalURL = components?.url else { loadingRequest.finishLoading(with: NSError(domain: "ReverseProxy", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to map URL"])) loadingRequest.finishLoading() return false } var request = URLRequest(url: originalURL) request.httpMethod = "GET" if let storeCoockie = HTTPCookie(properties: [ .name: "dazn-token", .value: cookie, .domain: originalURL.host ?? "", .path: "/", .discard: true ]){ HTTPCookieStorage.shared.setCookie(storeCoockie) } let headers = loadingRequest.request.allHTTPHeaderFields ?? [:] for (key, value) in headers { request.addValue(value, forHTTPHeaderField: key) } request.addValue(cookie, forHTTPHeaderField: "Cookie") URLSession.shared.configuration.httpShouldSetCookies = true request.httpShouldHandleCookies = true let task = (URLSession.shared.dataTask(with: originalURL) { data, response, error in if let error = error { print("Error Received:", error) loadingRequest.finishLoading(with: error) return } print(originalURL) guard let data = data , let url = response?.url else { loadingRequest.finishLoading(with: NSError(domain: "ReverseProxy", code: -1, userInfo: [NSLocalizedDescriptionKey: "No data received"])) return } loadingRequest.dataRequest?.respond(with: data) loadingRequest.finishLoading() } as URLSessionDataTask) task.resume() return true } } Example project
0
0
834
Dec ’24
Lightweight RTSP lib on iOS
idk why there isn't built in lib for watch RTSP stream on iOS of apple framework list, even though rtsp is popular. Can i built my own with swift,? have any tutorial for this purpose, i did try many framework like VLCMobileKit,.. it work but I can't understand why it so many enomous files and account for 400mb to 1.7gb for installed pod and have so many bug i cannot fix when usage (so hard to maintain). Can you suggest for me how to built my own with swift. As my knowledge our camera only support for RTSP so I'm not using HTTP Live Stream, it is true? can I use HTTP Live Streaming for this purpose.
0
0
887
Dec ’21
updateConfiguration no work sometimes
I'm using screenCaptureKit for winodow capture. I build a filter like follow code, (I'm not usng independent window filter, because sometime I need capture multi windows in the same time) filter = [[SCContentFilter alloc] initWithDisplay:displayID includingWindows:includingWindows]; At begining, the capture works OK. When the target window's size or position changed, my code monitored this change and called updateConfiguration like below , I got completionHandler without error. [streamConfiguration setSourceRect:newRect]; [streamConfiguration setWidth:newWidth]; [streamConfiguration setHeight:newHeight]; [scStream updateConfiguration:streamConfiguration completionHandler:^(NSError *_Nullable error) { if (error) { // some error log } else { // update done } }]; But sometimes, it still output frame with old size, and the rect is still the old. And int some other cases, it works fine..... Is there any special work before call updateConfiguration to make it work ?
0
0
658
Aug ’24
Playing FairPlay encrypted content works fine on ios17 but won't play on ios26
For devices that are still on ios17, playing Fairplay encrypted content still works fine. For devices that I've upgraded to ios26 playing the same content in the same app no longer works. I can advance and see the stream frames by tapping +10 scrubbing so I know that the content is being decrypted but tapping the play button of AVPlayer for an AVPlayerItem now does nothing in ios26. Is this a breaking change or is there a stricter requirement that I now have to implement?
0
0
370
Oct ’25
How to retrieve the playback state
Per FP Streaming programming guide, The SPC includes a specific TLLV to provide the state of the media content playback. And total value length of this is 16 in decimals. Here i'm trying to retrieve the Playback State. which is of 20-23 ByteRange. byte[] mediaPlaybackStateBlock = getBlock(MEDIA_PLAYBACK_STATE).getValueData(); playbackState = Arrays.copyOfRange(mediaPlaybackStateBlock, 20, 24); I'm endup in issue - arraycopy: length -4 is negative. I'm bit confused on how to retrieve the playback state from 20-23 ByteRange when its length jus 16.. Kindly clarify
0
0
682
Jan ’24
How to implement Trick Play in a custom AVPlayer?
Hi. We have a custom player and would like to implement trick play(show preview thumbnail of the content as user scrubs on the slider). Stream format is .m3u8 and the manifest does have "EXT-X-I-FRAME-STREAM-INF" tag mentioned in specification. But we are clueless about how to utilise it and show thumbnail above the slider. Looking forward to the help. Thank you.
Replies
0
Boosts
0
Views
1.3k
Activity
Dec ’21
AVPlayer HLS Restirect Stream Resulotion
Hello, we have HLS stream app and we use AVPlayer for HLS stream. We want to implement dynamic resulotion feature as user's selection. For example, if user want to watch only 1080p user has to watch only 1080p but we have tried to implement "preferredMaximumResolution" and "preferredPeakBitRate" parameters and but AVPlayer does not force it which means that setting preferredMaximumResolution= CGSize(width: 1920, height: 1080) player does not only force to play 1080p profile, player drops resulotion to 720p but we do not want 720p stream if user selected 1080p resulotion. Is there any method to force it even if stream stalls? Thank you in advance
Replies
0
Boosts
0
Views
898
Activity
Oct ’24
AppleTV HLS player with metrics?
Hello, I am running some simple playback tests. I would like to playback content streamed via HLS manifest on my AppleTV device, ideally with playback metrics. I should be able to use something like the VLC app: https://www.videolan.org/vlc/download-appletv.html (open to suggestions) But as for metrics, im not 100%. Does anyone have experience on this topic? As for the specific metrics, Im just looking for something that I can use to objectively measure different tests. I was thinking anything related to buffer rates, error rates, and percentage of time playing back specific streams.
Replies
0
Boosts
0
Views
841
Activity
May ’23
iOS 16.1 Safari/Chrome with video js player 7.18 fails with Fairplay DRM playback
On updating to iOS 16.1 we started having playback failure for all our drm content on safari/chrome for ios which uses fairplay. Versions below 16.0 or earlier do not have this issue. We have tried using video js player with minimum eme plugins required to play drm/fairplay and no player customizations, that still doesn't play back. We get the media decoder saying : VIDEOJS: ERROR: (CODE:3 MEDIA_ERR_DECODE) The media playback was aborted due to a corruption problem or because the media used features your browser did not support. MediaError {code: 3, message: "The media playback was aborted due to a corruption…media used features your browser did not support."} This issue looks localized to fairplay on ios 16.1. Has there been any changes to fairplay on ios browsers?.
Replies
0
Boosts
1
Views
3.5k
Activity
Nov ’22
LL-HLS preload hint issue
Im a developer for Low-Latency HLS protocol. I found some doubts when reading contents about preload hint/blocking. Suppose that a media segment of 2 seconds long is divided into 10 partial segments, which means that each part segment is 0.2 second long. At the point the last part segment is completed, how should I provide a preload hint? Should I give a preload hint for 11-th part, although it will never generate? or first part for next media segment? How should I write a rate index file when facing this situation? https://developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls
Replies
0
Boosts
0
Views
709
Activity
Nov ’21
Issues Detecting Apple TV's HDR Playback Capability
I've been working with the eligibleforhdrplayback property to determine if HDR playback is supported. However, I've noticed an inconsistency. When the video format switches from HDR to SDR in settings menu on Apple TV, the property still returns true, indicating HDR is playable even when it's not (This seems to contradict what was mentioned around the [20:40] mark of this WWDC video). I've tried using the eligibleForHDRPlaybackDidChangeNotification and even restarted the app, but I still encounter the same issue. Are there alternative approaches to accurately determine if the app can play HDR content on Apple TV?
Replies
0
Boosts
0
Views
685
Activity
Oct ’23
New FairPlay Keys
Hello, My company has an in-store app with FPS SDK 4.x (1024) keys. We've handed those keys over to a trusted third-party and we do not have them. We've been in-store for several years. The person that created the keys in our organization mistakenly stored them encrypted to our third-party's PGP keys, so we cannot decrypt them, and the third party also has no mechanism to provide us with the keys even though it is in their runtime environment. They only have secure mechanisms for us to upload keys onto their servers. We are trying to migrate to a different third-party DRM provider, and would like to obtain new keys. Unfortunately, the developer portal won't let me create new keys, saying that we have exceeded the number of keys allowed, which I assume is one. Additionally, the new DRM provider can only support SDK 4.x keys, and it appears that we can only request SDK 5.x keys on the Apple Developer portal, as the SDK 4.0 option is grayed out. Regardless, it seems that we are not able to request any keys. We've submitted a request to the support e-mail address and received an automated e-mail that the response should take a few days, but may take longer on occasion. It's now been a month. The e-mail says that the reply address is not monitored. Is there any way we can accelerate this? Thank you, Carlos
Replies
0
Boosts
1
Views
438
Activity
Aug ’25
AVPlayer and HLS streams timeout
I find the default timeout of 1 second to download a segment is not reasonable when playing an HLS stream from a server that is transcoding. Does anyone know if it's possible to change this networking timeout? Error status: -12889, Error domain: CoreMediaErrorDomain, Error comment: No response for map in 1s. Event: <AVPlayerItemErrorLogEvent: 0x301866250> Also there is a delegate to control downloading HLS for offline viewing but no delegate for just streaming HLS.
Replies
0
Boosts
0
Views
912
Activity
Jul ’24
New FairPlay Streaming (FPS) credentials
Hi, I have a question about FairPlay Streaming (FPS) credentials. When a new set of FPS credentials is requested, will existing FPS Credentials on a live app continue to function until it is swapped for the new ones?  Or will the existing FPS credentials immediately cease to function upon issuing new FPS credentials?
Replies
0
Boosts
0
Views
720
Activity
Mar ’23
VTT Special Characters not displaying properly sometimes
When choosing to display a foreign audio track on some videos, the text does not render correctly. instead of a musical note I see white boxes for instance. This issue does not occur for the same content on Safari for Mac or Safari for iPad. The issue does present itself for a native mobile app (AVPlayer) on the same iPad, Safari for iPhone and the native mobile app on iPhone. Below is an image of the issue, the left is what I see on a problematic device and the right is what I would expect. Are there any known issues or workaround for this?
Replies
0
Boosts
0
Views
1.5k
Activity
Dec ’22
Couldn't able to hear audio via speaker on ios real device
This is my native module code implementation I'm getting base64 encoded string from server and passing this to my native module of pcm player to play audio App.tsx PcmPlayer.writeChunk(e.data); PcmPlayer.swift import AVFoundation @objc(PcmPlayer) class PcmPlayer: RCTEventEmitter { private var engine: AVAudioEngine? private var playerNode: AVAudioPlayerNode? private var format: AVAudioFormat? private var bufferQueue = [Data]() private var isPlaying = false private var hasEnded = false private var scheduledBufferCount = 0 private let minBufferBytes = 50000 private let pcmQueue = DispatchQueue(label: "pcm.queue") override init() { super.init() } override func supportedEvents() -> [String]! { return ["onStatus", "onMessage"] } @objc(initPlayer:channels:bitsPerSample:) func initPlayer(_ sampleRate: NSNumber, channels: NSNumber, bitsPerSample: NSNumber) { pcmQueue.async { self.stopInternal() let session = AVAudioSession.sharedInstance() do { try session.setCategory(.playback, mode: .default, options: []) try session.setActive(true, options: .notifyOthersOnDeactivation) try session.setMode(.default) print("🔈 Audio session active. Output route:", session.currentRoute.outputs) } catch { print("❌ Audio session setup failed:", error) return } self.engine = AVAudioEngine() self.playerNode = AVAudioPlayerNode() guard let engine = self.engine, let playerNode = self.playerNode else { print("❌ Engine or playerNode is nil") return } engine.attach(playerNode) self.format = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: sampleRate.doubleValue, channels: AVAudioChannelCount(channels.uintValue), interleaved: false) guard let format = self.format else { print("❌ Failed to create AVAudioFormat") return } engine.connect(playerNode, to: engine.mainMixerNode, format: format) do { try engine.start() playerNode.play() engine.mainMixerNode.outputVolume = 1.0 print("✅ AVAudioEngine started with format:", format) } catch { print("❌ Engine start failed:", error) } self.hasEnded = false } } @objc(writeChunk:) func writeChunk(_ base64Pcm: String) { pcmQueue.async { guard base64Pcm.count >= 10 else { print("⚠️ Skipping short base64 string") return } var padded = base64Pcm let mod4 = base64Pcm.count % 4 if mod4 > 0 { padded += String(repeating: "=", count: 4 - mod4) } guard let data = Data(base64Encoded: padded, options: .ignoreUnknownCharacters) else { print("❌ Failed to decode base64") return } self.bufferQueue.append(data) print("📥 Received PCM chunk (\(data.count) bytes)") print("📥 writeChunk called. isPlaying=\(self.isPlaying), bufferQueue.count=\(self.bufferQueue.count)") if !self.isPlaying { self.isPlaying = true self.waitForBufferAndStartPlayback() } else if self.scheduledBufferCount == 0 { self.isPlaying = true self.waitForBufferAndStartPlayback() } } } private func waitForBufferAndStartPlayback() { DispatchQueue.global().async { while self.queueSize() < self.minBufferBytes && !self.hasEnded { Thread.sleep(forTimeInterval: 0.01) } self.writeLoop() } } private func writeLoop() { DispatchQueue.global().async { writeLoop: while self.isPlaying { if self.bufferQueue.isEmpty { for _ in 0..<100 { Thread.sleep(forTimeInterval: 0.01) if !self.bufferQueue.isEmpty { break } } if self.bufferQueue.isEmpty { print("🔇 No more data to play after waiting") self.isPlaying = false break writeLoop } } var data: Data? self.pcmQueue.sync { if !self.bufferQueue.isEmpty { data = self.bufferQueue.removeFirst() } } guard let chunk = data else { print("⚠️ No data to process") continue } if let buffer = self.pcmBufferFromData(chunk) { self.scheduledBufferCount += 1 self.playerNode?.scheduleBuffer(buffer, completionHandler: { self.pcmQueue.async { self.scheduledBufferCount -= 1 if self.bufferQueue.isEmpty && self.scheduledBufferCount == 0 { print("ℹ️ Playback idle - waiting for more data") self.isPlaying = false } } }) } } } } private func pcmBufferFromData(_ data: Data) -> AVAudioPCMBuffer? { guard let format = self.format else { return nil } let frameCount = UInt32(data.count / 2) guard let buffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: frameCount) else { print("❌ Failed to create AVAudioPCMBuffer") return nil } buffer.frameLength = frameCount guard let floatChannelData = buffer.floatChannelData?[0] else { print("❌ floatChannelData is nil") return nil } data.withUnsafeBytes { (rawBuffer: UnsafeRawBufferPointer) in let int16Buffer = rawBuffer.bindMemory(to: Int16.self) let count = min(int16Buffer.count, Int(frameCount)) for i in 0..<count { floatChannelData[i] = Float32(int16Buffer[i]) / Float32(Int16.max) } } return buffer } @objc(stopPlayer) func stopPlayer() { pcmQueue.async { self.stopInternal() } } private func stopInternal() { print("🛑 stopInternal called") self.playerNode?.stop() self.engine?.stop() self.engine?.reset() self.playerNode = nil self.engine = nil self.format = nil self.bufferQueue.removeAll() self.isPlaying = false self.hasEnded = true self.scheduledBufferCount = 0 } @objc(canWrite:rejecter:) func canWrite(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) { pcmQueue.async { resolve(self.bufferQueue.count < 20) } } @objc(flushPlayer:rejecter:) func flushPlayer(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) { pcmQueue.async { self.bufferQueue.removeAll() resolve(nil) } } @objc static override func requiresMainQueueSetup() -> Bool { return false } private func queueSize() -> Int { return pcmQueue.sync { return self.bufferQueue.reduce(0) { $0 + $1.count } } } } I couldn't able to hear any audio via my real iOS device also it is working fine on emulator.
Replies
0
Boosts
0
Views
362
Activity
Jul ’25
FairPlay license auto-renewal (on SPC request)
Hi, is it possible to force/ensure an automatic license renewal in a Fairplay SPC response? I can find that feature in other DRM systems like Widevine (using specific parameters in the response) Searching in "FairPlay Streaming Server SDK 4.4.4" I can only find parameters related to lease/rental TLLs, but not an explicit renewal request. does this feature exists on FairPlay? Any information will be appreciated. Have a great day!
Replies
0
Boosts
0
Views
957
Activity
Jun ’23
Unknown error -12881 when using AVAssetResourceLoader
Here we are focusing to change the cookie at every 120 seconds while playing , in apple avplayer we can't modify cookie after initialisation due to that we followed the approach to using " Resource loader delegate " to pass cookie as a header value . What I notice is that the playlist file (.m3u8) gets downloaded correctly. Then video file (.m4a) some chunks also gets downloaded. I know that the .ts file is downloaded because I can see the GET request completing on the web server with status 200. I also set a breakpoint at the following line: loadingRequest.dataRequest?.respond(with: data) immediately got error from avplayer status as "The operation could not be completed. An unknown error occurred (-12881) From core media" Need confirmation on why I am unable to load HLS using resource loader. is it possible to update cookie value while paying continuously on avplayer. override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. let urlString = "localhost://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8" guard let url = URL(string: urlString) else { print("Invalid URL") return } //Create cookie to prepare for player asset let cookie = HTTPCookie(properties: [ .name: "dazn-token", .value: "cookie value", .domain: url.host() ?? "", .path: "/", .discard: true ]) //Create cookie key to set AVURLAsset let options = [AVURLAssetHTTPCookiesKey: [cookie]] let asset = AVURLAsset(url: url,options: options) proxy = ReverseProxyResourceLoader() proxy?.cookie = "exampleCookie" // Set resource loader delegate to moniter the chunks asset.resourceLoader.setDelegate(proxy, queue: DispatchQueue.global()) // Load asset keys asynchronously (e.g., "playable") let keys = ["playable"] // Initialize the AVPlayer with the URL let playerItem = AVPlayerItem(asset: asset) self.player = AVPlayer(playerItem: playerItem) playerItem.addObserver(self, forKeyPath: "status", options: [.new, .initial], context: nil) // Observe 'error' property (if needed) playerItem.addObserver(self, forKeyPath: "error", options: [.new], context: nil) let contentKeySessionDelegate = ContentKeyDelegate() // Initialize AVContentKeySession let contentKeySession = AVContentKeySession(keySystem: .clearKey) self.contentKeySession = contentKeySession contentKeySession.setDelegate(contentKeySessionDelegate, queue: DispatchQueue.main) // Associate the asset with the content key session contentKeySession.addContentKeyRecipient(asset) // Create a layer for the AVPlayer and add it to the view playerLayer = AVPlayerLayer(player: player) playerLayer?.frame = view.bounds playerLayer?.videoGravity = .resizeAspect if let playerLayer = playerLayer { view.layer.addSublayer(playerLayer) } NotificationCenter.default.addObserver( self, selector: #selector(playerDidFinishPlaying), name: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem ) // Start playback player?.play() } // Update cookie when ever needed func updateCookie() { proxy?.cookie = "update exampleCookie" } @objc private func playerDidFinishPlaying(notification: Notification) { print("Playback finished!") // Optionally, handle end-of-playback actions here } // // ReverseProxyResourceLoader.swift // HLSDemo // // Created by Gajje.Venkatarao on 12/12/24. // import Foundation import AVKit import AVFoundation class ReverseProxyResourceLoader: NSObject, AVAssetResourceLoaderDelegate { var cookie = "" func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool { resourceLoader.preloadsEligibleContentKeys = true guard let interceptedURL = loadingRequest.request.url else { loadingRequest.finishLoading(with: NSError(domain: "ReverseProxy", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])) return false } if interceptedURL.scheme == "skd" { print("Token updated Cookie:", interceptedURL ) return false } var components = URLComponents(url: interceptedURL, resolvingAgainstBaseURL: false) components?.scheme = "https" // Replace with the original scheme guard let originalURL = components?.url else { loadingRequest.finishLoading(with: NSError(domain: "ReverseProxy", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to map URL"])) loadingRequest.finishLoading() return false } var request = URLRequest(url: originalURL) request.httpMethod = "GET" if let storeCoockie = HTTPCookie(properties: [ .name: "dazn-token", .value: cookie, .domain: originalURL.host ?? "", .path: "/", .discard: true ]){ HTTPCookieStorage.shared.setCookie(storeCoockie) } let headers = loadingRequest.request.allHTTPHeaderFields ?? [:] for (key, value) in headers { request.addValue(value, forHTTPHeaderField: key) } request.addValue(cookie, forHTTPHeaderField: "Cookie") URLSession.shared.configuration.httpShouldSetCookies = true request.httpShouldHandleCookies = true let task = (URLSession.shared.dataTask(with: originalURL) { data, response, error in if let error = error { print("Error Received:", error) loadingRequest.finishLoading(with: error) return } print(originalURL) guard let data = data , let url = response?.url else { loadingRequest.finishLoading(with: NSError(domain: "ReverseProxy", code: -1, userInfo: [NSLocalizedDescriptionKey: "No data received"])) return } loadingRequest.dataRequest?.respond(with: data) loadingRequest.finishLoading() } as URLSessionDataTask) task.resume() return true } } Example project
Replies
0
Boosts
0
Views
834
Activity
Dec ’24
Lightweight RTSP lib on iOS
idk why there isn't built in lib for watch RTSP stream on iOS of apple framework list, even though rtsp is popular. Can i built my own with swift,? have any tutorial for this purpose, i did try many framework like VLCMobileKit,.. it work but I can't understand why it so many enomous files and account for 400mb to 1.7gb for installed pod and have so many bug i cannot fix when usage (so hard to maintain). Can you suggest for me how to built my own with swift. As my knowledge our camera only support for RTSP so I'm not using HTTP Live Stream, it is true? can I use HTTP Live Streaming for this purpose.
Replies
0
Boosts
0
Views
887
Activity
Dec ’21
updateConfiguration no work sometimes
I'm using screenCaptureKit for winodow capture. I build a filter like follow code, (I'm not usng independent window filter, because sometime I need capture multi windows in the same time) filter = [[SCContentFilter alloc] initWithDisplay:displayID includingWindows:includingWindows]; At begining, the capture works OK. When the target window's size or position changed, my code monitored this change and called updateConfiguration like below , I got completionHandler without error. [streamConfiguration setSourceRect:newRect]; [streamConfiguration setWidth:newWidth]; [streamConfiguration setHeight:newHeight]; [scStream updateConfiguration:streamConfiguration completionHandler:^(NSError *_Nullable error) { if (error) { // some error log } else { // update done } }]; But sometimes, it still output frame with old size, and the rect is still the old. And int some other cases, it works fine..... Is there any special work before call updateConfiguration to make it work ?
Replies
0
Boosts
0
Views
658
Activity
Aug ’24
Playing FairPlay encrypted content works fine on ios17 but won't play on ios26
For devices that are still on ios17, playing Fairplay encrypted content still works fine. For devices that I've upgraded to ios26 playing the same content in the same app no longer works. I can advance and see the stream frames by tapping +10 scrubbing so I know that the content is being decrypted but tapping the play button of AVPlayer for an AVPlayerItem now does nothing in ios26. Is this a breaking change or is there a stricter requirement that I now have to implement?
Replies
0
Boosts
0
Views
370
Activity
Oct ’25
How to retrieve the playback state
Per FP Streaming programming guide, The SPC includes a specific TLLV to provide the state of the media content playback. And total value length of this is 16 in decimals. Here i'm trying to retrieve the Playback State. which is of 20-23 ByteRange. byte[] mediaPlaybackStateBlock = getBlock(MEDIA_PLAYBACK_STATE).getValueData(); playbackState = Arrays.copyOfRange(mediaPlaybackStateBlock, 20, 24); I'm endup in issue - arraycopy: length -4 is negative. I'm bit confused on how to retrieve the playback state from 20-23 ByteRange when its length jus 16.. Kindly clarify
Replies
0
Boosts
0
Views
682
Activity
Jan ’24