Dive into the technical aspects of audio on your device, including codecs, format support, and customization options.

Audio Documentation

Posts under Audio subtopic

Post

Replies

Boosts

Views

Activity

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) } }
2
0
899
3w
Video recording goes fine but adding audio fails mysteriously
I'm trying to update an old unity app for a client. The app has been crashing on iOS in a plugin they use called NatCorder. They use it to record video only separately and then re-record it with effects and audio gathered separately. Instead of trying to update the plugin to something else which would be quite the hassle, I noticed the API for the native part of the plugin, where the crash occurs, is very simple, especially if you don't try to support everything the plugin does and the app does not use. So I tried to re-implement that native library using AVFoundation. I got the video recording right, it captures the camera from the iPhone and writes it to a file properly. However, when the app does the second part, where it sends video and audio frames to the plugin, it fails. The app sends all the video frames and then sends all the audio frames. The video frames are eaten fine by AVFoundation but the audio fails at random points with unknown errors. I wonder if I'm trying to use incompatible audio-video formats or if I'm using timestamps wrong or something. Here's my init code. Anything suspicious to you? void* NCCreateMP4Recorder(int width, int height, float framerate, int bitrate, int keyframeInterval, int sampleRate, int channelCount, const char* recordingPath, void (*callback)(void*, void*), void* context) { Recorder* recorder = calloc(1, sizeof(Recorder)); recorder->context = context; recorder->callback = callback; recorder->path = strdup(recordingPath); recorder->width = width; recorder->channelCount = channelCount; recorder->sampleRate = sampleRate; recorder->height = height; NSError *error = nil; NSURL* url = createURLFromArgumentCString(recordingPath); recorder->writer = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeMPEG4 error:&error]; if (recorder->writer == nil) NSLog(@"Failed creating media writer: %@", error); NSDictionary *videoSettings = @{ AVVideoCodecKey: AVVideoCodecTypeH264, AVVideoWidthKey: @(width), AVVideoHeightKey: @(height), AVVideoCompressionPropertiesKey: @{ AVVideoAverageBitRateKey: @(bitrate), AVVideoMaxKeyFrameIntervalKey: @(keyframeInterval), } }; recorder->video = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings]; if (recorder->video == nil) NSLog(@"Failed creating video writer input"); recorder->video.expectsMediaDataInRealTime = true; NSDictionary* videoSource = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, [NSNumber numberWithInt:width], kCVPixelBufferWidthKey, [NSNumber numberWithInt:height], kCVPixelBufferHeightKey, nil]; recorder->videoAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:recorder->video sourcePixelBufferAttributes:videoSource]; if (recorder->videoAdaptor == nil) NSLog(@"Failed creating video adaptor"); if ([recorder->writer canAddInput:recorder->video]) [recorder->writer addInput:recorder->video]; else NSLog(@"Could not add video input to writer"); if (sampleRate > 0 && channelCount > 0) { AudioChannelLayout layout = { .mChannelLayoutTag = channelCount == 1 ? kAudioChannelLayoutTag_Mono : kAudioChannelLayoutTag_Stereo, .mChannelBitmap = 0, .mNumberChannelDescriptions = 0 }; NSDictionary* audioOutputSettings = @{ AVFormatIDKey: @(kAudioFormatMPEG4AAC), AVNumberOfChannelsKey: @(channelCount), AVSampleRateKey: @(sampleRate), AVEncoderBitRateKey: @128000, AVChannelLayoutKey: [NSData dataWithBytes:&layout length:sizeof(layout)] }; recorder->audio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:audioOutputSettings]; if (!recorder->audio) NSLog(@"Failed creating audio adaptor"); recorder->audio.expectsMediaDataInRealTime = true; AudioStreamBasicDescription audioStreamDesc = { .mSampleRate = sampleRate, .mFormatID = kAudioFormatLinearPCM, .mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsFloat, .mBytesPerPacket = channelCount * sizeof(float), .mFramesPerPacket = 1, .mBytesPerFrame = channelCount * sizeof(float), .mChannelsPerFrame = channelCount, .mBitsPerChannel = sizeof(float) * 8, }; OSStatus status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &audioStreamDesc, sizeof(layout), &layout, 0, nil, nil, &recorder->audioDesc); if (status) NSLog(@"Failed creating audio format description: %d", (int)status); if ([recorder->writer canAddInput:recorder->audio]) [recorder->writer addInput:recorder->audio]; else NSLog(@"Could not add audio input to writer"); } if (![recorder->writer startWriting]) NSLog(@"Could not start writing: %@", recorder->writer.error); [recorder->writer startSessionAtSourceTime:kCMTimeZero]; NSLog(@"Recording started to %s", recordingPath); return recorder; }
2
0
147
3w
Processing / tapping an HLS audio stream (or global app output)
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). It doesn't seem like attaching an AVAudioMix configured with with an `audioTapProcessor` has any effect; none of the callbacks except `init` are being invoked. Is this a known limitation? If so, is this documented somewhere?If the above is a limitation, what are my options using some of the other audio APIs? I looked into `AVAudioEngine` as well but it doesn't seem like there's any way I can configure any of the input node types to use an HLS stream. Am I wrong? Are there lower level APIs available to play HLS streams that provide the necessary hooks?Alternatively, is there some generic way to tap into all audio being output by my app regardless of its source?Thanks a lot!
12
0
5.3k
3w
Preserve AirPods Transparency while capturing one AirPod microphone for low latency cross ear audio
I am prototyping an iOS accessibility audio application for people with unilateral hearing loss. The goal is simple. Capture environmental audio using the AirPod on the poor hearing side and route that audio with very low latency into the AirPod on the working hearing side. The core concept is already working on physical AirPods and an iPhone. Our desired signal path is Right AirPod microphone → iPhone audio processing → Left AirPod output The user sets the AirPods microphone in Settings to Always Right AirPod. The app then captures that Bluetooth microphone and routes the signal into the left output channel. Using AVAudioSession and AVAudioEngine we have successfully achieved low latency cross ear audio. The main issue is native AirPods Transparency. When the app activates the AirPods Bluetooth microphone using HFP, the transferred audio continues working correctly, but native Transparency audio on the receiving AirPod effectively disappears. Interestingly, iOS still reports Transparency as enabled in Control Center and AirPods settings. This means the user can hear audio transferred from the poor hearing side, but their working ear loses much of the normal environmental sound that Transparency previously provided. We have tested several configurations. Normal Bluetooth HFP with playAndRecord This provides the best result so far. The AirPods microphone signal is strong. The output route exposes two channels. We can route the microphone signal only to the opposite AirPod. Latency can be reduced enough that conversation feels nearly real time. However, native Transparency on the receiving AirPod effectively stops providing environmental audio. bluetoothHighQualityRecording Microphone quality is noticeably better. However, latency is significantly higher and produces an audible delayed or echo effect during conversation. Transparency has the same general issue. multiRoute with dualRoute This allows the iPhone audio hardware and AirPods to operate simultaneously. It appears to preserve more ambient awareness on the working side. However, the AirPods microphone becomes substantially weaker when used as the secondary Bluetooth HFP input. We measured the incoming AirPods microphone signal at roughly minus 40 dB during normal speech testing. Adding 12 to 18 dB of software gain increases distortion without materially improving intelligibility. farFieldInput with dualRoute We tested the raw AirPods microphone with and without farFieldInput. The microphone levels and practical pickup were very similar. Far field speech processing improved intelligibility somewhat, but did not solve the weak secondary Bluetooth input signal. Our main technical question is Is there a supported AVAudioSession configuration, Core Audio API, AirPods API, or entitlement that allows a third party application to capture an AirPods microphone while preserving the AirPods native Transparency processing on the output AirPod? Ideally we want Right AirPod microphone capture plus native Transparency on the left AirPod plus application generated right to left audio mixed into the left AirPod all operating simultaneously. We do not need access to Apple's Transparency microphone signal itself if native Transparency can simply remain active while our application audio is mixed into the receiving AirPod. If this is not currently possible using public APIs, is this an intentional platform limitation of the AirPods Bluetooth microphone route? We would also appreciate guidance on whether there is another recommended architecture for this accessibility use case. The low latency cross ear routing itself works surprisingly well. Preserving natural environmental audio in the user's working ear while the Bluetooth microphone is active is currently the main technical blocker. Testing has been performed on a physical iPhone running iOS 26.x using Xcode 26.6 and current AirPods hardware, not the Simulator. Thank you for any guidance.
0
0
137
3w
watchOS: Network framework WebSocket loses its path ~35 s in, while URLSession keeps working
Following up on TN3135 and the resolution in https://developer.apple.com/forums/thread/773362 — that thread solved establishing a low-level connection on watchOS (the asynchronous AVAudioSession.activate(options:completionHandler:) instead of the synchronous setActive()). This question is about a connection staying established, which I could not find discussed anywhere. Environment: Apple Watch, watchOS 26.6 (23U67). Audio app, WKBackgroundModes = ["self-care"]. Real device, TestFlight build, not the simulator. What works Opening an NWConnection WebSocket to my own server is reliable — 8 attempts out of 8 reached .ready in 0.28–0.98 s, and an echo frame round-tripped in 27–89 ms. Interestingly, in my measurements it opens under BOTH activation variants: the asynchronous activate(options:completionHandler:) AND the synchronous setActive(true). The two are within ~0.2 s of each other. I mention it only because the thread above concluded the synchronous one is insufficient; on 26.6 I cannot reproduce that difference for establishment. What fails The connection goes quiet after roughly half a minute, and an NWPathMonitor running alongside it shows why: the path transitions to .unsatisfied. Four runs: +34.0 s (cellular) +34.6 s (cellular) +36.0 s (Wi-Fi) +34.3 s (companion link only — availableInterfaces ["other", "other"]) The server sends a heartbeat frame every 5 s and closes the socket on a schedule, so I can tell "the peer closed" from "we stopped receiving". The client receives beats 1–6 (5 s … 30 s) and then nothing; the scheduled close never arrives. What I ruled out Server side. The same client construction run on macOS against the same endpoint receives all 8 heartbeats and the scheduled close at 45.1 s. Both audio-session activation variants — no difference, as above. Network type — cellular, Wi-Fi and companion-link-only all drop at ~35 s. The app being suspended. The app keeps logging densely throughout, and in the last run it held a WKExtendedRuntimeSession (delegate reported extendedRuntimeSessionDidStart) and was actively playing audio through AVAudioEngine from the first second — i.e. the audio-streaming condition TN3135 describes — for the entire window. The path dropped anyway, at +34.3 s. An idle socket. Server traffic arrives every 5 s until the drop. The comparison that puzzles me The same app, on the same watch, the same afternoon, relays the same realtime audio session over plain HTTPS (URLSession) instead — and that runs for 64 s continuously without a stall, including straight through a WatchConnectivity "reachability settled: unreachable" transition. So a high-level URLSession request stream survives a period in which a low-level NWConnection's path is reported unsatisfied. That is consistent with the note in thread 773362 that "on watchOS every session is kinda like a background session, where the actual work is done out of process" — but it leaves me unsure what the intended behaviour is. Questions Is a ~35 s path lifetime the expected behaviour for low-level networking on watchOS, or does it indicate something wrong on my side? Does the TN3135 audio-streaming exception cover only the establishment of a low-level connection, or is it also supposed to keep the path available for the duration of the audio streaming? If it is supposed to persist: is there something beyond an active audio session, flowing audio and a WKExtendedRuntimeSession that an app must do to keep the path alive? If ~35 s is the expected ceiling, is a WebSocket a supported transport for a multi-minute conversational audio session on watchOS at all — or is relaying over URLSession the intended approach despite the guidance to prefer Network framework? Happy to file a bug with a sysdiagnose and a reduced sample project if that is more useful — please say the word and I will attach the numbers above.
4
0
1.1k
3w
Setting appEntityIdentifiers on Now Playing content from a RemoteMediaSessionExtension
I'm using the new RemoteMediaSession API (iOS 27) to surface a remote device's playback (network speakers) on the Lock Screen / Control Center. I'd like to link the presented MusicContent to my App Intents entities so Siri can answer "what's playing?" / "tell me more about this artist," using appEntityIdentifiers. The problem: that property is unavailable in extensions. @available(iOSApplicationExtension, unavailable) extension MediaContentRepresentable { public var appEntityIdentifiers: [EntityIdentifier] { get set } } Result: an extension-hosted remote session seems to have no supported way to attach App Intents entity identifiers to its content. A local MediaSession can set it, but only while the app is running. Questions: Is there a supported way to associate appEntityIdentifiers with RemoteMediaSession content that I'm missing? If not, is this an intentional limitation? I've filed an enhancement request — FB24301827. Any guidance appreciated. Thanks!
0
0
396
Aug ’26
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
456
Aug ’26
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
560
Aug ’26
.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
414
Aug ’26
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
429
Aug ’26
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
393
Aug ’26
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
683
Aug ’26
Native WebRTC remote audio stops after ~1 hour while Safari still plays the same stream
Hello, I am developing BROXMEDIA Intercom, an iOS intercom application for live audiovisual production. The app uses a native Swift audio plugin, Google WebRTC, AVAudioSession, and a Capacitor user interface. The current TestFlight version is 2.0, build 17. Environment: iPhone 16 Pro Max iOS 26.5.2 TestFlight internal build AVAudioSession category: playAndRecord AVAudioSession mode: voiceChat Background audio capability enabled Bidirectional WebRTC audio between a web browser and the native iOS app Observed behavior: A remote web browser publishes WebRTC audio. The native iOS app receives and plays the audio correctly for approximately one hour. Wi-Fi disconnection/reconnection and airplane mode on/off initially recover correctly. After the prolonged session, the native app stops playing the remote audio. Signaling and participant presence remain connected. The remote participant is still shown as speaking. Completely closing and reopening the native app does not recover the remote audio. Safari on the same iPhone, connected to the same room and network, can still hear the same remote transmission. Restarting the remote web publication usually causes the native app to receive audio again. This suggests that the remote publication, network connection, signaling server, and device audio hardware are still operational when the native route fails. We are investigating whether: AVAudioSession or the underlying WebRTC audio unit has stopped rendering; the native RTCPeerConnection retains a stale receiver or audio track; inbound RTP has stopped even though the peer remains connected; an interruption, route change, or media-services reset has not been fully recovered. Our current recovery logic checks the peer connection state and whether a remote audio track object exists. However, we do not yet continuously verify that inbound RTP packets or bytes are increasing for each participant. Questions: Can AVAudioSession or its underlying audio unit stop rendering audio while RTCPeerConnection signaling remains connected? Which AVAudioSession or audio-unit callbacks should be monitored to distinguish an iOS audio-session failure from a WebRTC receiver or inbound-RTP failure? After AVAudioSession.mediaServicesWereResetNotification, should an app recreate the complete WebRTC audio engine, or is reactivating AVAudioSession normally sufficient? Is monitoring inbound RTP progression and audio energy the recommended way to detect a remote audio track that still exists but is no longer delivering usable audio? Are there any known considerations for prolonged bidirectional VoIP-style audio using playAndRecord, voiceChat, and background audio? We can add diagnostic logging and provide a Feedback Assistant report with sysdiagnose if the problem is reproduced again. Thank you.
0
0
379
Aug ’26
SFSpeechRecognizer is unavailable or fails to initialize on iOS 26.4 and 26.5 Simulators
I am testing SFSpeechRecognizer using the en_US locale. When the iPhone Simulator’s system language is set to Japanese, SFSpeechRecognizer.isAvailable returns false for en_US, so speech recognition is unavailable. As far as I have tested, this issue does not occur on iOS Simulator 26.2 or earlier. Is this a Simulator-specific issue, or is it a behavior change that could also occur on physical devices? Has any additional setup become necessary to use speech recognition in Simulator? I then changed the iPhone Simulator’s system language to English. After doing so, SFSpeechRecognizer.isAvailable returned true for en_US. However, starting a recognition task still failed immediately with kLSRErrorDomain Code=300, “Failed to initialize recognizer.” The following error was returned: Error Domain=kLSRErrorDomain Code=300 "Failed to initialize recognizer" UserInfo={ NSLocalizedDescription=Failed to initialize recognizer, NSUnderlyingError={ Error Domain=kLSRErrorDomain Code=300 "Failed to create recognizer from=/Users/<USERNAME>/Library/Developer/CoreSimulator/Devices/<DEVICE-UUID>/data/private/var/MobileAsset/AssetsV2/com_apple_MobileAsset_UAF_Siri_Understanding/purpose_auto/ c079bfa6b8856202dc8cb2135fef3b06229ced6e.asset/AssetData/mini.json" UserInfo={ NSLocalizedDescription=Failed to create recognizer from=/Users/<USERNAME>/Library/Developer/CoreSimulator/Devices/<DEVICE-UUID>/data/private/var/MobileAsset/AssetsV2/com_apple_MobileAsset_UAF_Siri_Understanding/purpose_auto/ c079bfa6b8856202dc8cb2135fef3b06229ced6e.asset/AssetData/mini.json } } } I have not observed either of these issues on iOS Simulator 26.2 or earlier: With the Simulator language set to Japanese, the en_US recognizer does not become unavailable. When SFSpeechRecognizer.isAvailable is true, recognition does not fail with kLSRErrorDomain Code=300. Environment Xcode: 26.6 (17F113) iOS Simulator 26.5 (23F77), iPhone 17 (A3258J/A) iOS Simulator 26.4 (23E244), iPhone 17 (A3258J/A)
0
1
936
Aug ’26
VPIO Audio Ducking
Hey y'all, I'm new here and in the process of building some audio software. I'm hitting a roadblock trying to incorporate VPIO into audio playback states without it ducking what's currently playing in my DAW. I have a few questions: Can VPIO other-audio ducking be completely disabled on macOS, beyond fixed/minimum? Minimum is not enough for professional audio environments. Is attenuation of an unrelated application routed through a different Core Audio output device expected? Is split-device VPIO—built-in microphone input with Apollo/Universal Audio output—supported? Why can AVAudioEngine.start() succeed while the engine remains stopped and immediately emits a configuration-change notification? Thanks for any insight into this!
0
0
822
Jul ’26
AVRoutePickerView's presented route list is automatically dismissed when CXProvider reports the call as connected (`reportOutgoingCall(with:connectedAt:)`)
Hi, I want my user to be able to change their audio output device while calling someone, even before the call is established. But I've run into an issue combining CallKit and AVRoutePickerView. On iOS 26 (Xcode 26.5, tested on iPhone 13 Mini): when my AVRoutePickerView's route list is presented while my call is still connecting (not yet established), the presented list is automatically dismissed the moment the app reports the call as connected via CXProvider.reportOutgoingCall(with:connectedAt:). That doesn't seem natural to me — it should stay open, since the user is actively interacting with unrelated system UI at that moment. This happens even when nothing about the AVAudioSession itself changes: no category change, no route change, no didActivate/didDeactivate callback fires around that time. The dismissal is caused by the CallKit "connected" state transition itself, but I don't know why, or whether it's intentional. Steps to reproduce (sample project below): Tap "Start Fake Call". Within 5 seconds, tap the small route picker button and leave its list open. Wait — at t+5s the app reports the call connected via reportOutgoingCall(connectedAt:), and the list closes itself right after. Is this normal? And is there an official, CallKit-sanctioned way to report a call's connected state without this side effect — some way to keep the route picker stable across that transition? The two workarounds I've found both have real downsides: Calling reportOutgoingCall(connectedAt:) at the very start of the call, before the callee has actually answered , but then CallKit no longer reflects the real call state (Recents/duration would include ringing time, and calls that are never answered would still show as "connected"). Disabling audio device selection entirely until the call is established... works, but hurts the user experience, since users may want to switch output before the call connects. Here's the minimal reproduction: import CallKit import SwiftUI struct ContentView: View { @StateObject private var demo = CallKitDemo() var body: some View { VStack(spacing: 24) { Text(demo.statusText) .font(.system(.body, design: .monospaced)) .multilineTextAlignment(.center) Button("Start Fake Call") { demo.startFakeCall() } .disabled(demo.isCallInProgress) RoutePickerView() .frame(width: 60, height: 60) } .padding() } } private struct RoutePickerView: UIViewRepresentable { func makeUIView(context: Context) -> AVRoutePickerView { let picker = AVRoutePickerView() picker.delegate = context.coordinator return picker } func updateUIView(_ uiView: AVRoutePickerView, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator() } final class Coordinator: NSObject, AVRoutePickerViewDelegate { func routePickerViewWillBeginPresentingRoutes(_ routePickerView: AVRoutePickerView) { print("[REPRO]", Date(), "picker WILL present routes") } func routePickerViewDidEndPresentingRoutes(_ routePickerView: AVRoutePickerView) { print("[REPRO]", Date(), "picker DID end presenting routes <- dismissed here") } } } @MainActor final class CallKitDemo: NSObject, ObservableObject { @Published var statusText = "Idle" @Published var isCallInProgress = false private let provider: CXProvider = { let configuration = CXProviderConfiguration() configuration.supportsVideo = false configuration.maximumCallGroups = 1 configuration.maximumCallsPerCallGroup = 1 configuration.supportedHandleTypes = [.generic] return CXProvider(configuration: configuration) }() private let callController = CXCallController() private var currentCallUUID: UUID? override init() { super.init() provider.setDelegate(self, queue: nil) } func startFakeCall() { let uuid = UUID() currentCallUUID = uuid isCallInProgress = true statusText = "Requesting CXStartCallAction..." let handle = CXHandle(type: .generic, value: "repro-call") let startAction = CXStartCallAction(call: uuid, handle: handle) callController.request(CXTransaction(action: startAction)) { error in if let error { print("[REPRO]", Date(), "CXStartCallAction request failed:", error) } } DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [weak self] in guard let self, currentCallUUID == uuid else { return } print("[REPRO]", Date(), "reportOutgoingCall(connectedAt:)") statusText = "Reported connected at t+5s" provider.reportOutgoingCall(with: uuid, connectedAt: Date()) } DispatchQueue.main.asyncAfter(deadline: .now() + 8) { [weak self] in guard let self, currentCallUUID == uuid else { return } callController.request(CXTransaction(action: CXEndCallAction(call: uuid))) { _ in } currentCallUUID = nil isCallInProgress = false statusText = "Call ended" } } } extension CallKitDemo: CXProviderDelegate { func providerDidReset(_ provider: CXProvider) {} func provider(_ provider: CXProvider, perform action: CXStartCallAction) { action.fulfill() } func provider(_ provider: CXProvider, perform action: CXEndCallAction) { action.fulfill() } func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) { print("[REPRO]", Date(), "didActivate") } func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) { print("[REPRO]", Date(), "didDeactivate") } } Thanks for your help !
1
0
804
Jul ’26
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
2
Boosts
0
Views
899
Activity
3w
Apple Music for DJ App
Hi there, I recently launched a dj app to the mac app store, and was wondering how I could access songs for mixing purposes via Apple Music just like how serato, rekordbox, djay, and other DJ apps do? Thanks, Gunek
Replies
1
Boosts
0
Views
1.6k
Activity
3w
Video recording goes fine but adding audio fails mysteriously
I'm trying to update an old unity app for a client. The app has been crashing on iOS in a plugin they use called NatCorder. They use it to record video only separately and then re-record it with effects and audio gathered separately. Instead of trying to update the plugin to something else which would be quite the hassle, I noticed the API for the native part of the plugin, where the crash occurs, is very simple, especially if you don't try to support everything the plugin does and the app does not use. So I tried to re-implement that native library using AVFoundation. I got the video recording right, it captures the camera from the iPhone and writes it to a file properly. However, when the app does the second part, where it sends video and audio frames to the plugin, it fails. The app sends all the video frames and then sends all the audio frames. The video frames are eaten fine by AVFoundation but the audio fails at random points with unknown errors. I wonder if I'm trying to use incompatible audio-video formats or if I'm using timestamps wrong or something. Here's my init code. Anything suspicious to you? void* NCCreateMP4Recorder(int width, int height, float framerate, int bitrate, int keyframeInterval, int sampleRate, int channelCount, const char* recordingPath, void (*callback)(void*, void*), void* context) { Recorder* recorder = calloc(1, sizeof(Recorder)); recorder->context = context; recorder->callback = callback; recorder->path = strdup(recordingPath); recorder->width = width; recorder->channelCount = channelCount; recorder->sampleRate = sampleRate; recorder->height = height; NSError *error = nil; NSURL* url = createURLFromArgumentCString(recordingPath); recorder->writer = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeMPEG4 error:&error]; if (recorder->writer == nil) NSLog(@"Failed creating media writer: %@", error); NSDictionary *videoSettings = @{ AVVideoCodecKey: AVVideoCodecTypeH264, AVVideoWidthKey: @(width), AVVideoHeightKey: @(height), AVVideoCompressionPropertiesKey: @{ AVVideoAverageBitRateKey: @(bitrate), AVVideoMaxKeyFrameIntervalKey: @(keyframeInterval), } }; recorder->video = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings]; if (recorder->video == nil) NSLog(@"Failed creating video writer input"); recorder->video.expectsMediaDataInRealTime = true; NSDictionary* videoSource = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, [NSNumber numberWithInt:width], kCVPixelBufferWidthKey, [NSNumber numberWithInt:height], kCVPixelBufferHeightKey, nil]; recorder->videoAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:recorder->video sourcePixelBufferAttributes:videoSource]; if (recorder->videoAdaptor == nil) NSLog(@"Failed creating video adaptor"); if ([recorder->writer canAddInput:recorder->video]) [recorder->writer addInput:recorder->video]; else NSLog(@"Could not add video input to writer"); if (sampleRate > 0 && channelCount > 0) { AudioChannelLayout layout = { .mChannelLayoutTag = channelCount == 1 ? kAudioChannelLayoutTag_Mono : kAudioChannelLayoutTag_Stereo, .mChannelBitmap = 0, .mNumberChannelDescriptions = 0 }; NSDictionary* audioOutputSettings = @{ AVFormatIDKey: @(kAudioFormatMPEG4AAC), AVNumberOfChannelsKey: @(channelCount), AVSampleRateKey: @(sampleRate), AVEncoderBitRateKey: @128000, AVChannelLayoutKey: [NSData dataWithBytes:&layout length:sizeof(layout)] }; recorder->audio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:audioOutputSettings]; if (!recorder->audio) NSLog(@"Failed creating audio adaptor"); recorder->audio.expectsMediaDataInRealTime = true; AudioStreamBasicDescription audioStreamDesc = { .mSampleRate = sampleRate, .mFormatID = kAudioFormatLinearPCM, .mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsFloat, .mBytesPerPacket = channelCount * sizeof(float), .mFramesPerPacket = 1, .mBytesPerFrame = channelCount * sizeof(float), .mChannelsPerFrame = channelCount, .mBitsPerChannel = sizeof(float) * 8, }; OSStatus status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &audioStreamDesc, sizeof(layout), &layout, 0, nil, nil, &recorder->audioDesc); if (status) NSLog(@"Failed creating audio format description: %d", (int)status); if ([recorder->writer canAddInput:recorder->audio]) [recorder->writer addInput:recorder->audio]; else NSLog(@"Could not add audio input to writer"); } if (![recorder->writer startWriting]) NSLog(@"Could not start writing: %@", recorder->writer.error); [recorder->writer startSessionAtSourceTime:kCMTimeZero]; NSLog(@"Recording started to %s", recordingPath); return recorder; }
Replies
2
Boosts
0
Views
147
Activity
3w
Processing / tapping an HLS audio stream (or global app output)
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). It doesn't seem like attaching an AVAudioMix configured with with an `audioTapProcessor` has any effect; none of the callbacks except `init` are being invoked. Is this a known limitation? If so, is this documented somewhere?If the above is a limitation, what are my options using some of the other audio APIs? I looked into `AVAudioEngine` as well but it doesn't seem like there's any way I can configure any of the input node types to use an HLS stream. Am I wrong? Are there lower level APIs available to play HLS streams that provide the necessary hooks?Alternatively, is there some generic way to tap into all audio being output by my app regardless of its source?Thanks a lot!
Replies
12
Boosts
0
Views
5.3k
Activity
3w
Preserve AirPods Transparency while capturing one AirPod microphone for low latency cross ear audio
I am prototyping an iOS accessibility audio application for people with unilateral hearing loss. The goal is simple. Capture environmental audio using the AirPod on the poor hearing side and route that audio with very low latency into the AirPod on the working hearing side. The core concept is already working on physical AirPods and an iPhone. Our desired signal path is Right AirPod microphone → iPhone audio processing → Left AirPod output The user sets the AirPods microphone in Settings to Always Right AirPod. The app then captures that Bluetooth microphone and routes the signal into the left output channel. Using AVAudioSession and AVAudioEngine we have successfully achieved low latency cross ear audio. The main issue is native AirPods Transparency. When the app activates the AirPods Bluetooth microphone using HFP, the transferred audio continues working correctly, but native Transparency audio on the receiving AirPod effectively disappears. Interestingly, iOS still reports Transparency as enabled in Control Center and AirPods settings. This means the user can hear audio transferred from the poor hearing side, but their working ear loses much of the normal environmental sound that Transparency previously provided. We have tested several configurations. Normal Bluetooth HFP with playAndRecord This provides the best result so far. The AirPods microphone signal is strong. The output route exposes two channels. We can route the microphone signal only to the opposite AirPod. Latency can be reduced enough that conversation feels nearly real time. However, native Transparency on the receiving AirPod effectively stops providing environmental audio. bluetoothHighQualityRecording Microphone quality is noticeably better. However, latency is significantly higher and produces an audible delayed or echo effect during conversation. Transparency has the same general issue. multiRoute with dualRoute This allows the iPhone audio hardware and AirPods to operate simultaneously. It appears to preserve more ambient awareness on the working side. However, the AirPods microphone becomes substantially weaker when used as the secondary Bluetooth HFP input. We measured the incoming AirPods microphone signal at roughly minus 40 dB during normal speech testing. Adding 12 to 18 dB of software gain increases distortion without materially improving intelligibility. farFieldInput with dualRoute We tested the raw AirPods microphone with and without farFieldInput. The microphone levels and practical pickup were very similar. Far field speech processing improved intelligibility somewhat, but did not solve the weak secondary Bluetooth input signal. Our main technical question is Is there a supported AVAudioSession configuration, Core Audio API, AirPods API, or entitlement that allows a third party application to capture an AirPods microphone while preserving the AirPods native Transparency processing on the output AirPod? Ideally we want Right AirPod microphone capture plus native Transparency on the left AirPod plus application generated right to left audio mixed into the left AirPod all operating simultaneously. We do not need access to Apple's Transparency microphone signal itself if native Transparency can simply remain active while our application audio is mixed into the receiving AirPod. If this is not currently possible using public APIs, is this an intentional platform limitation of the AirPods Bluetooth microphone route? We would also appreciate guidance on whether there is another recommended architecture for this accessibility use case. The low latency cross ear routing itself works surprisingly well. Preserving natural environmental audio in the user's working ear while the Bluetooth microphone is active is currently the main technical blocker. Testing has been performed on a physical iPhone running iOS 26.x using Xcode 26.6 and current AirPods hardware, not the Simulator. Thank you for any guidance.
Replies
0
Boosts
0
Views
137
Activity
3w
watchOS: Network framework WebSocket loses its path ~35 s in, while URLSession keeps working
Following up on TN3135 and the resolution in https://developer.apple.com/forums/thread/773362 — that thread solved establishing a low-level connection on watchOS (the asynchronous AVAudioSession.activate(options:completionHandler:) instead of the synchronous setActive()). This question is about a connection staying established, which I could not find discussed anywhere. Environment: Apple Watch, watchOS 26.6 (23U67). Audio app, WKBackgroundModes = ["self-care"]. Real device, TestFlight build, not the simulator. What works Opening an NWConnection WebSocket to my own server is reliable — 8 attempts out of 8 reached .ready in 0.28–0.98 s, and an echo frame round-tripped in 27–89 ms. Interestingly, in my measurements it opens under BOTH activation variants: the asynchronous activate(options:completionHandler:) AND the synchronous setActive(true). The two are within ~0.2 s of each other. I mention it only because the thread above concluded the synchronous one is insufficient; on 26.6 I cannot reproduce that difference for establishment. What fails The connection goes quiet after roughly half a minute, and an NWPathMonitor running alongside it shows why: the path transitions to .unsatisfied. Four runs: +34.0 s (cellular) +34.6 s (cellular) +36.0 s (Wi-Fi) +34.3 s (companion link only — availableInterfaces ["other", "other"]) The server sends a heartbeat frame every 5 s and closes the socket on a schedule, so I can tell "the peer closed" from "we stopped receiving". The client receives beats 1–6 (5 s … 30 s) and then nothing; the scheduled close never arrives. What I ruled out Server side. The same client construction run on macOS against the same endpoint receives all 8 heartbeats and the scheduled close at 45.1 s. Both audio-session activation variants — no difference, as above. Network type — cellular, Wi-Fi and companion-link-only all drop at ~35 s. The app being suspended. The app keeps logging densely throughout, and in the last run it held a WKExtendedRuntimeSession (delegate reported extendedRuntimeSessionDidStart) and was actively playing audio through AVAudioEngine from the first second — i.e. the audio-streaming condition TN3135 describes — for the entire window. The path dropped anyway, at +34.3 s. An idle socket. Server traffic arrives every 5 s until the drop. The comparison that puzzles me The same app, on the same watch, the same afternoon, relays the same realtime audio session over plain HTTPS (URLSession) instead — and that runs for 64 s continuously without a stall, including straight through a WatchConnectivity "reachability settled: unreachable" transition. So a high-level URLSession request stream survives a period in which a low-level NWConnection's path is reported unsatisfied. That is consistent with the note in thread 773362 that "on watchOS every session is kinda like a background session, where the actual work is done out of process" — but it leaves me unsure what the intended behaviour is. Questions Is a ~35 s path lifetime the expected behaviour for low-level networking on watchOS, or does it indicate something wrong on my side? Does the TN3135 audio-streaming exception cover only the establishment of a low-level connection, or is it also supposed to keep the path available for the duration of the audio streaming? If it is supposed to persist: is there something beyond an active audio session, flowing audio and a WKExtendedRuntimeSession that an app must do to keep the path alive? If ~35 s is the expected ceiling, is a WebSocket a supported transport for a multi-minute conversational audio session on watchOS at all — or is relaying over URLSession the intended approach despite the guidance to prefer Network framework? Happy to file a bug with a sysdiagnose and a reduced sample project if that is more useful — please say the word and I will attach the numbers above.
Replies
4
Boosts
0
Views
1.1k
Activity
3w
Setting appEntityIdentifiers on Now Playing content from a RemoteMediaSessionExtension
I'm using the new RemoteMediaSession API (iOS 27) to surface a remote device's playback (network speakers) on the Lock Screen / Control Center. I'd like to link the presented MusicContent to my App Intents entities so Siri can answer "what's playing?" / "tell me more about this artist," using appEntityIdentifiers. The problem: that property is unavailable in extensions. @available(iOSApplicationExtension, unavailable) extension MediaContentRepresentable { public var appEntityIdentifiers: [EntityIdentifier] { get set } } Result: an extension-hosted remote session seems to have no supported way to attach App Intents entity identifiers to its content. A local MediaSession can set it, but only while the app is running. Questions: Is there a supported way to associate appEntityIdentifiers with RemoteMediaSession content that I'm missing? If not, is this an intentional limitation? I've filed an enhancement request — FB24301827. Any guidance appreciated. Thanks!
Replies
0
Boosts
0
Views
396
Activity
Aug ’26
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
1
Boosts
0
Views
741
Activity
Aug ’26
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
456
Activity
Aug ’26
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
560
Activity
Aug ’26
.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
414
Activity
Aug ’26
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
429
Activity
Aug ’26
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
393
Activity
Aug ’26
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
683
Activity
Aug ’26
How to hide route button `showsRouteButton = false` in `MPVolumeView` without deprecation warning?
MPVolumeView's showsRouteButton was deprecated (https://developer.apple.com/documentation/mediaplayer/mpvolumeview/showsroutebutton?language=objc). It's not clear how can we now hide this button without deprecation warning. The documentation is lacking. Please advise. Thank you!
Replies
6
Boosts
0
Views
1.1k
Activity
Aug ’26
Native WebRTC remote audio stops after ~1 hour while Safari still plays the same stream
Hello, I am developing BROXMEDIA Intercom, an iOS intercom application for live audiovisual production. The app uses a native Swift audio plugin, Google WebRTC, AVAudioSession, and a Capacitor user interface. The current TestFlight version is 2.0, build 17. Environment: iPhone 16 Pro Max iOS 26.5.2 TestFlight internal build AVAudioSession category: playAndRecord AVAudioSession mode: voiceChat Background audio capability enabled Bidirectional WebRTC audio between a web browser and the native iOS app Observed behavior: A remote web browser publishes WebRTC audio. The native iOS app receives and plays the audio correctly for approximately one hour. Wi-Fi disconnection/reconnection and airplane mode on/off initially recover correctly. After the prolonged session, the native app stops playing the remote audio. Signaling and participant presence remain connected. The remote participant is still shown as speaking. Completely closing and reopening the native app does not recover the remote audio. Safari on the same iPhone, connected to the same room and network, can still hear the same remote transmission. Restarting the remote web publication usually causes the native app to receive audio again. This suggests that the remote publication, network connection, signaling server, and device audio hardware are still operational when the native route fails. We are investigating whether: AVAudioSession or the underlying WebRTC audio unit has stopped rendering; the native RTCPeerConnection retains a stale receiver or audio track; inbound RTP has stopped even though the peer remains connected; an interruption, route change, or media-services reset has not been fully recovered. Our current recovery logic checks the peer connection state and whether a remote audio track object exists. However, we do not yet continuously verify that inbound RTP packets or bytes are increasing for each participant. Questions: Can AVAudioSession or its underlying audio unit stop rendering audio while RTCPeerConnection signaling remains connected? Which AVAudioSession or audio-unit callbacks should be monitored to distinguish an iOS audio-session failure from a WebRTC receiver or inbound-RTP failure? After AVAudioSession.mediaServicesWereResetNotification, should an app recreate the complete WebRTC audio engine, or is reactivating AVAudioSession normally sufficient? Is monitoring inbound RTP progression and audio energy the recommended way to detect a remote audio track that still exists but is no longer delivering usable audio? Are there any known considerations for prolonged bidirectional VoIP-style audio using playAndRecord, voiceChat, and background audio? We can add diagnostic logging and provide a Feedback Assistant report with sysdiagnose if the problem is reproduced again. Thank you.
Replies
0
Boosts
0
Views
379
Activity
Aug ’26
SFSpeechRecognizer is unavailable or fails to initialize on iOS 26.4 and 26.5 Simulators
I am testing SFSpeechRecognizer using the en_US locale. When the iPhone Simulator’s system language is set to Japanese, SFSpeechRecognizer.isAvailable returns false for en_US, so speech recognition is unavailable. As far as I have tested, this issue does not occur on iOS Simulator 26.2 or earlier. Is this a Simulator-specific issue, or is it a behavior change that could also occur on physical devices? Has any additional setup become necessary to use speech recognition in Simulator? I then changed the iPhone Simulator’s system language to English. After doing so, SFSpeechRecognizer.isAvailable returned true for en_US. However, starting a recognition task still failed immediately with kLSRErrorDomain Code=300, “Failed to initialize recognizer.” The following error was returned: Error Domain=kLSRErrorDomain Code=300 "Failed to initialize recognizer" UserInfo={ NSLocalizedDescription=Failed to initialize recognizer, NSUnderlyingError={ Error Domain=kLSRErrorDomain Code=300 "Failed to create recognizer from=/Users/<USERNAME>/Library/Developer/CoreSimulator/Devices/<DEVICE-UUID>/data/private/var/MobileAsset/AssetsV2/com_apple_MobileAsset_UAF_Siri_Understanding/purpose_auto/ c079bfa6b8856202dc8cb2135fef3b06229ced6e.asset/AssetData/mini.json" UserInfo={ NSLocalizedDescription=Failed to create recognizer from=/Users/<USERNAME>/Library/Developer/CoreSimulator/Devices/<DEVICE-UUID>/data/private/var/MobileAsset/AssetsV2/com_apple_MobileAsset_UAF_Siri_Understanding/purpose_auto/ c079bfa6b8856202dc8cb2135fef3b06229ced6e.asset/AssetData/mini.json } } } I have not observed either of these issues on iOS Simulator 26.2 or earlier: With the Simulator language set to Japanese, the en_US recognizer does not become unavailable. When SFSpeechRecognizer.isAvailable is true, recognition does not fail with kLSRErrorDomain Code=300. Environment Xcode: 26.6 (17F113) iOS Simulator 26.5 (23F77), iPhone 17 (A3258J/A) iOS Simulator 26.4 (23E244), iPhone 17 (A3258J/A)
Replies
0
Boosts
1
Views
936
Activity
Aug ’26
Turn my iPhone to silent mode via Code (Swift)
Hi All,I am working on a project to turn my iPhone to silent mode via Code (Swift), Can someone ,plz, help to put on the right direction as I am very new to Xcode and Swift.Regards
Replies
2
Boosts
0
Views
3.1k
Activity
Jul ’26
VPIO Audio Ducking
Hey y'all, I'm new here and in the process of building some audio software. I'm hitting a roadblock trying to incorporate VPIO into audio playback states without it ducking what's currently playing in my DAW. I have a few questions: Can VPIO other-audio ducking be completely disabled on macOS, beyond fixed/minimum? Minimum is not enough for professional audio environments. Is attenuation of an unrelated application routed through a different Core Audio output device expected? Is split-device VPIO—built-in microphone input with Apollo/Universal Audio output—supported? Why can AVAudioEngine.start() succeed while the engine remains stopped and immediately emits a configuration-change notification? Thanks for any insight into this!
Replies
0
Boosts
0
Views
822
Activity
Jul ’26
AVRoutePickerView's presented route list is automatically dismissed when CXProvider reports the call as connected (`reportOutgoingCall(with:connectedAt:)`)
Hi, I want my user to be able to change their audio output device while calling someone, even before the call is established. But I've run into an issue combining CallKit and AVRoutePickerView. On iOS 26 (Xcode 26.5, tested on iPhone 13 Mini): when my AVRoutePickerView's route list is presented while my call is still connecting (not yet established), the presented list is automatically dismissed the moment the app reports the call as connected via CXProvider.reportOutgoingCall(with:connectedAt:). That doesn't seem natural to me — it should stay open, since the user is actively interacting with unrelated system UI at that moment. This happens even when nothing about the AVAudioSession itself changes: no category change, no route change, no didActivate/didDeactivate callback fires around that time. The dismissal is caused by the CallKit "connected" state transition itself, but I don't know why, or whether it's intentional. Steps to reproduce (sample project below): Tap "Start Fake Call". Within 5 seconds, tap the small route picker button and leave its list open. Wait — at t+5s the app reports the call connected via reportOutgoingCall(connectedAt:), and the list closes itself right after. Is this normal? And is there an official, CallKit-sanctioned way to report a call's connected state without this side effect — some way to keep the route picker stable across that transition? The two workarounds I've found both have real downsides: Calling reportOutgoingCall(connectedAt:) at the very start of the call, before the callee has actually answered , but then CallKit no longer reflects the real call state (Recents/duration would include ringing time, and calls that are never answered would still show as "connected"). Disabling audio device selection entirely until the call is established... works, but hurts the user experience, since users may want to switch output before the call connects. Here's the minimal reproduction: import CallKit import SwiftUI struct ContentView: View { @StateObject private var demo = CallKitDemo() var body: some View { VStack(spacing: 24) { Text(demo.statusText) .font(.system(.body, design: .monospaced)) .multilineTextAlignment(.center) Button("Start Fake Call") { demo.startFakeCall() } .disabled(demo.isCallInProgress) RoutePickerView() .frame(width: 60, height: 60) } .padding() } } private struct RoutePickerView: UIViewRepresentable { func makeUIView(context: Context) -> AVRoutePickerView { let picker = AVRoutePickerView() picker.delegate = context.coordinator return picker } func updateUIView(_ uiView: AVRoutePickerView, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator() } final class Coordinator: NSObject, AVRoutePickerViewDelegate { func routePickerViewWillBeginPresentingRoutes(_ routePickerView: AVRoutePickerView) { print("[REPRO]", Date(), "picker WILL present routes") } func routePickerViewDidEndPresentingRoutes(_ routePickerView: AVRoutePickerView) { print("[REPRO]", Date(), "picker DID end presenting routes <- dismissed here") } } } @MainActor final class CallKitDemo: NSObject, ObservableObject { @Published var statusText = "Idle" @Published var isCallInProgress = false private let provider: CXProvider = { let configuration = CXProviderConfiguration() configuration.supportsVideo = false configuration.maximumCallGroups = 1 configuration.maximumCallsPerCallGroup = 1 configuration.supportedHandleTypes = [.generic] return CXProvider(configuration: configuration) }() private let callController = CXCallController() private var currentCallUUID: UUID? override init() { super.init() provider.setDelegate(self, queue: nil) } func startFakeCall() { let uuid = UUID() currentCallUUID = uuid isCallInProgress = true statusText = "Requesting CXStartCallAction..." let handle = CXHandle(type: .generic, value: "repro-call") let startAction = CXStartCallAction(call: uuid, handle: handle) callController.request(CXTransaction(action: startAction)) { error in if let error { print("[REPRO]", Date(), "CXStartCallAction request failed:", error) } } DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [weak self] in guard let self, currentCallUUID == uuid else { return } print("[REPRO]", Date(), "reportOutgoingCall(connectedAt:)") statusText = "Reported connected at t+5s" provider.reportOutgoingCall(with: uuid, connectedAt: Date()) } DispatchQueue.main.asyncAfter(deadline: .now() + 8) { [weak self] in guard let self, currentCallUUID == uuid else { return } callController.request(CXTransaction(action: CXEndCallAction(call: uuid))) { _ in } currentCallUUID = nil isCallInProgress = false statusText = "Call ended" } } } extension CallKitDemo: CXProviderDelegate { func providerDidReset(_ provider: CXProvider) {} func provider(_ provider: CXProvider, perform action: CXStartCallAction) { action.fulfill() } func provider(_ provider: CXProvider, perform action: CXEndCallAction) { action.fulfill() } func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) { print("[REPRO]", Date(), "didActivate") } func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) { print("[REPRO]", Date(), "didDeactivate") } } Thanks for your help !
Replies
1
Boosts
0
Views
804
Activity
Jul ’26