Explore the integration of media technologies within your app. Discuss working with audio, video, camera, and other media functionalities.

All subtopics
Posts under Media Technologies topic

Post

Replies

Boosts

Views

Activity

Breaking change in Apple Music Recently Played API behavior
The Apple Music Recently Played API appears to have changed its behavior on 2026-08-05/2026-08-06. The endpoint no longer reports songs that are saved in a user's library. This impacts music tracking applications that rely on this API to retrieve listening history. Currently, tracks only appear in the Recently Played response when users stream them directly from the Apple Music catalog. If a user plays a song from their personal library, the playback is not reported by the endpoint and cannot be tracked. This is a breaking change that significantly affects existing integrations, but we could not find any announcement in the release notes or updates to the documentation regarding this behavior change. Could you please confirm whether this change is intentional? If so, we would appreciate updated documentation or guidance on how apps should handle tracking playback from a user's library.
5
3
527
2h
iOS 27: ScreenCaptureKit requires UIBackgroundModes 'screen-capture', but App StoiOS 27: ScreenCaptureKit requires UIBackgroundModes 'screen-capture', but App Store Connect rejects that valuere Connect rejects that value
On iOS, ScreenCaptureKit terminates an SCStream when the app is backgrounded unless the app declares UIBackgroundModes: screen-capture. The delegate reports SCStreamError code -3824 (SCStreamError.Code.missingBackgroundMode). Adding screen-capture to UIBackgroundModes - the value Apple's own iOS 27 ScreenCaptureKit sample code declares - makes App Store Connect reject the upload: error: exportArchive Invalid Info.plist value. The Info.plist key UIBackgroundModes contains an invalid value: 'screen-capture'. So the app cannot be distributed at all, not even to TestFlight internal testers. We have ruled out simply keeping the process alive: running a continuous silent AVAudioEngine under the audio background mode keeps the app running but does not prevent -3824, which is consistent with the framework performing an explicit background-mode check rather than the stream dying from process suspension. One observation that may explain why this has gone unnoticed: Apple's sample is installed directly from Xcode and therefore never passes through App Store Connect's upload validation, so a mismatch between the sample's Info.plist and App Store Connect's allowlist would not be visible when testing the sample internally. My question is which of these three describes the actual status of screen-capture for third-party iOS apps: (1) App Store Connect's allowlist has not yet been updated for iOS 27, and this will resolve on its own. (2) screen-capture requires an entitlement or a specially provisioned profile we have not requested. If so, which one, and how is it requested? (3) screen-capture is restricted to Apple's own or system applications and is not available to third-party App Store apps by design. I could not find screen-capture documented on the general UIBackgroundModes page, which is why I cannot tell these apart. Filed as FB24169650. Device: iPhone 16 Pro, iOS 27.0 Built against the iOS 27 SDK, deployment target 17.0.
3
0
325
4h
FairPlay Streaming Credentials Approval — no response after 5 days
Hi, I submitted a FairPlay Streaming credentials approval request 5 days ago (through the "Request FairPlay Streaming credentials approval" form) and haven't received any response yet. Could someone from the Security Engineering team please check the status? Team ID: US7RGQX775 We're an online education platform and use a third-party DRM/video hosting provider (VdoCipher) that already operates a working, tested FairPlay Streaming KSM on our behalf — we just need the certificate to hand over to them. Thanks in advance!
0
0
220
1d
MacOS Music App Returning 404 to Play Next Commands from iTunes Remote app
MacOS Music App No Longer Accepts "Play Next" and "Add to Up Next" from iTunes Remote app. Connect to your library through the iTunes Remote App. Navigate to a song within the iOS iTunes Remote App and press and hold on the song and when the action sheet comes up select "Play Next" or "Add to Up Next". View the MacOS Music App's Playing Next queue to discover that the additions were not made. Thanks for any help you can provide on this. I'd really love to see this working again. I captured network traffic (tcpdump) between the iTunes Remote iOS app and Music.app on macOS 26 (Tahoe). When tapping "Play Next" on a track, the Remote app sends: GET /ctrl-int/1/playqueue-edit?command=add&query='dmap.itemid:27387'&sort=album&mode=3 Music.app responds with HTTP 404 Not Found. "Add to Up Next" sends the same endpoint with mode=0 and also receives 404 Not Found. Other Remote app functions work correctly over the same connection (play/pause, skip), browsing the library, and viewing the queue all return successful responses. Only the queue-add operation returns 404.
0
0
246
1d
Does the TN3135 audio-session networking exception have a defined lifetime? Seeing a ~38.5 s revoke/re-grant cycle
TN3135 describes the exception that lets a watchOS app use low-level networking while it holds an active audio session. I have that working, and the app functions — but the network path is withdrawn and restored on a strikingly regular cycle, and I would like to know whether that is expected behaviour rather than something I am doing wrong. Setup Apple Watch Series 10 (Watch7,9), watchOS 26.5. Reproduced on a Series 6 (Watch6,2). UIBackgroundModes: [audio]; AVAudioSession category .playAndRecord, mode .spokenAudio; activated with the async activate(options:completionHandler:). NWConnection with NWProtocolWebSocket to a WebSocket relay over TLS. The app streams 16 kHz mono PCM continuously while transmitting and holds the socket open otherwise. Symptom NWPathMonitor reports .unsatisfied, then .satisfied about two seconds later, over and over. Measured with the iPhone powered off, so the watch was on its own Wi-Fi: Uptime between drops Outage 36.4 s 2.1 s 36.7 s 1.9 s 36.9 s 2.1 s The regularity is what prompts the question — uptime varies by ±0.3 s and the outage is consistently 2.0 s. That reads as a timeout expiring rather than radio behaviour. What I have ruled out Not the network or the server. A browser client on the same relay, same TLS, same wire protocol, holds a WebSocket indefinitely. Not the interface. Identical cadence over the companion ipsec1 tunnel with the iPhone present, and over the watch's own en0 with the iPhone powered off. Pinning requiredInterfaceType = .wifi while the iPhone is reachable fails outright — the path offers only ipsec1. Not audio-session interruption. I observe interruptionNotification, routeChangeNotification, mediaServicesWereResetNotification and silenceSecondaryAudioHintNotification. None fire at a drop. At the moment the path goes .unsatisfied, the engine is running and the player node is actively playing. Not session idleness. Playing continuous silence for the whole session, rather than only while reconnecting, made no difference — still 36.4 s. The control that surprised me To test whether this affects any long-lived watch socket or only audio-unlocked ones, I built a second app with no AVAudioSession at all, no audio background mode, holding a URLSessionWebSocketTask and kept alive by a WKExtendedRuntimeSession so screen sleep was not a factor. It never connected. NWPathMonitor reported .unsatisfied once and never changed, across a 30 s run, and every request failed with "The Internet connection appears to be offline." I had expected URLSession to be permitted regardless. Questions Does the audio-session networking exception in TN3135 have a defined lifetime, and is a periodic revoke/re-grant cycle expected? If so, is there a supported way to hold it continuously — or is the correct design simply to expect the interruption and reconnect through it? Is it expected that an app with no audio session gets no network path at all on watchOS, including via URLSession, even in the foreground with an extended runtime session?
1
0
65
1d
AVPlayerItemSampleBufferOutput
I am using AVPlayer, but I am unable to retrieve PCM data from .m3u8 streams via the AVPlayerItemSampleBufferOutput API in iOS 27 beta. I have tried both the Objective-C and Swift APIs: the Objective-C delegate methods are not being called, and the Swift methods nextAvailableSampleBuffer() and nextSampleBuffer() are returning no data.
0
0
27
1d
[iOS 27 DB3] Photos taken with third party apps have photographic styles applied
It's unclear if this is a bug or a new feature but I have noticed that my photos starting coming out looking more stylised than expected and worked out that it was because photographic styles were being applied even tho I was taking photos through a third party app. Is there a way to disable this behaviour if it is intended? I've raised a feedback report #FB23632714 Photographic Styles [OFF] Photographic Styles [ON] My settings:
1
0
415
1d
fail to get HLS realtime stream via AVPlayerItemSampleBufferOutputDelegate
Hi, I'm trying to do some realtime audio processing on audio served from an HLS stream (i.e. an AVPlayer created using an M3U HTTP URL). And I find that new APIs(AVPlayerItemSampleBufferOutput) are available in iOS 27.0 to achieve it. However, I failed to get the available data via the AVPlayerItemSampleBufferOutputDelegate. And I found some error in the system log: I create AVPlayerItemSampleBufferOutput and set the delegate after receiving the AVPlayerItemStatusReadyToPlay event. And here's my code: @interface OCAudioSamplebuffer () <AVPlayerItemSampleBufferOutputDelegate> @property (nonatomic, strong) AVPlayerItemSampleBufferOutput *bufferOutput; @property (nonatomic, strong) dispatch_queue_t bufferOutputQueue; @property (nonatomic, strong) AVPlayerItem *playerItem; @end - (void)playItem:(AVPlayerItem *)item { if (@available(iOS 27, *)) { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; if([NSThread mainThread]){ [audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; }else{ dispatch_async(dispatch_get_main_queue(), ^{ [audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; }); } AVPlayerItemSampleBufferOutputAudioConfiguration *cfg = [[AVPlayerItemSampleBufferOutputAudioConfiguration alloc] init]; CMFormatDescriptionRef formatDescription = [self createPCMFormatDescriptionWithSampleRate:44100.0 channels:2 isFloat:YES]; cfg.requestedAudioFormat = formatDescription; if (formatDescription) { NSLog(@"create PCM Format Description success"); CFRelease(formatDescription); } else { NSLog(@"fail to create PCM Format Description"); } self.bufferOutput = [[AVPlayerItemSampleBufferOutput alloc] initWithConfiguration:cfg]; NSLog(@"create buffer success, PCM Format Description%@---,%@", cfg.requestedAudioFormat, formatDescription); self.bufferOutputQueue = dispatch_queue_create("audioSamplebufferQueue", DISPATCH_QUEUE_CONCURRENT); [self.bufferOutput setDelegate:self queue:self.bufferOutputQueue]; [item addOutput:self.bufferOutput]; self.playerItem = item; } else { // Fallback on earlier versions } } Any help. Thank you
1
0
348
2d
.longFormAudio and USB mic input
I am trying to stream audio from a USB input to a set of AirPlay speakers. I can get this to work to a single AirPlay speaker when I use .playAndRecord and don't use .longFormAudio in the AVAudioSession setup but I hear some audio glitches. I believe these glitches to be audio under-run at the speaker due to differences in clock rates, etc. As I understand the API, to get rid of the audio glitches, I need to use .longFormAudio to enable AirPlay2 and get the speaker to deal with tracking the audio sample timing and have the speaker do any re-sampling when the clocks drift. But if I turn on .longFormAudio, the API will not allow me to use .playAndRecord. Is there a way to get AirPlay2 re-timing behaviors and also enable mic input in the same IOS app?
0
0
197
2d
[FairPlay] Attack AVContentKey to CMSampleBuffer results in "NSLocalizedFailureReason=This app is not authorized to play this file"
I implemented an AVContentKeySessionDelegate that after calling processContentKeyRequest succeeds in producing a contentKey in the callback func contentKeySession(_: AVContentKeySession, didProvide _contentKey: AVContentKey) of the AVContentKeyRecipient that manages the decoding of CMSampleBuffers. However, when I store the AVContentKey from the contentKeySession callback and try to attach it to the CMSampleBuffer with AVSampleBufferAttachContentKey, I get the error: Error Domain=AVFoundationErrorDomain Code=-11836 "Cannot Open" UserInfo={NSLocalizedFailureReason=This app is not authorized to play this file., NSLocalizedDescription=Cannot Open, NSUnderlyingError=0x28303a220 {Error Domain=NSOSStatusErrorDomain Code=-12161 "(null)"}} Does anyone have some insight on why this is happening and how to solve it?
2
0
1.6k
2d
flashMode .on overrides locked focus — AF scan runs and refocuses before the strobe
I'm building a fixed-focus camera app (Bayer RAW, manual exposure, focus permanently locked at a known lens position) and need a full-power flash still that keeps that locked focus. On iPhone 17 Pro, iOS 26, any capture with flashMode = .on runs an autofocus-assist scan — visible lens hunt, assist lamp in low light — and the exposure happens at whatever the scan converged on (usually the far background), not my locked position. In low light it reproduces every time; bright-scene behavior varied by configuration (see matrix), and in my current build it hunts in daylight too. This follows https://developer.apple.com/forums/thread/724897 where DTS confirmed locked lens position + flash "is possible" in a test app, but the differentiating configuration was never identified. I've now exhausted every documented lever, with instrumentation, and would like guidance on whether this stage is bypassable at all. Session configuration session.sessionPreset = .photo // Plain wide camera (also reproduced on .builtInLiDARDepthCamera). let camera = AVCaptureDevice.default( .builtInWideAngleCamera, for: .video, position: .back )! session.addInput(try AVCaptureDeviceInput(device: camera)) session.addOutput(photoOutput) photoOutput.maxPhotoQualityPrioritization = .speed photoOutput.isZeroShutterLagEnabled = false photoOutput.isResponsiveCaptureEnabled = true // Pre-allocate flash capture resources up front. photoOutput.setPreparedPhotoSettingsArray( [makeFlashRawSettings()], completionHandler: nil ) Device configuration (before any capture) try camera.lockForConfiguration() camera.isSubjectAreaChangeMonitoringEnabled = false camera.isSmoothAutoFocusEnabled = false camera.autoFocusRangeRestriction = .near camera.automaticallyEnablesLowLightBoostWhenAvailable = false camera.automaticallyAdjustsFaceDrivenAutoFocusEnabled = false camera.isFaceDrivenAutoFocusEnabled = false // true is worse; see matrix camera.automaticallyAdjustsFaceDrivenAutoExposureEnabled = false camera.isFaceDrivenAutoExposureEnabled = false camera.setFocusModeLocked(lensPosition: 0.60) // ~1 m on this device let gains = camera.deviceWhiteBalanceGains( for: .init(temperature: 4000, tint: 0) ) camera.setWhiteBalanceModeLocked(with: gains) camera.setExposureModeCustom( duration: CMTime(value: 1, timescale: 125), iso: 400 ) camera.unlockForConfiguration() Capture func makeFlashRawSettings() -> AVCapturePhotoSettings { let bayer = photoOutput.availableRawPhotoPixelFormatTypes.first { AVCapturePhotoOutput.isBayerRAWPixelFormat($0) }! let settings = AVCapturePhotoSettings(rawPixelFormatType: bayer) settings.flashMode = .on settings.isAutoRedEyeReductionEnabled = false settings.isAutoStillImageStabilizationEnabled = false settings.isAutoVirtualDeviceFusionEnabled = false settings.isAutoContentAwareDistortionCorrectionEnabled = false settings.photoQualityPrioritization = .speed return settings } // Right before the request, exposure flips .custom → .locked (same // duration/ISO), one preview frame presents, then: photoOutput.capturePhoto(with: makeFlashRawSettings(), delegate: self) What I measure (KVO during the capture window) isAdjustingFocus goes true after the request: a scan runs despite focusMode == .locked (assist lamp on in low light). lensPosition moves from the locked 0.60 to a far position and stays there through willCapturePhotoFor — the exposure uses the scan's answer. When isAdjustingFocus falls back to false (before the metering preflash) I issue one setFocusModeLocked(lensPosition: 0.60). The call succeeds, yet the exposure still happens at the far position — something re-asserts the scan's focus before the strobe. With flashMode = .off, locked focus and custom exposure are honored perfectly (my app's normal path). Tried, all reproduced focusMode = .locked + setFocusModeLocked(lensPosition:): scan still runs. Exposure .custom → .locked for the flash window: no change. Plain wide vs LiDAR wide device: no change. Subject-area / smooth AF / face-driven AF+AE / low-light boost all off: scan still runs in low light. isFaceDrivenAutoFocusEnabled = true (steer scan toward faces): worse — scans in daylight too. Red-eye reduction, fusion, distortion correction off: no change. autoFocusRangeRestriction = .near: still converges far. photoQualityPrioritization = .speed everywhere: no change. Prepared photo settings (flash RAW): no change. Re-lock lens mid-scan: fights the scan; worse convergence. Re-lock lens after scan, before strobe: succeeds; exposure still at the scan's position. Torch lit at request time: scans even in bright daylight. The last two items seem diagnostic: the gate is not scene brightness. A torch adding no visible light in daylight still arms the scan, and face-driven AF arms it in bright scenes — the AF-assist stage runs whenever the sequence sees any reason to focus, and a client's .locked focus mode is never treated as that reason being absent. Questions Is the flash AF-assist stage skippable when focusMode == .locked? The earlier thread's DTS reply achieved a locked-focus flash photo — what configuration makes that true on current hardware/iOS? If not skippable: is there a supported way for the final exposure to honor the locked lens position — run the scan but not apply its result? Why does a successful setFocusModeLocked(lensPosition:) issued between scan end and strobe not stick? Is the sequence re-asserting its own focus at exposure time? Are the observed triggers (torch active at request; face-driven AF enabled — each arming the scan regardless of brightness) expected for flashMode = .on? Goal: full-power flash still + fixed focus + manual exposure, which flashMode = .off already delivers minus the flash. Any guidance — including "file a feedback, here's the rdar to duplicate" — appreciated. Happy to attach a focused sample project and sysdiagnose.
0
0
230
3d
Turning AutoFocus off while flash is on.
Hello, I am creating a simple camere app where I want to turn OFF the autofocus (and set the focus within the app) then take a picture with the flash. The only problem is as soon as i set the flash and take a photo, it auto focuses even though i have set the focus mode locked and lens position? Is this even possible? My av capture output settings:     photoOutput.isHighResolutionCaptureEnabled = true     photoOutput.isLivePhotoCaptureEnabled = false;     photoOutput.isDepthDataDeliveryEnabled = false;     photoOutput.isPortraitEffectsMatteDeliveryEnabled = false     photoOutput.isAppleProRAWEnabled = false;     photoOutput.setPreparedPhotoSettingsArray([buildPhotoSettings(flash: flash)]); my AVCapturePhoto Settings     let photoSettings = AVCapturePhotoSettings(rawPixelFormatType: availbleRaw[0]);     photoSettings.isAutoStillImageStabilizationEnabled = false;     photoSettings.flashMode = flash ?.on :.off;     photoSettings.isHighResolutionPhotoEnabled = true;     photoSettings.isAutoRedEyeReductionEnabled = false; my device input settings           //--white balance     let whiteBalanceValues = AVCaptureDevice.WhiteBalanceTemperatureAndTintValues(temperature: settings.whiteBalanceTemp, tint: settings.whiteBalanceTint);     let newWhiteBalance = videoDeviceInput.device.deviceWhiteBalanceGains(for:whiteBalanceValues);     let maxGain = videoDeviceInput.device.maxWhiteBalanceGain           if(newWhiteBalance.redGain > maxGain || newWhiteBalance.greenGain > maxGain || newWhiteBalance.blueGain > maxGain){       videoDeviceInput.device.unlockForConfiguration();       return (false, "WhiteBalance values are invalid (over maximum gain allowed)");     }           videoDeviceInput.device.setWhiteBalanceModeLocked(with: newWhiteBalance);           //--iso and exposure     let exposure = Float64(settings.exposure/1000);     let exposureTime = CMTime(seconds: exposure, preferredTimescale: 1000)     let iso = Float(settings.iso)           if(exposureTime > videoDeviceInput.device.activeFormat.maxExposureDuration || exposureTime < videoDeviceInput.device.activeFormat.minExposureDuration){       videoDeviceInput.device.unlockForConfiguration();       return (false, "Exposure out of bounds");     }           if(iso > videoDeviceInput.device.activeFormat.maxISO || iso < videoDeviceInput.device.activeFormat.minISO){       videoDeviceInput.device.unlockForConfiguration();       return (false, "ISO out of bounds");     }           videoDeviceInput.device.setExposureModeCustom(duration: exposureTime, iso: iso);           //--Lens focus     if(settings.lensPosition < 0 || settings.lensPosition>1){       videoDeviceInput.device.unlockForConfiguration();       return (false, "Lens position out of bounds");     }               if(videoDeviceInput.device.isFocusModeSupported(.locked)){       videoDeviceInput.device.focusMode = .locked;       videoDeviceInput.device.setFocusModeLocked(lensPosition: settings.lensPosition);             }           if #available(iOS 15.4, *) {       if(videoDeviceInput.device.isFaceDrivenAutoFocusEnabled){         videoDeviceInput.device.automaticallyAdjustsFaceDrivenAutoFocusEnabled = false;                 }               if(videoDeviceInput.device.isFaceDrivenAutoExposureEnabled){         videoDeviceInput.device.automaticallyAdjustsFaceDrivenAutoExposureEnabled = false;       }               if(videoDeviceInput.device.isLowLightBoostSupported){         videoDeviceInput.device.automaticallyEnablesLowLightBoostWhenAvailable = false;       }     } else {       // Fallback on earlier versions     }           //--Torch ON     videoDeviceInput.device.torchMode = settings.torch ? AVCaptureDevice.TorchMode.on :AVCaptureDevice.TorchMode.off;           if(settings.torch){       if(settings.torchLevel<0 || settings.torchLevel>1){         return (false, "Flash out of bounds");       }               try? videoDeviceInput.device.setTorchModeOn(level: Float(settings.torchLevel));     }                       //--Finish     videoDeviceInput.device.unlockForConfiguration();
3
0
1.6k
3d
Apple-supported alternative to MusicKit JS authorization for child accounts
I’m developing a dedicated children’s audio player using MusicKit JS. Ideally, a child would have access to their own Apple Music library and listening history while remaining managed through Family Sharing. Apple Developer Support confirmed that MusicKit cannot be authorized for an under-13 Apple Account due to age restrictions. Is there an Apple-supported alternative, such as parent authorization with access to a child’s library through any other SDK/API path?
0
0
226
3d
Why isn’t Audio Output a per-app permission, like Microphone?
iOS already gives users a simple per-app Microphone permission: Settings → Apps → [App] → Microphone: On/Off Why isn’t there an equivalent permission in the other direction? Settings → Apps → [App] → Audio Output: On/Off This would solve a surprisingly common problem: I may deliberately be listening to Spotify, an audiobook or a podcast, then open another app which suddenly produces audio from an advertisement or autoplaying video. That audio may mix with, duck, or even interrupt what I actually chose to listen to. As I understand the current architecture, apps use AVAudioSession to describe how their audio should interact with other audio. But much of that policy is therefore controlled by the application producing the unwanted audio, rather than by the device owner. The simplest solution wouldn’t require a per-app mixer or complicated audio controls. Just one user-controlled permission: Allow Audio Output: On / Off When disabled, iOS would prevent that app from producing audible media output, while audio sessions belonging to other apps would continue normally. Conceptually, this seems very similar to the existing Microphone permission: Microphone: Can this app receive audio from my device? Audio Output: Can this app produce audio on my device? More advanced controls — per-app volume, permission to interrupt other audio, ducking policy, etc. — could potentially come later. But they aren’t necessary to solve the fundamental problem. I’m curious from an AVAudioSession perspective: Is there a technical reason why iOS could not enforce an OS-level per-app Audio Output permission in the same way it already enforces Microphone access? And if there isn’t, would others find this useful?
0
0
244
3d
AVSpeechSynthesizer does not work on "Mac (Designed for iPad)", with some voices
The iOS 26 sample below speaks well on iPhone/iPad devices and the iOS simulator. But it does not speak on "Mac (Designed for iPad)", with a voice downloaded via the macOS settings. Instead it issues this warning : Invalid maui voice identifier com.apple.voice.enhanced.en-US.Samantha How to make an iOS app speak on "Mac (Designed for iPad)", with a downloaded voice ? Note : I use iOS 26.5.2 and macOS 26.5.2. I use voices that can be found in System Settings > Accessibility > Read & Speak > System voice. I have checked that "Samantha (Enhanced)" is the "System voice" in the macOS settings. I have checked that the same issue occurs with other voices and other languages. There is no such issue for a voice that never needs to be downloaded. import AVFAudio import SwiftUI @main struct SampleApp: App { var body: some Scene { WindowGroup { SampleView() } } } struct SampleView: View { private var synthesizer = AVSpeechSynthesizer() var body: some View { Button("Speak", action: speak) } private func speak() { let utterance = AVSpeechUtterance(string: "I speak English.") utterance.voice = AVSpeechSynthesisVoice(language: "en") self.synthesizer.speak(utterance) } }
0
0
305
4d
Supported Core Image workflow for cropping/scaling Apple Log x422 buffers without converting to HLG?
We capture Apple Log video using AVCaptureVideoDataOutput with: AVCaptureDevice.activeColorSpace = .appleLog or .appleLog2 kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange (x422) AVAssetWriter for the final ProRes/HEVC recording We need to bake spatial operations such as a centre crop and optional anamorphic desqueeze into the recorded raster. We want the result to remain Apple Log for subsequent grading; we do not want to display-transform or convert it to HLG. Core Image/Core Graphics does not appear to expose a public Apple Log or Apple Log 2 CGColorSpace. Core Video instead identifies the signal using kCVImageBufferLogTransferFunctionKey. Would this be the supported Core Image approach for spatial-only processing? let image = CIImage( cvPixelBuffer: sourceBuffer, options: [.colorSpace: NSNull()] ) let context = CIContext( mtlDevice: metalDevice, options: [ .workingColorSpace: NSNull(), .outputColorSpace: NSNull(), .cacheIntermediates: false ] ) let outputImage = image .cropped(to: cropRect) .transformed(by: spatialTransform) context.render( outputImage, to: destinationX422Buffer, bounds: outputBounds, colorSpace: nil ) We would then copy the source buffer’s Apple Log colour and Log-transfer attachments to the destination buffer and append it to an AVAssetWriterInputPixelBufferAdaptor. Could an Apple engineer clarify the following? Does CIImage(cvPixelBuffer:) natively interpret kCVImageBufferLogTransferFunctionKey, even though no public Apple Log CGColorSpace exists? When NSNull()/nil is supplied as above, does Core Image leave the Apple Log values unmanaged during crop and affine operations? When rendering x422 to x422, can Core Image preserve the Log signal apart from expected resampling/rounding, or does it internally perform a colour conversion such as YCbCr → RGB → YCbCr? For scaling or anamorphic desqueeze, is Apple’s recommended workflow to: resample the encoded Apple Log values with colour management disabled, or explicitly decode Apple Log to a linear working space, resample, and encode back using a custom Metal implementation? Is copying kCVImageBufferLogTransferFunctionKey and the related colour attachments from source to destination sufficient for AVAssetWriter, assuming the writer settings were obtained from recommendedVideoSettingsForAssetWriter(writingTo:)? Is there ever a supported reason to use HLG as an intermediate for Apple Log processing, or should that be avoided? This this part, we are concerned about preserving the captured Log signal in a recording pipeline, not applying a viewing LUT or displaying Apple Log. Next, we also support optional LUT processing with CIColorCube. Some LUTs are technical Apple Log-to-display transforms, while others expect linear or Rec.709 input. If the image is created with .colorSpace: NSNull(), we understand that the LUT receives unmanaged Apple Log code values and that the LUT itself must perform the required transfer-function and gamut conversion. Does Core Image synthesize an Apple Log-aware input color space from kCVImageBufferLogTransferFunctionKey, or must applications implement Apple Log/Apple Log 2 decoding explicitly before using ordinary Core Image filters? Is there a supported CGColorSpace, ColorSync profile, or Core Image conversion API for this? Additionally, what numeric range does CIColorCube receive when its source is an x422 video-range Apple Log buffer— normalized Log RGB values, or values requiring explicit video-range conversion?
0
0
289
4d
Supported way to re-acquire genlock after follow() detaches mid-session?
Summary. iPhone 17 Pro Max + Blackmagic Camera ProDock, genlock BNC in from a generator confirmed at a true 30.00 fps. follow(_:videoFrameDuration:delegate:) reaches .activeSync in ~2 s. On one unit the lock then holds for 10+ minutes. On a second unit, same binary and same reference, it detaches 6 s to ~4 min after lock: .activeSync → .ready with input.externalSyncDevice == nil, no runtime error and no delegate error. Calling follow() again on the still-running session is rejected with -11800 every time, while unfollowExternalSyncDevice() plus a stopRunning()/startRunning() bounce recovers reliably. I am not looking for a fix. I want to know whether my call sequence is wrong, whether this transition is expected, and how a shipping app should be structured around it. Questions Is re-following a running session supported? Is the unfollow + bounce the intended reset sequence, or is there a lighter-weight way to clear whatever state the -11800 is keyed on? And once detached, is re-acquisition entirely the app's responsibility, or is the system expected to re-calibrate on its own while the reference is present? Is a hard detach a legal outcome for an already-calibrated input? The documentation describes .freeRunSync as the hold-over when a locked input loses sync. Is that hold-over guaranteed, or must an app also handle .activeSync → .ready with a nil externalSyncDevice? Is anything in my call sequence wrong (code in a reply below), and is polling input.externalSyncDevice the right signal to key recovery on, or is there a supported notification for detach? Setup. Video-only AVCaptureSession: one .builtInWideAngleCamera input, one AVCaptureVideoDataOutput. No multi-cam, no depth output, no synchronizer, no audio. Both frame durations set to CMTime(1, 30) before the input is created, never rewritten while a follow is live. Device A (iOS 26.0.1) holds: 601 s and 956 s runs, zero detaches. Device B (26.3.1, then 26.5.2) has 39 drops across 6 logs. The ProDock, cable and generator were swapped between units; the failure followed the phone. Caveat: n=2, and unit and OS build vary together. The detach. No AVCaptureSessionRuntimeError and no delegate error (-11892 has never been observed here, so this is not the documented frame-duration-mismatch path). The session keeps running and delivering frames. Status is .ready, not .unavailable — the ProDock stays enumerated, the reference unchanged. No confirmed drop has passed through .freeRunSync. PTS ground truth, independent of the follow state: while locked, every frame PTS sits exactly on the 1/30 grid, zero drift. At the drop there is exactly one teardown gap, 238–337 ms across 8 runs, after which the clock free-runs at ~30.013 fps (444 ppm) and never returns to the grid. On -11800. It surfaces through AVCaptureSessionRuntimeErrorNotification. The bounce recovers 3/3, with no activeFormat change. Caveat: -11800 is AVErrorUnknown and I see it in unrelated cases too, so I do not assume it is specific to retained follow state. Ruled out. Exposure duration — a run at ≤ 16.67 ms, within the recommendation in the follow() documentation, still drops. Reference drift — zero, by microsecond PTS. Accessory chain — full swap; the failure followed the phone. Another client — Final Cut Camera holds genlock on the fragile unit with the same ProDock and reference. Load and resolution — load changes time-to-drop, not whether it drops; with recording and audio off it still drops, and Device B drops at both 12 MP and 1080p. Code and supporting logs are in replies below; the length limit would not take them inline. Per-frame PTS CSVs, raw status logs, and a minimal Xcode project that still drops are available on request. Prior art read: forums/thread/799739 and thread/804594 — neither covers post-lock detach or re-acquisition.
3
0
720
4d
Fetch tracks from a playlist
If an app allows people to create a playlist and add more songs to that created playlist, it would make sense to guard them from accidentally adding the same song to the playlist more than once. In this code, even though it is successfully receiving the existing playlist from the request, its tracks and entries always show as nil even when there are songs in the playlist. Any suggestions for how to guard against adding duplicates to a playlist? Thank you! var request = MusicLibraryRequest<Playlist>() request.filter(matching: \.name, equalTo: "AppGeneratedPlaylist") let response = try await request.response() if let existingPlaylist = response.items.first { if let tracks = existingPlaylist.entries, tracks.contains(where: { $0.id == song.id }) { print("Song is already in the playlist, so don't add again") return } else { try await MusicLibrary.shared.add(song, to: existingPlaylist) print("Added song to existing playlist: \(existingPlaylist.name)") print("Count of tracks: \(existingPlaylist.tracks?.count)") print("Count of entries: \(existingPlaylist.entries?.count)") print("Current tracks: \(existingPlaylist.tracks?.map(\.id))") print("Current entries: \(existingPlaylist.entries?.map(\.id))") } }
1
0
383
4d
Breaking change in Apple Music Recently Played API behavior
The Apple Music Recently Played API appears to have changed its behavior on 2026-08-05/2026-08-06. The endpoint no longer reports songs that are saved in a user's library. This impacts music tracking applications that rely on this API to retrieve listening history. Currently, tracks only appear in the Recently Played response when users stream them directly from the Apple Music catalog. If a user plays a song from their personal library, the playback is not reported by the endpoint and cannot be tracked. This is a breaking change that significantly affects existing integrations, but we could not find any announcement in the release notes or updates to the documentation regarding this behavior change. Could you please confirm whether this change is intentional? If so, we would appreciate updated documentation or guidance on how apps should handle tracking playback from a user's library.
Replies
5
Boosts
3
Views
527
Activity
2h
iOS 27: ScreenCaptureKit requires UIBackgroundModes 'screen-capture', but App StoiOS 27: ScreenCaptureKit requires UIBackgroundModes 'screen-capture', but App Store Connect rejects that valuere Connect rejects that value
On iOS, ScreenCaptureKit terminates an SCStream when the app is backgrounded unless the app declares UIBackgroundModes: screen-capture. The delegate reports SCStreamError code -3824 (SCStreamError.Code.missingBackgroundMode). Adding screen-capture to UIBackgroundModes - the value Apple's own iOS 27 ScreenCaptureKit sample code declares - makes App Store Connect reject the upload: error: exportArchive Invalid Info.plist value. The Info.plist key UIBackgroundModes contains an invalid value: 'screen-capture'. So the app cannot be distributed at all, not even to TestFlight internal testers. We have ruled out simply keeping the process alive: running a continuous silent AVAudioEngine under the audio background mode keeps the app running but does not prevent -3824, which is consistent with the framework performing an explicit background-mode check rather than the stream dying from process suspension. One observation that may explain why this has gone unnoticed: Apple's sample is installed directly from Xcode and therefore never passes through App Store Connect's upload validation, so a mismatch between the sample's Info.plist and App Store Connect's allowlist would not be visible when testing the sample internally. My question is which of these three describes the actual status of screen-capture for third-party iOS apps: (1) App Store Connect's allowlist has not yet been updated for iOS 27, and this will resolve on its own. (2) screen-capture requires an entitlement or a specially provisioned profile we have not requested. If so, which one, and how is it requested? (3) screen-capture is restricted to Apple's own or system applications and is not available to third-party App Store apps by design. I could not find screen-capture documented on the general UIBackgroundModes page, which is why I cannot tell these apart. Filed as FB24169650. Device: iPhone 16 Pro, iOS 27.0 Built against the iOS 27 SDK, deployment target 17.0.
Replies
3
Boosts
0
Views
325
Activity
4h
kVTCompressionPropertyKey_AverageBitRate seems to be broken in iOS 27 Beta
The set bitrate is not respected when kVTCompressionPropertyKey_AverageBitRate is used. constant and variable bitrates seems to work, only average that is broken. All three modes works in iOS 26.
Replies
5
Boosts
0
Views
2.4k
Activity
17h
FairPlay Streaming Credentials Approval — no response after 5 days
Hi, I submitted a FairPlay Streaming credentials approval request 5 days ago (through the "Request FairPlay Streaming credentials approval" form) and haven't received any response yet. Could someone from the Security Engineering team please check the status? Team ID: US7RGQX775 We're an online education platform and use a third-party DRM/video hosting provider (VdoCipher) that already operates a working, tested FairPlay Streaming KSM on our behalf — we just need the certificate to hand over to them. Thanks in advance!
Replies
0
Boosts
0
Views
220
Activity
1d
MacOS Music App Returning 404 to Play Next Commands from iTunes Remote app
MacOS Music App No Longer Accepts "Play Next" and "Add to Up Next" from iTunes Remote app. Connect to your library through the iTunes Remote App. Navigate to a song within the iOS iTunes Remote App and press and hold on the song and when the action sheet comes up select "Play Next" or "Add to Up Next". View the MacOS Music App's Playing Next queue to discover that the additions were not made. Thanks for any help you can provide on this. I'd really love to see this working again. I captured network traffic (tcpdump) between the iTunes Remote iOS app and Music.app on macOS 26 (Tahoe). When tapping "Play Next" on a track, the Remote app sends: GET /ctrl-int/1/playqueue-edit?command=add&query='dmap.itemid:27387'&sort=album&mode=3 Music.app responds with HTTP 404 Not Found. "Add to Up Next" sends the same endpoint with mode=0 and also receives 404 Not Found. Other Remote app functions work correctly over the same connection (play/pause, skip), browsing the library, and viewing the queue all return successful responses. Only the queue-add operation returns 404.
Replies
0
Boosts
0
Views
246
Activity
1d
Does the TN3135 audio-session networking exception have a defined lifetime? Seeing a ~38.5 s revoke/re-grant cycle
TN3135 describes the exception that lets a watchOS app use low-level networking while it holds an active audio session. I have that working, and the app functions — but the network path is withdrawn and restored on a strikingly regular cycle, and I would like to know whether that is expected behaviour rather than something I am doing wrong. Setup Apple Watch Series 10 (Watch7,9), watchOS 26.5. Reproduced on a Series 6 (Watch6,2). UIBackgroundModes: [audio]; AVAudioSession category .playAndRecord, mode .spokenAudio; activated with the async activate(options:completionHandler:). NWConnection with NWProtocolWebSocket to a WebSocket relay over TLS. The app streams 16 kHz mono PCM continuously while transmitting and holds the socket open otherwise. Symptom NWPathMonitor reports .unsatisfied, then .satisfied about two seconds later, over and over. Measured with the iPhone powered off, so the watch was on its own Wi-Fi: Uptime between drops Outage 36.4 s 2.1 s 36.7 s 1.9 s 36.9 s 2.1 s The regularity is what prompts the question — uptime varies by ±0.3 s and the outage is consistently 2.0 s. That reads as a timeout expiring rather than radio behaviour. What I have ruled out Not the network or the server. A browser client on the same relay, same TLS, same wire protocol, holds a WebSocket indefinitely. Not the interface. Identical cadence over the companion ipsec1 tunnel with the iPhone present, and over the watch's own en0 with the iPhone powered off. Pinning requiredInterfaceType = .wifi while the iPhone is reachable fails outright — the path offers only ipsec1. Not audio-session interruption. I observe interruptionNotification, routeChangeNotification, mediaServicesWereResetNotification and silenceSecondaryAudioHintNotification. None fire at a drop. At the moment the path goes .unsatisfied, the engine is running and the player node is actively playing. Not session idleness. Playing continuous silence for the whole session, rather than only while reconnecting, made no difference — still 36.4 s. The control that surprised me To test whether this affects any long-lived watch socket or only audio-unlocked ones, I built a second app with no AVAudioSession at all, no audio background mode, holding a URLSessionWebSocketTask and kept alive by a WKExtendedRuntimeSession so screen sleep was not a factor. It never connected. NWPathMonitor reported .unsatisfied once and never changed, across a 30 s run, and every request failed with "The Internet connection appears to be offline." I had expected URLSession to be permitted regardless. Questions Does the audio-session networking exception in TN3135 have a defined lifetime, and is a periodic revoke/re-grant cycle expected? If so, is there a supported way to hold it continuously — or is the correct design simply to expect the interruption and reconnect through it? Is it expected that an app with no audio session gets no network path at all on watchOS, including via URLSession, even in the foreground with an extended runtime session?
Replies
1
Boosts
0
Views
65
Activity
1d
AVPlayerItemSampleBufferOutput
I am using AVPlayer, but I am unable to retrieve PCM data from .m3u8 streams via the AVPlayerItemSampleBufferOutput API in iOS 27 beta. I have tried both the Objective-C and Swift APIs: the Objective-C delegate methods are not being called, and the Swift methods nextAvailableSampleBuffer() and nextSampleBuffer() are returning no data.
Replies
0
Boosts
0
Views
27
Activity
1d
[iOS 27 DB3] Photos taken with third party apps have photographic styles applied
It's unclear if this is a bug or a new feature but I have noticed that my photos starting coming out looking more stylised than expected and worked out that it was because photographic styles were being applied even tho I was taking photos through a third party app. Is there a way to disable this behaviour if it is intended? I've raised a feedback report #FB23632714 Photographic Styles [OFF] Photographic Styles [ON] My settings:
Replies
1
Boosts
0
Views
415
Activity
1d
fail to get HLS realtime stream via AVPlayerItemSampleBufferOutputDelegate
Hi, I'm trying to do some realtime audio processing on audio served from an HLS stream (i.e. an AVPlayer created using an M3U HTTP URL). And I find that new APIs(AVPlayerItemSampleBufferOutput) are available in iOS 27.0 to achieve it. However, I failed to get the available data via the AVPlayerItemSampleBufferOutputDelegate. And I found some error in the system log: I create AVPlayerItemSampleBufferOutput and set the delegate after receiving the AVPlayerItemStatusReadyToPlay event. And here's my code: @interface OCAudioSamplebuffer () <AVPlayerItemSampleBufferOutputDelegate> @property (nonatomic, strong) AVPlayerItemSampleBufferOutput *bufferOutput; @property (nonatomic, strong) dispatch_queue_t bufferOutputQueue; @property (nonatomic, strong) AVPlayerItem *playerItem; @end - (void)playItem:(AVPlayerItem *)item { if (@available(iOS 27, *)) { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; if([NSThread mainThread]){ [audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; }else{ dispatch_async(dispatch_get_main_queue(), ^{ [audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; }); } AVPlayerItemSampleBufferOutputAudioConfiguration *cfg = [[AVPlayerItemSampleBufferOutputAudioConfiguration alloc] init]; CMFormatDescriptionRef formatDescription = [self createPCMFormatDescriptionWithSampleRate:44100.0 channels:2 isFloat:YES]; cfg.requestedAudioFormat = formatDescription; if (formatDescription) { NSLog(@"create PCM Format Description success"); CFRelease(formatDescription); } else { NSLog(@"fail to create PCM Format Description"); } self.bufferOutput = [[AVPlayerItemSampleBufferOutput alloc] initWithConfiguration:cfg]; NSLog(@"create buffer success, PCM Format Description%@---,%@", cfg.requestedAudioFormat, formatDescription); self.bufferOutputQueue = dispatch_queue_create("audioSamplebufferQueue", DISPATCH_QUEUE_CONCURRENT); [self.bufferOutput setDelegate:self queue:self.bufferOutputQueue]; [item addOutput:self.bufferOutput]; self.playerItem = item; } else { // Fallback on earlier versions } } Any help. Thank you
Replies
1
Boosts
0
Views
348
Activity
2d
.longFormAudio and USB mic input
I am trying to stream audio from a USB input to a set of AirPlay speakers. I can get this to work to a single AirPlay speaker when I use .playAndRecord and don't use .longFormAudio in the AVAudioSession setup but I hear some audio glitches. I believe these glitches to be audio under-run at the speaker due to differences in clock rates, etc. As I understand the API, to get rid of the audio glitches, I need to use .longFormAudio to enable AirPlay2 and get the speaker to deal with tracking the audio sample timing and have the speaker do any re-sampling when the clocks drift. But if I turn on .longFormAudio, the API will not allow me to use .playAndRecord. Is there a way to get AirPlay2 re-timing behaviors and also enable mic input in the same IOS app?
Replies
0
Boosts
0
Views
197
Activity
2d
Is there any supported API for a third party app to access live audio from a call it isn't itself carrying?
Is there any supported API for a third party app to access live audio from a call it isn't itself carrying?
Replies
0
Boosts
0
Views
46
Activity
2d
[FairPlay] Attack AVContentKey to CMSampleBuffer results in "NSLocalizedFailureReason=This app is not authorized to play this file"
I implemented an AVContentKeySessionDelegate that after calling processContentKeyRequest succeeds in producing a contentKey in the callback func contentKeySession(_: AVContentKeySession, didProvide _contentKey: AVContentKey) of the AVContentKeyRecipient that manages the decoding of CMSampleBuffers. However, when I store the AVContentKey from the contentKeySession callback and try to attach it to the CMSampleBuffer with AVSampleBufferAttachContentKey, I get the error: Error Domain=AVFoundationErrorDomain Code=-11836 "Cannot Open" UserInfo={NSLocalizedFailureReason=This app is not authorized to play this file., NSLocalizedDescription=Cannot Open, NSUnderlyingError=0x28303a220 {Error Domain=NSOSStatusErrorDomain Code=-12161 "(null)"}} Does anyone have some insight on why this is happening and how to solve it?
Replies
2
Boosts
0
Views
1.6k
Activity
2d
flashMode .on overrides locked focus — AF scan runs and refocuses before the strobe
I'm building a fixed-focus camera app (Bayer RAW, manual exposure, focus permanently locked at a known lens position) and need a full-power flash still that keeps that locked focus. On iPhone 17 Pro, iOS 26, any capture with flashMode = .on runs an autofocus-assist scan — visible lens hunt, assist lamp in low light — and the exposure happens at whatever the scan converged on (usually the far background), not my locked position. In low light it reproduces every time; bright-scene behavior varied by configuration (see matrix), and in my current build it hunts in daylight too. This follows https://developer.apple.com/forums/thread/724897 where DTS confirmed locked lens position + flash "is possible" in a test app, but the differentiating configuration was never identified. I've now exhausted every documented lever, with instrumentation, and would like guidance on whether this stage is bypassable at all. Session configuration session.sessionPreset = .photo // Plain wide camera (also reproduced on .builtInLiDARDepthCamera). let camera = AVCaptureDevice.default( .builtInWideAngleCamera, for: .video, position: .back )! session.addInput(try AVCaptureDeviceInput(device: camera)) session.addOutput(photoOutput) photoOutput.maxPhotoQualityPrioritization = .speed photoOutput.isZeroShutterLagEnabled = false photoOutput.isResponsiveCaptureEnabled = true // Pre-allocate flash capture resources up front. photoOutput.setPreparedPhotoSettingsArray( [makeFlashRawSettings()], completionHandler: nil ) Device configuration (before any capture) try camera.lockForConfiguration() camera.isSubjectAreaChangeMonitoringEnabled = false camera.isSmoothAutoFocusEnabled = false camera.autoFocusRangeRestriction = .near camera.automaticallyEnablesLowLightBoostWhenAvailable = false camera.automaticallyAdjustsFaceDrivenAutoFocusEnabled = false camera.isFaceDrivenAutoFocusEnabled = false // true is worse; see matrix camera.automaticallyAdjustsFaceDrivenAutoExposureEnabled = false camera.isFaceDrivenAutoExposureEnabled = false camera.setFocusModeLocked(lensPosition: 0.60) // ~1 m on this device let gains = camera.deviceWhiteBalanceGains( for: .init(temperature: 4000, tint: 0) ) camera.setWhiteBalanceModeLocked(with: gains) camera.setExposureModeCustom( duration: CMTime(value: 1, timescale: 125), iso: 400 ) camera.unlockForConfiguration() Capture func makeFlashRawSettings() -> AVCapturePhotoSettings { let bayer = photoOutput.availableRawPhotoPixelFormatTypes.first { AVCapturePhotoOutput.isBayerRAWPixelFormat($0) }! let settings = AVCapturePhotoSettings(rawPixelFormatType: bayer) settings.flashMode = .on settings.isAutoRedEyeReductionEnabled = false settings.isAutoStillImageStabilizationEnabled = false settings.isAutoVirtualDeviceFusionEnabled = false settings.isAutoContentAwareDistortionCorrectionEnabled = false settings.photoQualityPrioritization = .speed return settings } // Right before the request, exposure flips .custom → .locked (same // duration/ISO), one preview frame presents, then: photoOutput.capturePhoto(with: makeFlashRawSettings(), delegate: self) What I measure (KVO during the capture window) isAdjustingFocus goes true after the request: a scan runs despite focusMode == .locked (assist lamp on in low light). lensPosition moves from the locked 0.60 to a far position and stays there through willCapturePhotoFor — the exposure uses the scan's answer. When isAdjustingFocus falls back to false (before the metering preflash) I issue one setFocusModeLocked(lensPosition: 0.60). The call succeeds, yet the exposure still happens at the far position — something re-asserts the scan's focus before the strobe. With flashMode = .off, locked focus and custom exposure are honored perfectly (my app's normal path). Tried, all reproduced focusMode = .locked + setFocusModeLocked(lensPosition:): scan still runs. Exposure .custom → .locked for the flash window: no change. Plain wide vs LiDAR wide device: no change. Subject-area / smooth AF / face-driven AF+AE / low-light boost all off: scan still runs in low light. isFaceDrivenAutoFocusEnabled = true (steer scan toward faces): worse — scans in daylight too. Red-eye reduction, fusion, distortion correction off: no change. autoFocusRangeRestriction = .near: still converges far. photoQualityPrioritization = .speed everywhere: no change. Prepared photo settings (flash RAW): no change. Re-lock lens mid-scan: fights the scan; worse convergence. Re-lock lens after scan, before strobe: succeeds; exposure still at the scan's position. Torch lit at request time: scans even in bright daylight. The last two items seem diagnostic: the gate is not scene brightness. A torch adding no visible light in daylight still arms the scan, and face-driven AF arms it in bright scenes — the AF-assist stage runs whenever the sequence sees any reason to focus, and a client's .locked focus mode is never treated as that reason being absent. Questions Is the flash AF-assist stage skippable when focusMode == .locked? The earlier thread's DTS reply achieved a locked-focus flash photo — what configuration makes that true on current hardware/iOS? If not skippable: is there a supported way for the final exposure to honor the locked lens position — run the scan but not apply its result? Why does a successful setFocusModeLocked(lensPosition:) issued between scan end and strobe not stick? Is the sequence re-asserting its own focus at exposure time? Are the observed triggers (torch active at request; face-driven AF enabled — each arming the scan regardless of brightness) expected for flashMode = .on? Goal: full-power flash still + fixed focus + manual exposure, which flashMode = .off already delivers minus the flash. Any guidance — including "file a feedback, here's the rdar to duplicate" — appreciated. Happy to attach a focused sample project and sysdiagnose.
Replies
0
Boosts
0
Views
230
Activity
3d
Turning AutoFocus off while flash is on.
Hello, I am creating a simple camere app where I want to turn OFF the autofocus (and set the focus within the app) then take a picture with the flash. The only problem is as soon as i set the flash and take a photo, it auto focuses even though i have set the focus mode locked and lens position? Is this even possible? My av capture output settings:     photoOutput.isHighResolutionCaptureEnabled = true     photoOutput.isLivePhotoCaptureEnabled = false;     photoOutput.isDepthDataDeliveryEnabled = false;     photoOutput.isPortraitEffectsMatteDeliveryEnabled = false     photoOutput.isAppleProRAWEnabled = false;     photoOutput.setPreparedPhotoSettingsArray([buildPhotoSettings(flash: flash)]); my AVCapturePhoto Settings     let photoSettings = AVCapturePhotoSettings(rawPixelFormatType: availbleRaw[0]);     photoSettings.isAutoStillImageStabilizationEnabled = false;     photoSettings.flashMode = flash ?.on :.off;     photoSettings.isHighResolutionPhotoEnabled = true;     photoSettings.isAutoRedEyeReductionEnabled = false; my device input settings           //--white balance     let whiteBalanceValues = AVCaptureDevice.WhiteBalanceTemperatureAndTintValues(temperature: settings.whiteBalanceTemp, tint: settings.whiteBalanceTint);     let newWhiteBalance = videoDeviceInput.device.deviceWhiteBalanceGains(for:whiteBalanceValues);     let maxGain = videoDeviceInput.device.maxWhiteBalanceGain           if(newWhiteBalance.redGain > maxGain || newWhiteBalance.greenGain > maxGain || newWhiteBalance.blueGain > maxGain){       videoDeviceInput.device.unlockForConfiguration();       return (false, "WhiteBalance values are invalid (over maximum gain allowed)");     }           videoDeviceInput.device.setWhiteBalanceModeLocked(with: newWhiteBalance);           //--iso and exposure     let exposure = Float64(settings.exposure/1000);     let exposureTime = CMTime(seconds: exposure, preferredTimescale: 1000)     let iso = Float(settings.iso)           if(exposureTime > videoDeviceInput.device.activeFormat.maxExposureDuration || exposureTime < videoDeviceInput.device.activeFormat.minExposureDuration){       videoDeviceInput.device.unlockForConfiguration();       return (false, "Exposure out of bounds");     }           if(iso > videoDeviceInput.device.activeFormat.maxISO || iso < videoDeviceInput.device.activeFormat.minISO){       videoDeviceInput.device.unlockForConfiguration();       return (false, "ISO out of bounds");     }           videoDeviceInput.device.setExposureModeCustom(duration: exposureTime, iso: iso);           //--Lens focus     if(settings.lensPosition < 0 || settings.lensPosition>1){       videoDeviceInput.device.unlockForConfiguration();       return (false, "Lens position out of bounds");     }               if(videoDeviceInput.device.isFocusModeSupported(.locked)){       videoDeviceInput.device.focusMode = .locked;       videoDeviceInput.device.setFocusModeLocked(lensPosition: settings.lensPosition);             }           if #available(iOS 15.4, *) {       if(videoDeviceInput.device.isFaceDrivenAutoFocusEnabled){         videoDeviceInput.device.automaticallyAdjustsFaceDrivenAutoFocusEnabled = false;                 }               if(videoDeviceInput.device.isFaceDrivenAutoExposureEnabled){         videoDeviceInput.device.automaticallyAdjustsFaceDrivenAutoExposureEnabled = false;       }               if(videoDeviceInput.device.isLowLightBoostSupported){         videoDeviceInput.device.automaticallyEnablesLowLightBoostWhenAvailable = false;       }     } else {       // Fallback on earlier versions     }           //--Torch ON     videoDeviceInput.device.torchMode = settings.torch ? AVCaptureDevice.TorchMode.on :AVCaptureDevice.TorchMode.off;           if(settings.torch){       if(settings.torchLevel<0 || settings.torchLevel>1){         return (false, "Flash out of bounds");       }               try? videoDeviceInput.device.setTorchModeOn(level: Float(settings.torchLevel));     }                       //--Finish     videoDeviceInput.device.unlockForConfiguration();
Replies
3
Boosts
0
Views
1.6k
Activity
3d
Apple-supported alternative to MusicKit JS authorization for child accounts
I’m developing a dedicated children’s audio player using MusicKit JS. Ideally, a child would have access to their own Apple Music library and listening history while remaining managed through Family Sharing. Apple Developer Support confirmed that MusicKit cannot be authorized for an under-13 Apple Account due to age restrictions. Is there an Apple-supported alternative, such as parent authorization with access to a child’s library through any other SDK/API path?
Replies
0
Boosts
0
Views
226
Activity
3d
Why isn’t Audio Output a per-app permission, like Microphone?
iOS already gives users a simple per-app Microphone permission: Settings → Apps → [App] → Microphone: On/Off Why isn’t there an equivalent permission in the other direction? Settings → Apps → [App] → Audio Output: On/Off This would solve a surprisingly common problem: I may deliberately be listening to Spotify, an audiobook or a podcast, then open another app which suddenly produces audio from an advertisement or autoplaying video. That audio may mix with, duck, or even interrupt what I actually chose to listen to. As I understand the current architecture, apps use AVAudioSession to describe how their audio should interact with other audio. But much of that policy is therefore controlled by the application producing the unwanted audio, rather than by the device owner. The simplest solution wouldn’t require a per-app mixer or complicated audio controls. Just one user-controlled permission: Allow Audio Output: On / Off When disabled, iOS would prevent that app from producing audible media output, while audio sessions belonging to other apps would continue normally. Conceptually, this seems very similar to the existing Microphone permission: Microphone: Can this app receive audio from my device? Audio Output: Can this app produce audio on my device? More advanced controls — per-app volume, permission to interrupt other audio, ducking policy, etc. — could potentially come later. But they aren’t necessary to solve the fundamental problem. I’m curious from an AVAudioSession perspective: Is there a technical reason why iOS could not enforce an OS-level per-app Audio Output permission in the same way it already enforces Microphone access? And if there isn’t, would others find this useful?
Replies
0
Boosts
0
Views
244
Activity
3d
AVSpeechSynthesizer does not work on "Mac (Designed for iPad)", with some voices
The iOS 26 sample below speaks well on iPhone/iPad devices and the iOS simulator. But it does not speak on "Mac (Designed for iPad)", with a voice downloaded via the macOS settings. Instead it issues this warning : Invalid maui voice identifier com.apple.voice.enhanced.en-US.Samantha How to make an iOS app speak on "Mac (Designed for iPad)", with a downloaded voice ? Note : I use iOS 26.5.2 and macOS 26.5.2. I use voices that can be found in System Settings > Accessibility > Read & Speak > System voice. I have checked that "Samantha (Enhanced)" is the "System voice" in the macOS settings. I have checked that the same issue occurs with other voices and other languages. There is no such issue for a voice that never needs to be downloaded. import AVFAudio import SwiftUI @main struct SampleApp: App { var body: some Scene { WindowGroup { SampleView() } } } struct SampleView: View { private var synthesizer = AVSpeechSynthesizer() var body: some View { Button("Speak", action: speak) } private func speak() { let utterance = AVSpeechUtterance(string: "I speak English.") utterance.voice = AVSpeechSynthesisVoice(language: "en") self.synthesizer.speak(utterance) } }
Replies
0
Boosts
0
Views
305
Activity
4d
Supported Core Image workflow for cropping/scaling Apple Log x422 buffers without converting to HLG?
We capture Apple Log video using AVCaptureVideoDataOutput with: AVCaptureDevice.activeColorSpace = .appleLog or .appleLog2 kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange (x422) AVAssetWriter for the final ProRes/HEVC recording We need to bake spatial operations such as a centre crop and optional anamorphic desqueeze into the recorded raster. We want the result to remain Apple Log for subsequent grading; we do not want to display-transform or convert it to HLG. Core Image/Core Graphics does not appear to expose a public Apple Log or Apple Log 2 CGColorSpace. Core Video instead identifies the signal using kCVImageBufferLogTransferFunctionKey. Would this be the supported Core Image approach for spatial-only processing? let image = CIImage( cvPixelBuffer: sourceBuffer, options: [.colorSpace: NSNull()] ) let context = CIContext( mtlDevice: metalDevice, options: [ .workingColorSpace: NSNull(), .outputColorSpace: NSNull(), .cacheIntermediates: false ] ) let outputImage = image .cropped(to: cropRect) .transformed(by: spatialTransform) context.render( outputImage, to: destinationX422Buffer, bounds: outputBounds, colorSpace: nil ) We would then copy the source buffer’s Apple Log colour and Log-transfer attachments to the destination buffer and append it to an AVAssetWriterInputPixelBufferAdaptor. Could an Apple engineer clarify the following? Does CIImage(cvPixelBuffer:) natively interpret kCVImageBufferLogTransferFunctionKey, even though no public Apple Log CGColorSpace exists? When NSNull()/nil is supplied as above, does Core Image leave the Apple Log values unmanaged during crop and affine operations? When rendering x422 to x422, can Core Image preserve the Log signal apart from expected resampling/rounding, or does it internally perform a colour conversion such as YCbCr → RGB → YCbCr? For scaling or anamorphic desqueeze, is Apple’s recommended workflow to: resample the encoded Apple Log values with colour management disabled, or explicitly decode Apple Log to a linear working space, resample, and encode back using a custom Metal implementation? Is copying kCVImageBufferLogTransferFunctionKey and the related colour attachments from source to destination sufficient for AVAssetWriter, assuming the writer settings were obtained from recommendedVideoSettingsForAssetWriter(writingTo:)? Is there ever a supported reason to use HLG as an intermediate for Apple Log processing, or should that be avoided? This this part, we are concerned about preserving the captured Log signal in a recording pipeline, not applying a viewing LUT or displaying Apple Log. Next, we also support optional LUT processing with CIColorCube. Some LUTs are technical Apple Log-to-display transforms, while others expect linear or Rec.709 input. If the image is created with .colorSpace: NSNull(), we understand that the LUT receives unmanaged Apple Log code values and that the LUT itself must perform the required transfer-function and gamut conversion. Does Core Image synthesize an Apple Log-aware input color space from kCVImageBufferLogTransferFunctionKey, or must applications implement Apple Log/Apple Log 2 decoding explicitly before using ordinary Core Image filters? Is there a supported CGColorSpace, ColorSync profile, or Core Image conversion API for this? Additionally, what numeric range does CIColorCube receive when its source is an x422 video-range Apple Log buffer— normalized Log RGB values, or values requiring explicit video-range conversion?
Replies
0
Boosts
0
Views
289
Activity
4d
Supported way to re-acquire genlock after follow() detaches mid-session?
Summary. iPhone 17 Pro Max + Blackmagic Camera ProDock, genlock BNC in from a generator confirmed at a true 30.00 fps. follow(_:videoFrameDuration:delegate:) reaches .activeSync in ~2 s. On one unit the lock then holds for 10+ minutes. On a second unit, same binary and same reference, it detaches 6 s to ~4 min after lock: .activeSync → .ready with input.externalSyncDevice == nil, no runtime error and no delegate error. Calling follow() again on the still-running session is rejected with -11800 every time, while unfollowExternalSyncDevice() plus a stopRunning()/startRunning() bounce recovers reliably. I am not looking for a fix. I want to know whether my call sequence is wrong, whether this transition is expected, and how a shipping app should be structured around it. Questions Is re-following a running session supported? Is the unfollow + bounce the intended reset sequence, or is there a lighter-weight way to clear whatever state the -11800 is keyed on? And once detached, is re-acquisition entirely the app's responsibility, or is the system expected to re-calibrate on its own while the reference is present? Is a hard detach a legal outcome for an already-calibrated input? The documentation describes .freeRunSync as the hold-over when a locked input loses sync. Is that hold-over guaranteed, or must an app also handle .activeSync → .ready with a nil externalSyncDevice? Is anything in my call sequence wrong (code in a reply below), and is polling input.externalSyncDevice the right signal to key recovery on, or is there a supported notification for detach? Setup. Video-only AVCaptureSession: one .builtInWideAngleCamera input, one AVCaptureVideoDataOutput. No multi-cam, no depth output, no synchronizer, no audio. Both frame durations set to CMTime(1, 30) before the input is created, never rewritten while a follow is live. Device A (iOS 26.0.1) holds: 601 s and 956 s runs, zero detaches. Device B (26.3.1, then 26.5.2) has 39 drops across 6 logs. The ProDock, cable and generator were swapped between units; the failure followed the phone. Caveat: n=2, and unit and OS build vary together. The detach. No AVCaptureSessionRuntimeError and no delegate error (-11892 has never been observed here, so this is not the documented frame-duration-mismatch path). The session keeps running and delivering frames. Status is .ready, not .unavailable — the ProDock stays enumerated, the reference unchanged. No confirmed drop has passed through .freeRunSync. PTS ground truth, independent of the follow state: while locked, every frame PTS sits exactly on the 1/30 grid, zero drift. At the drop there is exactly one teardown gap, 238–337 ms across 8 runs, after which the clock free-runs at ~30.013 fps (444 ppm) and never returns to the grid. On -11800. It surfaces through AVCaptureSessionRuntimeErrorNotification. The bounce recovers 3/3, with no activeFormat change. Caveat: -11800 is AVErrorUnknown and I see it in unrelated cases too, so I do not assume it is specific to retained follow state. Ruled out. Exposure duration — a run at ≤ 16.67 ms, within the recommendation in the follow() documentation, still drops. Reference drift — zero, by microsecond PTS. Accessory chain — full swap; the failure followed the phone. Another client — Final Cut Camera holds genlock on the fragile unit with the same ProDock and reference. Load and resolution — load changes time-to-drop, not whether it drops; with recording and audio off it still drops, and Device B drops at both 12 MP and 1080p. Code and supporting logs are in replies below; the length limit would not take them inline. Per-frame PTS CSVs, raw status logs, and a minimal Xcode project that still drops are available on request. Prior art read: forums/thread/799739 and thread/804594 — neither covers post-lock detach or re-acquisition.
Replies
3
Boosts
0
Views
720
Activity
4d
Fetch tracks from a playlist
If an app allows people to create a playlist and add more songs to that created playlist, it would make sense to guard them from accidentally adding the same song to the playlist more than once. In this code, even though it is successfully receiving the existing playlist from the request, its tracks and entries always show as nil even when there are songs in the playlist. Any suggestions for how to guard against adding duplicates to a playlist? Thank you! var request = MusicLibraryRequest<Playlist>() request.filter(matching: \.name, equalTo: "AppGeneratedPlaylist") let response = try await request.response() if let existingPlaylist = response.items.first { if let tracks = existingPlaylist.entries, tracks.contains(where: { $0.id == song.id }) { print("Song is already in the playlist, so don't add again") return } else { try await MusicLibrary.shared.add(song, to: existingPlaylist) print("Added song to existing playlist: \(existingPlaylist.name)") print("Count of tracks: \(existingPlaylist.tracks?.count)") print("Count of entries: \(existingPlaylist.entries?.count)") print("Current tracks: \(existingPlaylist.tracks?.map(\.id))") print("Current entries: \(existingPlaylist.entries?.map(\.id))") } }
Replies
1
Boosts
0
Views
383
Activity
4d