I am using Apple's original Lightning Digital AV-adapter (Lightning-to-HDMI dongle) to connect my iPhone to an external display via a HDMI cable.
I need to synchronize rendering with the external display's refresh rate, so I create a new CADisplayLink tied to the external display's UIScreen: UIScreen.screens[externalDisplayIdx].displayLink(withTarget:, selector:).
The callback is being called regularly, but with increasing delay relative to the CADisplayLink.timestamp, so the next time the callback is called, I have less and less time to draw the next frame (see the snippet below).
Assuming 60 FPS, the value of secondsTillDeadline starts at an arbitrary value in the range of approx -0.0001 to 0.0166667, and then it slowly decreases towards zero (and for a brief period it goes into small negative numbers). Once it reaches zero, it flips back to 0.0166667 and continues to decrease again. This cycle repeats indefinitely.
Changing the external display's resolution (UIScreen's mode) or the CADisplayLink's preferredFrameRateRange to a lower FPS does not seem to have any effect on the temporal drifting (even the rate of change seem to be the same).
When I create a new CADisplayLink for the iPhone's main screen, the value of secondsTillDeadline is stable, it does not drift and it is very close to 0.0166667, as expected.
Is this drift caused by the external monitor or by Apple's Lightning-to-HDMI dongle ...or is the problem somewhere else?
Can the drifting be stopped?
func onDisplayLinkUpdate(displayLink: CADisplayLink) {
// Gradually decreases from 0.01667 to -0.0001, then flips back to 0.01667 and continues to decrease
let secondsTillDeadline = displayLink.targetTimestamp - CACurrentMediaTime()
}
Explore the integration of media technologies within your app. Discuss working with audio, video, camera, and other media functionalities.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
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
Hi! I am making an app for Apple Vision pro (VisionOS 2.5) that is scanning the surroundings and recognises all the texts around you. I tried to use the AVCaptureSession library, but when I run the app from xcode on the real AVP device, the camera is not accessible. I enabled the camera access in my Info.plist: NSCameraUsageDescription Used for live text recognition and I checked camera settings in the AVP, there are no restrictions. However I have always a black square with a crossed camera icon displayed instead of the image from the camera.
I tried a couple of different apps from Github using the AVCaptureSession and they all display the black square instead of the picture.
What can be wrong with the camera?
Topic:
Media Technologies
SubTopic:
Photos & Camera
Hi,
I'm a fan of the gallery in vision pro which has video as well as still photography but I'm wondering if Apple has considered adding the projected media tags to heic so that we can go that next step from Spatial photos to Immersive photos. I have a device that can give me 12k x 6k fisheye images in HDR, but it can't do it at a framerate or resolution that's good enough for video, so I want to cut my losses and show off immersive photos instead. Is there something Apple is already working on for APMP stills or should I create my own app that reads metadata inside a HEIC that I infer in a similar way to the demo "ProjectedMediaConversion" is doing for Video. It would be great to have 180VR photos, which could show as Spatial in a gallery view, but going immersive would half-surround you instead of floating in the blurred view. I think that would be a pretty amazing effect.
Topic:
Media Technologies
SubTopic:
Photos & Camera
In the past, when using Lightning, many external devices had to go through MFi certification. However, since the iPhone 15 switched from Lightning to USB-C, is MFi certification still required?
Our company has developed several UVC devices, and we have confirmed that iPads can read frames from external cameras through the external device type in AVFoundation. However, this is not supported on iPhones.
We are currently exploring feasible ways to enable UVC device support on iPhones. Is MFi certification the only option? If so, is the MFi certification process for USB-C the same as it was for Lightning? Does it still require purchasing an MFi chip and manufacturing specially designed USB-C cables?
Hello,
We are developing a real-time speech recognition application and are utilizing AVAudioEngine with voice processing enabled on the input node. However, we have observed that enabling this mode interferes with the built-in iOS screen recording feature - specifically, the recorded video does not capture any audio when this mode is active.
Since we want users to be able to record their experience within our app, this issue significantly impacts our functionality. Is there a known workaround or recommended approach to ensure that both voice processing and screen recording can function simultaneously?
Any guidance would be greatly appreciated.
Thank you!
Issue:
Under certain conditions, using CallKit does not automatically enable the microphone.
Steps to Reproduce:
1.Start an outgoing call, then the user manually mutes the audio.
2.Receive a native incoming call, end the current call, then answer the new incoming call.(This order is important.)
3.End the incoming call.
4.Start another outgoing call and observe the microphone; do not manually mute or unmute.
Actual Behavior:
The audio icon indicates that the audio is unmuted, but the microphone remains off, and the small yellow dot in the top status bar (which represents the microphone) does not appear.
Expected Behavior:
The microphone should be on, consistent with the audio icon display, and the small yellow dot should appear in the top status bar.
Device:
iPhone 16 pro & iPhone 15 pro, iOS 18.0+
Can it be reproduced using speakerbox(CallKit Demo)?
YES
Hello, We have Video Stream app. It has HLS VOD Content. We supply 1080p, 4K Contents to users. Users were watching 1080p content before tvOS 26. Users can not watch 1080p content anymore when they update to tvOS 26. We have not changed anything at HLS playlist side and application version. This problem only occurs on Apple TV 4th Gen (A1625) tvOS 26 version. There is no problem with newer Apple TV devices. Would you help to resolve problem? Thanks in advance
Topic:
Media Technologies
SubTopic:
Streaming
Tags:
FairPlay Streaming
Apple TV
tvOS
HTTP Live Streaming
No external cameras show up in the app on visionOS. We use this sample code as a basis for our tests: https://developer.apple.com/documentation/visionos/displaying-video-from-connected-devices
We also received the needed entitlement from Apple, but every camera we tried so far does not show up on visionOS.
We tried the following devices and hubs:
Insta360 X4
Somikon Endoscope Camera: USB HD Endoscope Camera
EMEET Full HD Webcam - C960
BENFEI Video/Audio Capture Card, 4K HDMI auf USB C/A
Logitech C920 HD PRO Webcam,
Anker PowerConf C200
Insta360 GO 3S
Anker 341 USB-C Hub
UGREEN Revodok Pro 10Gbps USB-C Hub
All Vision Pro devices we tried run with visionOS 2.3. When trying the same code on iPad we can actually use external cameras.
Steps to reproduce:
Start the app on a Vision Pro device and connect an external camera. The connected camera does not show up in the dropdown.
Development environment:
Xcode 16.2, macOS 15.3
Run-time configuration:
iOS 18.3, visionOS 2.3
I would appreciate help in coding or an explanation what to use in swift for an app which will be able to capture LiDAR scanning and RGB data from taken pictures, generate a 3D mesh, and create .OBJ, .MTL, and .JPEG file set for further manipulation of 3D model.
Topic:
Media Technologies
SubTopic:
Photos & Camera
Tags:
3D Graphics
Swift Playground
Object Capture
Hi,
I am getting into a trap. Please check stack-trace, howto fix this?
regards, Joël
stack-trace with ExtAudioFileWrite
Hi everyone,
I’m exploring using the iPhone 17 Pro with the Blackmagic ProDock in a custom capture app. The genlock functionality seems accessible via AVExternalSyncDevice and related APIs, which is great.
I’m specifically curious about external timecode coming in from the ProDock:
• Is there a public way to access the timecode feed in a custom app via AVFoundation or another Apple API?
• If so, what is the recommended approach to read or apply that timecode during capture?
• Are there any current limitations or entitlements required to access timecode from ProDock in a third-party app?
I’m excited to start integrating synchronized capture in my app, and any guidance or sample patterns would be greatly appreciated.
Thanks in advance!
— [Artem]
Topic:
Media Technologies
SubTopic:
Video
FairPlay-Protected HLS Files Not Transferred via Quick Start I have an iOS app that downloads HLS files, which are protected by FairPlay. These files are stored locally, and their locations are managed using Core Data. When playing these tracks, I use AVURLAsset to access the stored file paths.
Recently, a client upgraded to a new iPhone and used Quick Start to transfer data from his old device. While all other app data was successfully transferred, including Core Data records and UserDefaults, the actual HLS files were missing. As a result, the app retained metadata about the downloaded content, but the files themselves were gone, causing playback failures.
Does Quick Start exclude certain types of locally stored files, especially DRM-protected HLS downloads, or is the issue related to how FairPlay-protected content is handled during the transfer of locally stored files?
Topic:
Media Technologies
SubTopic:
Streaming
Tags:
FairPlay Streaming
HTTP Live Streaming
AVFoundation
FxPlug is one of Apple’s official SDKs, recently updated to version 4.3.2. In theory the SDK should guarantee third-parties can build plug-ins that are backward compatible with older versions of Final Cut Pro, Motion and Compressor.
FxPlug SDK includes two frameworks that third-party developers like me end up bundling inside our third-party plugins: FxPlug.framework and PlugInManager.framework.
Behind the scenes, the SDK relies on PlugInKit, but the FxPlug.framework provides abstractions so that third-parties don't have to handle the intricacies of XPC directly.
The most recent version of FxPlug.framework included with the SDK was possibly built with an error: the Info.plist shows a LSMinimumSystemVersion entry of 14.6, suggesting the binary may have been compiled and linked with MACOSX_DEPLOYMENT_TARGET set to 14.6 by accident.
The problem: when older versions of Final Cut Pro or Motion load a third-party plugin (itself built with the appropriate deployment target, macOS 11 or 12, for example) on pre-macOS 14.6, the dynamic linker immediately loads Apple’s own FxPlug.framework, but this causes the process to crash immediately:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x7ff81e065955 map_images_nolock + 5399
1 libobjc.A.dylib 0x7ff81e0643d6 map_images + 67
2 dyld 0x10bd551fb invocation function for block in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) + 275
3 dyld 0x10bd506c9 dyld4::RuntimeState::withLoadersReadLock(void () block_pointer) + 41
4 dyld 0x10bd550e2 dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) + 82
5 dyld 0x10bd68d45 dyld4::APIs::_dyld_objc_notify_register(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) + 79
6 libobjc.A.dylib 0x7ff81e064244 _objc_init + 1279
7 libdispatch.dylib 0x7ff81e01d993 _os_object_init + 13
8 libdispatch.dylib 0x7ff81e02b1b8 libdispatch_init + 311
9 libSystem.B.dylib 0x7ff828fd585f libSystem_initializer + 238
10 dyld 0x10bd5ae4f invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 182
11 dyld 0x10bd81aad invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 242
12 dyld 0x10bd78e26 invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 557
13 dyld 0x10bd47db3 dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 129
14 dyld 0x10bd78bb7 dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 179
15 dyld 0x10bd81604 dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 466
16 dyld 0x10bd5ad82 dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 144
17 dyld 0x10bd6165a dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const + 30
18 dyld 0x10bd6e76e dyld4::APIs::runAllInitializersForMain() + 38
19 dyld 0x10bd4c38d dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*) + 3443
20 dyld 0x10bd4b4e4 start + 388
Can someone at Apple with the right domain expertise confirm that this is the type of crash you would see because the framework was built assuming it would run on macOS 14.6 and later, and when facing an older environment (e.g. ObjC runtime) it lacks extra code that would ensure backward compatibility with the earlier ObjC runtime found on macOS 12.x?
I'm developing the VisionOS app. I want to know how to play spatial audio in addition to RealityKit? If it's iOS or macOS, how to play spatial audio in addition to RealityKit?
If new photo is added to library and app is not running in foreground or was not opened after the new photo was added but the app is having full access to gallery, can it access, read the new photo - If the app is not specifically a cloud syncing app, can it have this attached function, suppose it is a game app or beauty camera app?
Topic:
Media Technologies
SubTopic:
Photos & Camera
Tags:
Privacy
PhotoKit
Background Tasks
Background Assets
I'm writing a program to control a PTZ camera connected via USB.
I can get access to target camera's unique_id, and also other infos provided by AVFoundation. But I don't know how to locate my target USB device to send a UVC ControlRequest.
There's many Cameras with same VendorID and ProductID connected at a time, so I need a more exact way to find out which device is my target.
It looks that the unique_id provided is (locationID<<32|VendorID<<16|ProductID) as hex string, but I'm not sure if I can always assume this behavior won't change.
Is there's a document declares how AVFoundation generate the unique_id for USB camera, so I can assume this convert will always work? Or is there's a way to send a PTZ control request to AVCaptureDevice?
https://stackoverflow.com/questions/40006908/usb-interface-of-an-avcapturedevice
I have seen this similar question. But I'm worrying that Exacting LocationID+VendorID+ProductID from unique_id seems like programming to implementation instead of interface. So, if there's any other better way to control my camera?
here's my example code for getting unique_id:
//
// camera_unique_id_test.mm
//
// 测试代码:使用C++获取当前系统摄像头的AVCaptureDevice unique_id
//
// 编译命令:
// clang++ -framework AVFoundation -framework CoreMedia -framework Foundation
// camera_unique_id_test.mm -o camera_unique_id_test
//
#include <iostream>
#include <string>
#include <vector>
#import <AVFoundation/AVFoundation.h>
#import <Foundation/Foundation.h>
struct CameraInfo {
std::string uniqueId;
};
std::vector<CameraInfo> getAllCameraDevices() {
std::vector<CameraInfo> cameras;
@autoreleasepool {
NSArray<AVCaptureDevice*>* devices =
[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice* defaultDevice =
[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// 遍历所有设备
for (AVCaptureDevice* device in devices) {
CameraInfo info;
// 获取unique_id
info.uniqueId = std::string([device.uniqueID UTF8String]);
cameras.push_back(info);
}
}
return cameras;
}
int main(int argc, char* argv[]) {
std::vector<CameraInfo> cameras = getAllCameraDevices();
for (size_t i = 0; i < cameras.size(); i++) {
const CameraInfo& camera = cameras[i];
std::cout << " 设备 " << (i + 1) << ":" << std::endl;
std::cout << " unique_id: " << camera.uniqueId << std::endl;
}
return 0;
}
and here's my code for UVC control:
// clang++ -framework Foundation -framework IOKit uvc_test.cpp -o uvc_test
#include <iostream>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/usb/USB.h>
CFStringRef CreateCFStringFromIORegistryKey(io_service_t ioService,
const char* key) {
CFStringRef keyString = CFStringCreateWithCString(kCFAllocatorDefault, key,
kCFStringEncodingUTF8);
if (!keyString)
return nullptr;
CFStringRef result = static_cast<CFStringRef>(
IORegistryEntryCreateCFProperty(ioService, keyString, kCFAllocatorDefault,
kIORegistryIterateRecursively));
CFRelease(keyString);
return result;
}
std::string GetStringFromIORegistry(io_service_t ioService, const char* key) {
CFStringRef cfString = CreateCFStringFromIORegistryKey(ioService, key);
if (!cfString)
return "";
char buffer[256];
Boolean success = CFStringGetCString(cfString, buffer, sizeof(buffer),
kCFStringEncodingUTF8);
CFRelease(cfString);
return success ? std::string(buffer) : std::string("");
}
uint32_t GetUInt32FromIORegistry(io_service_t ioService, const char* key) {
CFStringRef keyString = CFStringCreateWithCString(kCFAllocatorDefault, key,
kCFStringEncodingUTF8);
if (!keyString)
return 0;
CFNumberRef number = static_cast<CFNumberRef>(
IORegistryEntryCreateCFProperty(ioService, keyString, kCFAllocatorDefault,
kIORegistryIterateRecursively));
CFRelease(keyString);
if (!number)
return 0;
uint32_t value = 0;
CFNumberGetValue(number, kCFNumberSInt32Type, &value);
CFRelease(number);
return value;
}
int main() {
// Get matching dictionary for USB devices
CFMutableDictionaryRef matchingDict =
IOServiceMatching(kIOUSBDeviceClassName);
// Get iterator for matching services
io_iterator_t serviceIterator;
IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict,
&serviceIterator);
// Iterate through matching devices
io_service_t usbService;
while ((usbService = IOIteratorNext(serviceIterator))) {
uint32_t locationId = GetUInt32FromIORegistry(usbService, "locationID");
uint32_t vendorId = GetUInt32FromIORegistry(usbService, "idVendor");
uint32_t productId = GetUInt32FromIORegistry(usbService, "idProduct");
IOCFPlugInInterface** plugInInterface = nullptr;
IOUSBDeviceInterface** deviceInterface = nullptr;
SInt32 score;
// Get device plugin interface
IOCreatePlugInInterfaceForService(usbService, kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID, &plugInInterface,
&score);
// Get device interface
(*plugInInterface)
->QueryInterface(plugInInterface,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
(LPVOID*)&deviceInterface);
(*plugInInterface)->Release(plugInInterface);
// Try to find UVC control interface using CreateInterfaceIterator
io_iterator_t interfaceIterator;
IOUSBFindInterfaceRequest interfaceRequest;
interfaceRequest.bInterfaceClass = kUSBVideoInterfaceClass; // 14
interfaceRequest.bInterfaceSubClass = kUSBVideoControlSubClass; // 1
interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
interfaceRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare;
(*deviceInterface)
->CreateInterfaceIterator(deviceInterface, &interfaceRequest,
&interfaceIterator);
(*deviceInterface)->Release(deviceInterface);
io_service_t usbInterface = IOIteratorNext(interfaceIterator);
IOObjectRelease(interfaceIterator);
if (usbInterface) {
std::cout << "Get UVC device with:" << std::endl;
std::cout << "locationId: " << std::hex << locationId << std::endl;
std::cout << "vendorId: " << std::hex << vendorId << std::endl;
std::cout << "productId: " << std::hex << productId << std::endl
<< std::endl;
IOObjectRelease(usbInterface);
}
IOObjectRelease(usbService);
}
IOObjectRelease(serviceIterator);
}
I'm trying to implement airplay into my app. I can successfully playback sound and trigger the airplay selector sheet. If the target device is a Bluetooth only device I can connect with no problem and stream the audio to the Bluetooth device, but if the audio device is a airplay specific device like a HomePod or an Apple TV when I select it, I get a spinning icon, indicating that it is trying to connect, and eventually it times out and stops without connecting.
I don't believe it is an AirPlay audio issue because if I go to a different app, for example a podcast app and select my HomePods for output, and then switch back to my app. My audio will correctly stream to the HomePod. Not only that, I have it so that my icon will change color to indicate that it is connected via airplay and it is correctly indicating that it is connected via AirPlay. But I cannot then disconnect it using the Airplay selector.
The issue appears to be in the AirPlay selection side, which I have spent several days attempting to troubleshoot mostly using ChatGPT to suggest code different than what I have to maybe work around the issue. Mostly it is focused on the audio player section, but it doesn't seem like that is really the route that is the problem.
The operation couldn’t be completed. (CoreMediaErrorDomain error -19156 - The operation couldn’t be completed. (CoreMediaErrorDomain error -19156.
Hi all,
with my app ScreenFloat, you can record your screen, along with system- and microphone audio.
Those two audio feeds are recorded into separate audio tracks in order to individually remove or edit them later on.
Now, these recordings you create with ScreenFloat can be drag-and-dropped to other apps instantly. So far, so good, but some apps, like Slack, or VLC, or even websites like YouTube, do not play back multiple audio tracks, just one.
So what I'm trying to do is, on dragging the video recording file out of ScreenFloat, instantly baking together the two individual audio tracks into one, and offering that new file as the drag and drop file, so that all audio is played in the target app.
But it's slow. I mean, it's actually quite fast, but for drag and drop, it's slow.
My approach is this:
"Bake together" the two audio tracks into a one-track m4a audio file using AVMutableAudioMix and AVAssetExportSession
Take the video track, add the new audio file as an audio track to it, and render that out using AVAssetExportSession
For a quick benchmark, a 3'40'' movie, step 1 takes ~1.7 seconds, and step two adds another ~1.5 seconds, so we're at ~3.2 seconds. That's an eternity for a drag and drop, where the user might cancel if there's no immediate feedback.
I could also do it in one step, but then I couldn't use the AV*Passthrough preset, and that makes it take around 32 seconds then, because I assume it touches the video data (which is unnecessary in this case, so I think the two-step approach here is the fastest).
So, my question is, is there a faster way?
The best idea I can come up with right now is, when initially recording the screen with system- and microphone audio as separate tracks, to also record both of them into a third, muted, "hidden" track I could use later on, basically eliminating the need for step one and just ripping the two single audio tracks out of the movie and only have the video and the "hidden" track (then unmuted), but I'd still have a ~1.5 second delay there. Also, there's the processing and data overhead (basically doubling the movie's audio data).
All this would be great for an export operation (where one expects it to take a little time), but for a drag-and-drop operation, it's not ideal.
I've discarded the idea of doing a promise file drag, because many apps do not accept those, and I want to keep wide compatibility with all sorts of apps.
I'd appreciate any ideas or pointers.
Thank you kindly,
Matthias