I'm creating an app that uses AVCaptureSession to pass camera input to AVCaptureMetadataOutput type set [metaout setMetadataObjectTypes:@[AVMetadataObjectTypeFace]] and scan Face.
After updating to OS 26 Beta2 and iOS 26 Beta2, an issue has occurred where the delegate method of AVCaptureMetadataOutputObjectsDelegate is not called on some devices. The following devices are experiencing this issue.
iPad (9th Gen)
iPad air (4th Gen)
iPhone 15
This issue has not occur on any other devices I have.
I tried running the AVFoundation sample code on the Apple Developer site on the above device. The same problem still occurs. https://developer.apple.com/documentation/avfoundation/capture_setup/avcambarcode_detecting_barcodes_and_faces
Are any additional settings required after OS 26 beta and iOS 26 beta? Or is there some problem on the OS side?
AVFoundation
RSS for tagWork with audiovisual assets, control device cameras, process audio, and configure system audio interactions using AVFoundation.
Posts under AVFoundation tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Issue:
In iOS 26 (tested on Developer Beta), AVCaptureMetadataOutputObjectsDelegate no longer receives callbacks when using .face detection.
metadataOutput.metadataObjectTypes = [.face]
Hi, I'm developing an application for macos and ios that has to run DetectHumanBodyPose3DRequest model in real time for retrieving the 3d skeleton from the camera.
I'm experiencing a memory leak every time the model is used (when i comment that line, the memory stays constant). After a minute it uses about 1GB of ram running with mac catalyst.
I attached a minimal project that has this problem
Code
Camera View
import SwiftUI
import Combine
import Vision
struct CameraView: View {
@StateObject private var viewModel = CameraViewModel()
var body: some View {
HStack {
ZStack {
GeometryReader { geometry in
if let image = viewModel.currentFrame {
Image(decorative: image, scale: 1)
.resizable()
.scaledToFill()
.frame(width: geometry.size.width,
height: geometry.size.height)
.clipped()
} else {
ProgressView()
}
}
}
}
}
}
class CameraViewModel: ObservableObject {
@Published var currentFrame: CGImage?
@Published var frameRate: Double = 0
@Published var currentVisionBodyPose: HumanBodyPose3DObservation? // Store current body pose
@Published var currentImageSize: CGSize? // Store current image size
private var cameraManager: CameraManager?
private var humanBodyPose = HumanBodyPose3DDetector()
private var lastClassificationTime = Date()
private var frameCount = 0
private var lastFrameTime = Date()
private let classificationThrottleInterval: TimeInterval = 1.0
private var lastPoseSendTime: Date = .distantPast
init() {
cameraManager = CameraManager()
startPreview()
startClassification()
}
private func startPreview() {
Task {
guard let previewStream = cameraManager?.previewStream else { return }
for await frame in previewStream {
let size = CGSize(width: frame.width, height: frame.height)
Task { @MainActor in
self.currentFrame = frame
self.currentImageSize = size
self.updateFrameRate()
}
}
}
}
private func startClassification() {
Task {
guard let classificationStream = cameraManager?.classificationStream else { return }
for await pixelBuffer in classificationStream {
self.classifyFrame(pixelBuffer: pixelBuffer)
}
}
}
private func classifyFrame(pixelBuffer: CVPixelBuffer) {
humanBodyPose.runHumanBodyPose3DRequestOnImage(pixelBuffer: pixelBuffer) { [weak self] observation in
guard let self = self else { return }
DispatchQueue.main.async {
if let observation = observation {
self.currentVisionBodyPose = observation
print(observation)
} else {
self.currentVisionBodyPose = nil
}
}
}
}
private func updateFrameRate() {
frameCount += 1
let now = Date()
let elapsed = now.timeIntervalSince(lastFrameTime)
if elapsed >= 1.0 {
frameRate = Double(frameCount) / elapsed
frameCount = 0
lastFrameTime = now
}
}
}
HumanBodyPose3DDetector
import Foundation
import Vision
class HumanBodyPose3DDetector: NSObject, ObservableObject {
@Published var humanObservation: HumanBodyPose3DObservation? = nil
private let queue = DispatchQueue(label: "humanbodypose.queue")
private let request = DetectHumanBodyPose3DRequest()
private struct SendablePixelBuffer: @unchecked Sendable {
let buffer: CVPixelBuffer
}
public func runHumanBodyPose3DRequestOnImage(pixelBuffer: CVPixelBuffer, completion: @escaping (HumanBodyPose3DObservation?) -> Void) {
let sendableBuffer = SendablePixelBuffer(buffer: pixelBuffer)
queue.async { [weak self] in
Task { [weak self, sendableBuffer] in
do {
guard let self = self else { return }
let result = try await self.request.perform(on: sendableBuffer.buffer)
//process result
DispatchQueue.main.async {
if result.isEmpty {
completion(nil)
} else {
completion(result[0])
}
}
} catch {
DispatchQueue.main.async {
completion(nil)
}
}
}
}
}
}
Hi everyone,
I’m trying to use AVAssetResourceLoaderDelegate to handle a live radio stream (e.g. Icecast/HTTP stream). My goal is to have access to the last 30 seconds of audio data during playback, so I can analyze it for specific audio patterns in near-real-time.
I’ve implemented a custom resource loader that works fine for podcasts and static files, where the file size and content length are known. However, for infinite live streams, my current implementation stops receiving new loading requests after the first one is served. As a result, the playback either stalls or fails to continue.
Has anyone successfully used AVAssetResourceLoaderDelegate with a continuous radio stream? Or maybe you can suggest betterapproach for buffering and analyzing live audio?
Any tips, examples, or advice would be appreciated. Thanks!
Hi everyone,
I've encountered a rare and strange crash in my app that I can't consistently reproduce. The crash seems to occur deep within Apple's internal frameworks, and I can't pinpoint which line of my own code is causing it. Here's the crash stack trace:
#44 AXSpeech
SIGSEGV
SEGV_ACCERR
0 CoreFoundation ___CFCheckCFInfoPACSignature + 4
1 CoreFoundation _CFRunLoopSourceSignal + 28
2 Foundation _performQueueDequeue + 492
3 Foundation ___NSThreadPerformPerform + 88
4 CoreFoundation ___CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
5 CoreFoundation ___CFRunLoopDoSource0 + 176
6 CoreFoundation ___CFRunLoopDoSources0 + 340
7 CoreFoundation ___CFRunLoopRun + 828
8 CoreFoundation _CFRunLoopRunSpecific + 608
9 Foundation -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
10 TextToSpeech _TTSCFAttributedStringCreateStringByBracketingAttributeWithString + 776
11 Foundation ___NSThread__start__ + 732
12 libsystem_pthread.dylib __pthread_start + 136
Sometimes, instead of line 10 referencing _TTSCFAttributedStringCreateStringByBracketingAttributeWithString, it shows:
10 TextToSpeech LogWarning(char const*, ...) + 7288
Has anyone experienced a similar issue or know what might be triggering this crash? Any guidance on how to investigate or resolve this would be greatly appreciated. Thank you!
XCode 26 beta 2 is taking more than 20 seconds to start AVCaptureSession when AVCaptureVideoDataOutput and AVCaptureAudioDataOutput are added. The problem occurs only during debugging and is clearly seen with Cinematic Capture sample code by Apple. I am using iPhone 14 Pro running iOS 26 beta 2 for reference.
I'm seeing this error while attempting to compile my VisionOS app under Xcode 26. My existing code looks like:
let (naturalSize, formatDescriptions, mediaCharacteristics) = try? await videoTrack.load(.naturalSize, .formatDescriptions, .mediaCharacteristics)
This is now giving a compiler error: Type of expression is ambiguous without a type annotation
I don't see that anything that was changed or deprecated in the latest version. Also loading the properties individually seems to work fine i.e.:
let naturalSize = try? await videoTrack.load(.naturalSize)
let formatDescriptions = try? await videoTrack.load(.formatDescriptions)
let mediaCharacteristics = try? await videoTrack.load(.mediaCharacteristics)
We are facing a strange issue where a small portion of our large userbase can not start the capture session in our app, as it gets interrupted with the following reason:
AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableWithMultipleForegroundApps
Our users are all from iPhones, no one is using an iPad. Just to be sure we have set
session.isMultitaskingCameraAccessEnabled = true
but it does not seem to make any difference.
Another weird interruption we are seeing
I have this build error with Xcode 26 beta 2:
var asset:AVURLAsset?
func loadAsset() {
let assetURL = URL.documentsDirectory
.appendingPathComponent("sample.mov")
asset = AVURLAsset(url: assetURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
/*Error: Type of expression is ambiguous without a type annotation */
if let result = try? await asset?.load(.tracks, .isPlayable, .isComposable) {
}
}
Is there an issue with try? in the new Swift compiler?
Error: Type of expression is ambiguous without a type annotation
We are facing a strange issue where a small portion of our large userbase can not start the capture session in our app, as it gets interrupted with the following reason:
AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableWithMultipleForegroundApps
Our users are all from iPhones, no one is using an iPad. Just to be sure we have set
session.isMultitaskingCameraAccessEnabled = true
but it does not seem to make any difference.
Another weird scenario we are seeing on an even smaller number of users is that the following call:
AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
returns nil. A quick look at our error reports show this happening on iPhone XR, 13 and 14 models. They should all support this device type.
Any help on investigating these issue would be greatly appreciated!
TL;DR How to solve possible racing issue of EXT-X-SESSION-KEY request and encrypted media segment request?
I'm having trouble using custom AVAssetResourceLoaderDelegate with video manifest containing VideoProtectionKey(VPK). My master manifest contains rendition manifest url and VPK url. When not using custom resource delegate, everything works fine.
My custom resource delegate is implemented in way where it first append prefix to scheme of the master manifest url before creating the asset. And during handling master manifest, it puts back original scheme, make the request, modify the scheme for rendition manifest url in the response content by appending the same prefix again, so that rendition manifest request also goes into custom resource loader delegate. Same goes for VPK request. The AES-128 key is stored in memory within custom resource loader delegate object. So far so good.
The VPK is requested before segment request. But the problem comes where the media segment requests happen. The media segment request url from rendition manifest goes into custom resource loader as well and those are encrypted. I can see segment request finish first then the related VPK requests kick in after a few seconds. The previous VPK value is cached in memory so it is not network causing the delay but some mechanism that I'm not aware of causing this.
So could anyone tell me what would be the proper way of handling this situation? The native library is handling it well so I just want to know how. Thanks in advance!
We are seeing logs were on iOS devices we see some keyframes request.
but on safari browser don’t see any request like this. could you please explain what is it.
/d8ceb9244ff889b42b82eb807327531-c27dbcb10e0bbf3cde6c-1/d8ceb9244ff88e9b42b82eb807327531-c27dbcb10e0bbf3cde6c-1/keyframes/hls/.
Hello, I'm trying to subscribe to AVPlayerItem status updates using Combine and it's bridge to Swift Concurrency – .values.
This is my sample code.
struct ContentView: View {
@State var player: AVPlayer?
@State var loaded = false
var body: some View {
VStack {
if let player {
Text("loading status: \(loaded)")
Spacer()
VideoPlayer(player: player)
Button("Load") {
Task {
let item = AVPlayerItem(
url: URL(string: "https://sample-videos.com/video321/mp4/360/big_buck_bunny_360p_5mb.mp4")!
)
player.replaceCurrentItem(with: item)
let publisher = player.publisher(for: \.status)
for await status in publisher.values {
print(status.rawValue)
if status == .readyToPlay {
loaded = true
break
}
}
print("we are out")
}
}
}
else {
Text("No video selected")
}
}
.task {
player = AVPlayer()
}
}
}
After I click on the "load" button it prints out 0 (as the initial status of .unknown) and nothing after – even when the video is fully loaded.
At the same time this works as expected (loading status is set to true):
struct ContentView: View {
@State var player: AVPlayer?
@State var loaded = false
@State var cancellable: AnyCancellable?
var body: some View {
VStack {
if let player {
Text("loading status: \(loaded)")
Spacer()
VideoPlayer(player: player)
Button("Load") {
Task {
let item = AVPlayerItem(
url: URL(string: "https://sample-videos.com/video321/mp4/360/big_buck_bunny_360p_5mb.mp4")!
)
player.replaceCurrentItem(with: item)
let stream = AsyncStream { continuation in
cancellable = item.publisher(for: \.status)
.sink {
if $0 == .readyToPlay {
continuation.yield($0)
continuation.finish()
}
}
}
for await _ in stream {
loaded = true
cancellable?.cancel()
cancellable = nil
break
}
}
}
}
else {
Text("No video selected")
}
}
.task {
player = AVPlayer()
}
}
}
Is this a bug or something?
I'm seeking to a specific sync frame in a video file (HEVC, recorded on iPad). When I feed the buffers from that sync frame on to VTDecompressionSession it consistently drops the 2.,3.,4. buffer with a kVTVideoDecoderReferenceMissingErr (or no error but no buffer on the simulator). If I feed all the buffers from the penultimate sync frame prior to the desired frame the buffers come out fine but that would just create a massive overhead to always do it. Tried multiple OS versions, devices etc. Seems a consistent problem.
Here's a sample project with the offending video (disregard memory handling etc):
https://github.com/marcuseckert/vtSample
I've filed a radar FB18228296 but would appreciate any feedback on circumventing or at least detecting this behavior prior to decoding.
I developed a driverkit extension based on overriding-the-default-usb-video-class-extension, but the link didn’t give the details of realization. I asked DTS who gave two tips:
1, Do you also have a CMIO extension to load in place of the default overriding-the-default-usb-video-class-extension
2, Your DriverKit extension’s info.plist is also missing the CameraAssistantBundleID.
I want to know why a driverkit extension needs a CMIO extension, what’s the data and control flow?
I am wondering if new AVCam sample code was tested before release. It hangs on startup on iPhone 14 pro running iOS 26 beta with the following logs on console:
<<<< FigAudioSession(AV) >>>> audioSessionAVAudioSession_CopyMXSessionProperty signalled err=-19224 (kFigAudioSessionError_UnsupportedOperation) (getMXSessionProperty unsupported) at FigAudioSession_AVAudioSession.m:606
<<<< FigAudioSession(AV) >>>> audioSessionAVAudioSession_CopyMXSessionProperty signalled err=-19224 (kFigAudioSessionError_UnsupportedOperation) (getMXSessionProperty unsupported) at FigAudioSession_AVAudioSession.m:606
App is being debugged, do not track this hang
Hang detected: 8.04s (debugger attached, not reporting)```
I’m building a SwiftUI app whose primary job is to play audio. I manage all of the Now-Playing metadata and Command center manually via the available shared instances:
MPRemoteCommandCenter.shared()
MPNowPlayingInfoCenter.default().nowPlayingInfo
In certain parts of the app I also need to display videos, but as soon as I attach another AVPlayer, it automatically pushes its own metadata into the Control Center and overwrites my audio info.
What I need: a way to show video inline without ever having that video player update the system’s Now-Playing info (or Control Center).
In my app, I start by configuring the shared audio session
do {
try AVAudioSession.sharedInstance().setCategory(.playback,
mode: .default,
options: [
.allowAirPlay,
.allowBluetoothA2DP
])
try AVAudioSession.sharedInstance().setActive(true)
} catch {
NSLog("%@", "**** Failed to set up AVAudioSession \(error.localizedDescription)")
}
and then set the MPRemoteCommandCenter commands and MPNowPlayingInfoCenter nowPlayingInfo like mentioned above.
All this works without any issues as long as I only have one AVPlayer in my app. But when I add other AVPlayers to display some videos (and keep the main AVPlayer for the sound) they push undesired updates to MPNowPlayingInfoCenter:
struct VideoCardView: View {
@State private var player: AVPlayer
let videoName: String
init(player: AVPlayer = AVPlayer(), videoName: String) {
self.player = player
self.videoName = videoName
guard let path = Bundle.main.path(forResource: videoName, ofType: nil) else { return }
let url = URL(fileURLWithPath: path)
let item = AVPlayerItem(url: url)
self.player.replaceCurrentItem(with: item)
}
var body: some View {
VideoPlayer(player: player)
.aspectRatio(contentMode: .fill)
.onAppear {
player.isMuted = true
player.allowsExternalPlayback = false
player.actionAtItemEnd = .none
player.play()
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
MPNowPlayingInfoCenter.default().playbackState = .stopped
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime,
object: player.currentItem,
queue: .main) { notification in
guard let finishedItem = notification.object as? AVPlayerItem,
finishedItem === player.currentItem else { return }
player.seek(to: .zero)
player.play()
}
}
.onDisappear {
player.pause()
}
}
}
Which is why I tried adding:
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
MPNowPlayingInfoCenter.default().playbackState = .stopped // or .interrupted, .unknown
But that didn't work.
I also tried making a wrapper around the AVPlayerViewController in order to set updatesNowPlayingInfoCenter to false, but that didn’t work either:
struct CustomAVPlayerView: UIViewControllerRepresentable {
let player: AVPlayer
func makeUIViewController(context: Context) -> AVPlayerViewController {
let vc = AVPlayerViewController()
vc.player = player
vc.updatesNowPlayingInfoCenter = false
vc.showsPlaybackControls = false
return vc
}
func updateUIViewController(_ controller: AVPlayerViewController, context: Context) {
controller.player = player
}
}
Hence any help on how to embed video in SwiftUI without its AVPlayer touching MPNowPlayingInfoCenter would be greatly appreciated.
All this was tested on an actual device with iOS 18.4.1, and built with Xcode 16.2 on macOS 15.5
In the latest production release of our iOS app (deployed via the App Store), we’ve observed a significant increase in AVCaptureSessionWasInterrupted notifications where the interruption reason has a rawValue of 4. The session does not automatically recover, even after returning from background or deleting/reinstalling the app. An employee ran into this and was able to get a recording. We see the below error when attempting to take photos.
"Error Domain=AVFoundationErrorDomain Code=-11803 \"Cannot Record\" UserInfo={AVErrorRecordingFailureDomainKey=3, NSLocalizedDescription=Cannot Record, NSLocalizedRecoverySuggestion=Try recording again.}",
}
This interruption causes the camera preview to remain black, and any attempt to capture an image results in a failure with the following error:
Some questions from our team:
What common system conditions or foreground app behaviors can cause .videoDeviceNotAvailableWithMultipleForegroundApps (reason 4) to become persistent? Our teams under is under the impression the interruption reason 4 is mostly associated with iPad and PiP, but neither of these are true in the logs we see.
Is manual recovery of the session required?
Is there a recommended strategy to detect that the session is unrecoverable and gracefully notify the user or rebuild the session?
Is there an instrument(s) in XCode you would recommend when trying to evaluate the increase in reason 4?
Best,
Ben
Among the millions of users of our online product, we have identified through data metrics that the silent audio data capture rate on iPadOS 18.4.1 or 18.5 has increased abnormally. However, we are unable to reproduce the issue. Has anyone encountered a similar issue? The parameters we used are as follows:
AudioSession:
category:AVAudioSessionCategoryPlayAndRecord
mode:AVAudioSessionModeDefault
option:77
preferredSampleRate:48000.000000
preferredIOBufferDuration:0.010000
AudioUnit
format.mFormatID = kAudioFormatLinearPCM;
format.mSampleRate = 48000.0;
format.mChannelsPerFrame = 2;
format.mBitsPerChannel = 16;
format.mFramesPerPacket = 1;
format.mBytesPerFrame = format.mChannelsPerFrame * 16 / 8;
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;
format.mFormatFlags = kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger;
component.componentType = kAudioUnitType_Output;
component.componentSubType = kAudioUnitSubType_RemoteIO;
component.componentManufacturer = kAudioUnitManufacturer_Apple;
component.componentFlags = 0;
component.componentFlagsMask = 0;
Opening this question after discussing the issue in the AVCapture lab, hopefully so we can track down this issue.
We've been noticing some crashes in App Store Connect caused by layoutSublayers being called on a background thread.
After debugging the issue a bit we found that all calls which modified the AVCaptureSession or preview layer were indeed done on the main thread. It would be useful to see what results in AVCaptureVideoPreviewLayer.updateFormatDescription being called.
I've attached the crashlog below.
Crash log.ips - https://developer.apple.com/forums/content/attachment/800b0dba-3477-4c5a-b56c-f4cc393b384f