Short summary
When setting exposureMode to .locked or .custom the brightness of a video stream still changes depending on the composition and contrast of the visible scene. These changes seem to come from contrast enhancements or dynamic range optimizations and totally break any analysis of the image that requires to assess absolute luminance. While exposure lock seems to indeed lock the physical exposure parameters of the camera (shutter speed and ISO), I cannot find any way to control these "soft" modifiers.
Details
Background
I am the developer of the app "phyphox", an educational app that makes the phone's sensors accessible to students as measurement tools in science experiments. Currently I am working on implementing photometric measurements through the camera and one very important aspect of it is luminance measurements.
This is particularly relevant since the light sensor of the phone has no publicly accessible API and the camera could to some extend make experiments available to Apple users that are otherwise only possible on Android devices.
Implementation
The app uses AVFoundation and explicitly picks individual cameras since camera groups do not support custom exposure settings. This means that it handles camera switching during zoom by itself and even implements its own auto exposure routines to optimize for the use in experiments. Therefore it always stays in custom exposure mode. The app uses YUV420 color space and the individual frames are analyzed in Metal using compute shaders.
However, the effects discussed here still occur if I remove all code to control the camera and replace it with a simple sequence of setting the exposure mode to custom, setting custom exposure values, setting a fixed white balance and then setting the exposure mode to locked as suggested on stackoverflow. This neither helps on an iPhone 14 Pro nor on an iPhone 8 despite a report on the developer forums that it would resolve the issue for older devices.
The app is open source, so the code can be seen in our current development branch (without the changes for the tests here, though) on github.
The videos below use the implementation with the suggestion from stackoverflow, but they can be reproduced in the same way with "professional" camera apps that promise manual control over the camera (like the Blackmagic cam to quote a reputable company) as well as the stock camera app after pressing and holding on the preview to enable AE/AF lock.
Demonstration
These examples were captured on an iPhone 14 Pro. The central part of the image (highlighted by the app using metal shaders after capture) should not change with fixed exposure settings, but significant changes are noticable if there are changes at the edge of the frame when I move a black piece of cardboard in from above:
https://share.icloud.com/photos/0b1f_3IB6yAQG-qSH27pm6oDQ
The graph above the camera preview is the average luminance (gamma corrected and weighted based on sRGB) across the highlighted central area and as mentioned before it should not change because of something happening at the side of the frame (worst case it should get a bit darker because of the cardboard's shadow).
In my opinion, the iPhone changes its mind on the ideal contrast as soon as it has a different exposure histogram because of the dark image part from the cardboard, but that's just me guessing.
For completeness here is the same effect in the stock camera app with AE/AF lock enabled:
https://share.icloud.com/photos/0cd7QM8ucBZKwPwE9mybnEowg
Here you can also see that the iPhone "ramps" the changes. The brightness of the gray area does not change immediately but transitions smoothly, so this is clearly deliberate postprocessing.
So...
Any suggestion on how to prevent this behavior would be highly appreciated.
Video
RSS for tagDive into the world of video on Apple platforms, exploring ways to integrate video functionalities within your iOS,iPadOS, macOS, tvOS, visionOS or watchOS app.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
As of iOS 18, as far as I can tell, it appears there's still no AVPlayer options that allow users to toggle the caption / subtitle track on and off. Does anyone know of a way to do this with AVPlayer or with SwiftUI's VideoPlayer?
The following code reproduces this issue. It can be pasted into an app playground. This is a random video and a random vtt file I found on the internet.
import SwiftUI
import AVKit
import UIKit
struct ContentView: View {
private let video = URL(string: "https://server15700.contentdm.oclc.org/dmwebservices/index.php?q=dmGetStreamingFile/p15700coll2/15.mp4/byte/json")!
private let captions = URL(string: "https://gist.githubusercontent.com/samdutton/ca37f3adaf4e23679957b8083e061177/raw/e19399fbccbc069a2af4266e5120ae6bad62699a/sample.vtt")!
@State private var player: AVPlayer?
var body: some View {
VStack {
VideoPlayerView(player: player)
.frame(maxWidth: .infinity, maxHeight: 200)
}
.task {
// Captions won't work for some reason
player = try? await loadPlayer(video: video, captions: captions)
}
}
}
private struct VideoPlayerView: UIViewControllerRepresentable {
let player: AVPlayer?
func makeUIViewController(context: Context) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = player
controller.modalPresentationStyle = .overFullScreen
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
uiViewController.player = player
}
}
private func loadPlayer(video: URL, captions: URL?) async throws -> AVPlayer {
let videoAsset = AVURLAsset(url: video)
let videoPlusSubtitles = AVMutableComposition()
try await videoPlusSubtitles.add(videoAsset, withMediaType: .video)
try await videoPlusSubtitles.add(videoAsset, withMediaType: .audio)
if let captions {
let captionAsset = AVURLAsset(url: captions)
// Must add as .text. .closedCaption and .subtitle don't work?
try await videoPlusSubtitles.add(captionAsset, withMediaType: .text)
}
return await AVPlayer(playerItem: AVPlayerItem(asset: videoPlusSubtitles))
}
private extension AVMutableComposition {
func add(_ asset: AVAsset, withMediaType mediaType: AVMediaType) async throws {
let duration = try await asset.load(.duration)
try await asset.loadTracks(withMediaType: mediaType).first.map { track in
let newTrack = self.addMutableTrack(withMediaType: mediaType, preferredTrackID: kCMPersistentTrackID_Invalid)
let range = CMTimeRangeMake(start: .zero, duration: duration)
try newTrack?.insertTimeRange(range, of: track, at: .zero)
}
}
}
How can I setup correctly AVSampleBufferDisplayLayer for video display when I have input picture format kCVPixelFormatType_32BGRA?
Currently video i visible in simulator, but not iPhone, miss I something?
Render code:
var pixelBuffer: CVPixelBuffer?
let attrs: [String: Any] = [
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
kCVPixelBufferWidthKey as String: width,
kCVPixelBufferHeightKey as String: height,
kCVPixelBufferBytesPerRowAlignmentKey as String: width * 4,
kCVPixelBufferIOSurfacePropertiesKey as String: [:]
]
let status = CVPixelBufferCreateWithBytes(
nil,
width,
height,
kCVPixelFormatType_32BGRA,
img,
width * 4,
nil,
nil,
attrs as CFDictionary,
&pixelBuffer
)
guard status == kCVReturnSuccess, let pb = pixelBuffer else { return }
var formatDesc: CMVideoFormatDescription?
CMVideoFormatDescriptionCreateForImageBuffer(
allocator: nil,
imageBuffer: pb,
formatDescriptionOut: &formatDesc
)
guard let format = formatDesc else { return }
var timingInfo = CMSampleTimingInfo(
duration: .invalid,
presentationTimeStamp: currentTime,
decodeTimeStamp: .invalid
)
var sampleBuffer: CMSampleBuffer?
CMSampleBufferCreateForImageBuffer(
allocator: kCFAllocatorDefault,
imageBuffer: pb,
dataReady: true,
makeDataReadyCallback: nil,
refcon: nil,
formatDescription: format,
sampleTiming: &timingInfo,
sampleBufferOut: &sampleBuffer
)
if let sb = sampleBuffer {
if CMSampleBufferGetPresentationTimeStamp(sb) == .invalid {
print("Invalid video timestamp")
}
if (displayLayer.status == .failed) {
displayLayer.flush()
}
DispatchQueue.main.async { [weak self] in
guard let self = self else {
print("Lost reference to self drawing")
return
}
displayLayer.enqueue(sb)
}
frameIndex += 1
}
I have added some custom views on my pip. These controls disappeared after opening the camera in the Xcode16 environment and iOS 18 system, and it was found that these custom views were not removed and seemed to be obscured. They were displayed normally in the Xcode15.4 environment. I would like to ask how to make my custom views display normally
Topic:
Media Technologies
SubTopic:
Video
My app allows users to capture and save videos to the Photos app using the following Swift code:
PHPhotoLibrary.shared().performChanges {
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: fileURL)
} completionHandler: { success, error in
Videos are successfully saved to Photos and play correctly. However, users report that when they AirDrop these videos from the Photos app to another device (e.g., iPad to iPhone), the videos are saved in the Files app on the receiving device instead of the Photos app. This issue is more common with higher-resolution videos, such as 2K, recorded in HEVC format at 30 fps.
I wasn't able to reproduce the issue locally.
I've found a thread in public apple forum: https://discussions.apple.com/thread/255276865?sortBy=rank but I wonder maybe there are some special flags that I should clear or add to my videos (e.g. PHAssetChangeRequest)?
Thank you!
I am currently developing an HEVC player using VideoToolbox on an iOS device.
I have successfully created an HEVC decoder that receives HEVC streams from our custom image capture and encoding device, and it can decode and display images properly.
However, when my image capture and encoding device configures the encoder to output HEVC streams with fragmented NALUs (i.e., an I-frame or P-frame is split and stored across multiple slice NALUs), the iOS decoder can be initialized successfully but fails to decode and output images.
Can VideoToolbox properly decode HEVC bitstreams when a single frame is split into multiple slice NALUs?
Key Observations:
1. Single-NALU frames work fine.
2. Multi-NALU frames (sliced I/P-frames) cause decoding failure.
3. The decoder session is created successfully (VTDecompressionSessionCreate returns no error).
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
Hello,
I need to enumerate built-in media devices (cameras, microphones, etc.). For this purpose, I am using the CoreAudio and CoreMediaIO frameworks.
According to the table 'Daemon-Safe Frameworks' in Apple’s TN2083, CoreAudio is daemon-safe. However, the documentation does not mention CoreMediaIO.
Can CoreMediaIO be used in a daemon?
If not, are there any documented alternatives to detect built-in cameras in a daemon (e.g., via device classes in IOKit)?
Thank you in advance,
Pavel
In Final Cut Pro, keyframes for transform parameters (such as Position, Scale, and Rotation) are automatically set to “Smooth” interpolation. This often results in undesired easing between keyframes, especially when linear motion is required.
Currently, we have to manually adjust each keyframe to "Linear" using the Video Animation Editor, which can be time-consuming when working with many keyframes.
Would it be possible to add an option to set the default keyframe interpolation to "Linear"—either globally in Preferences or per parameter in the Inspector?
This would greatly streamline the animation workflow for many editors.
Thank you for considering this request!
When I play an HDR video in the iPhone Photos app, I can see the HDR effect obviously. But if this HDR video is played continuously for more than 30-40 minutes, the HDR effect will disappear and the brightness will be compressed to the SDR range. This issue will appear on any iPhone.
Depending on the phone, it may be 20-30 minutes, or 30-40 minutes, or even a few minutes, such as iPhone 12 mini.
Similarly, if I use AVPlayer to play and preview an HDR video, if it plays more than 30-40 minutes, the HDR effect will disappear and the screen brightness will dim. Also the currentEDRHeadroom will gradually decrease to 1
Note, test it with an HDR video longer than 1 hour, and if the video is short, please loop it.
My question is how to avoid losing the HDR effect after 30-40 minutes when I use CAMetalLayer to render any HDR video.
I'm currently using ReplayKit for background screen recording, but I can't determine whether the screen is in landscape mode from the CMSampleBuffer. All other APIs for detecting screen orientation are foreground-based. What should I do?
Hi All. I'm working on Single-Sign-On feature in my application to let customers sign into their TV Provider. I need to add Video Subscriber SSO entitlement (com.apple.developer.video-subscriber-single-sign-on) to the app, but I found out that it's a special entitlement, need to contact Apple to enable it for my Apple account. On https://developer.apple.com/account I navigated to Support -> Contact Us -> Development and Technical -> Entitlements and ask in the email about missing entitlement (ticket ID 102478794279). The support team couldn't help me, they redirected me to the operations team. I've been waiting for a few months now but they inform me to keep waiting.
Is there a better way to contact Apple and get Video Subscriber SSO entitlement in an efficient way?
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.
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 working on a media app that would like to be able to tell if the TV connected to tvOS is running at 59.94hz or 60.00hz, so it can optimize a video stream. It looks like the best I can currently do is to check if the user has Match Content Rate enabled, and based on that, when calling displayManager.preferredDisplayCriteria to change video modes, I could guess which rate their TV might be in. It's not very ideal, because not all TVs support both of these rates, and my request for 59.94 might end up as 60 and vice versa.
I dug around and can't find any available method in UIScreen to get this info. The odd thing is, the data is right there in currentMode when I look in the debugger, but it seems to be in a private or undocumented class. Is there any way to get at it?
I'm working on an app where a user needs to select a video from their Photos library, and I need to get the original, unmodified HEVC (H.265) data stream to preserve its encoding.
The Problem
I have confirmed that my source videos are HEVC. I can record a new video with my iPhone 15 Pro Max camera set to "High Efficiency," export the "Unmodified Original" from Photos on my Mac, and verify that the codec is MPEG-H Part2/HEVC (H.265).
However, when I select that exact same video in my app using PHPickerViewController, the itemProvider does not list public.hevc as an available type identifier. This forces me to fall back to a generic movie type, which results in the system providing me with a transcoded H.264 version of the video.
Here is the debug output from my app after selecting a known HEVC video:
⚠️ 'public.hevc' not found. Falling back to generic movie type (likely H.264).
What I've Tried
My code explicitly checks for the public.hevc identifier in the registeredTypeIdentifiers array. Since it's not found, my HEVC-specific logic is never triggered.
Here is a minimal version of my PHPickerViewControllerDelegate implementation:
import UniformTypeIdentifiers
// ... inside the Coordinator class ...
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
guard let result = results.first else { return }
let itemProvider = result.itemProvider
let hevcIdentifier = "public.hevc"
let identifiers = itemProvider.registeredTypeIdentifiers
print("Available formats from itemProvider: \(identifiers)")
if identifiers.contains(hevcIdentifier) {
print("✅ HEVC format found, requesting raw data...")
itemProvider.loadDataRepresentation(forTypeIdentifier: hevcIdentifier) { (data, error) in
// ... process H.265 data ...
}
} else {
print("⚠️ 'public.hevc' not found. Falling back to generic movie type (likely H.264).")
itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { url, error in
// ... process H.264 fallback ...
}
}
}
My Environment
Device: iPhone 15 Pro Max
iOS Version: iOS 18.5
Xcode Version: 16.2
My Questions
Are there specific conditions (e.g., the video being HDR/Dolby Vision, Cinematic, or stored in iCloud) under which PHPickerViewController's itemProvider would intentionally not offer the public.hevc type identifier, even for an HEVC video?
What is the definitive, recommended API sequence to guarantee that I receive the original, unmodified data stream for a video asset, ensuring that no transcoding to H.264 occurs during the process?
Any insight into why public.hevc might be missing from the registeredTypeIdentifiers for a known HEVC asset would be greatly appreciated. Thank you.
When i use AVPlayer to obtain the video frame CVPixelBufferRef of an HDR video, and use AVSampleBufferDisplayLayer to display it on the screen, after a period of time, the HDR video content and screen gradually darken, losing the HDR effect.
Steps to reproduce:
Create an AVPlayer to loop an HDR video, specify the video frame format as kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange
Create a timer to get the video frame CVPixelBufferRef at 30 frames per second
Use AVSampleBufferDisplayLayer to display CVPixelBufferRef on the screen
Don't operate the phone, wait for a period of time (such as 40 minutes), the HDR effect disappears and the screen darkens
Note:
You need to use an iPhone device, iOS 18.5 and below operating system
You need to ensure that the HDR video is played in a loop, that is, to ensure that the screen continues to display HDR content, wait for a period of time, depending on different devices, you need to wait for 20-40 minutes.
In the iPhone Photos app,the same problem will occur after playing HDR video in a loop for a long time
Expected Results:
When rendering HDR content for a long time, it is guaranteed that there is always an HDR effect, and the HDR content and screen will not be darkened.
Current Results:
After about 20-40 minutes, the HDR effect disappears and the screen darkens.
Hi everyone,
I'm developing a visionOS app for Apple Vision Pro, and I've encountered an issue related to window resizing at runtime when using AVPlayer to play a live HLS stream.
✅ What I'm Trying to Do
Play a live HLS stream (from Wowza) inside my app using AVPlayer.
Support resizing the immersive window using Vision Pro’s built-in runtime scaling gesture.
Stream works fine at default window size when the app launches.
❌ Problem
If I resize the app’s window at runtime (using the Vision Pro pinch-drag gesture), then try to start the stream, it does not play.
Instead, it just shows the "Loading live stream..." state and never proceeds to playback.
This issue only occurs after resizing the window — if I don’t resize, the stream works perfectly every time.
🧪 What I’ve Tried
Verified the HLS URL — it’s working and plays fine in Safari and in the app before resizing.
Set .automaticallyWaitsToMinimizeStalling = false on AVPlayer.
Observed that .status on AVPlayerItem never reaches .readyToPlay after resizing.
Tried to force window size back using UIWindowScene.requestGeometryUpdate(...), but behavior persists.
I'm developing a Final Cut Pro X workflow extension that transcribes audio and creates a text output. I need to allow users to drag this text directly from my extension into FCPX's timeline as titles.
Current Implementation:
Using NSFilePromiseProvider as per Apple's guidelines for drag and drop
Generating valid FCPXML (v1.10) with proper structure:
Complete resources section with format and asset references
Event and project hierarchy
Asset clip with connected title elements
Proper timing and duration calculations
Supporting multiple pasteboard types:
com.apple.finalcutpro.xml.v1-10
com.apple.finalcutpro.xml.v1-9
com.apple.finalcutpro.xml
What's Working:
Drag operation initiates correctly
File promise provider is set up properly
FCPXML generation is successful (verified content)
All required pasteboard types are registered
Proper logging confirms data is being requested and provided
Current Pasteboard Types Offered:
com.apple.NSFilePromiseItemMetaData
com.apple.pasteboard.promised-file-name
com.apple.pasteboard.promised-suggested-file-name
com.apple.pasteboard.promised-file-content-type
Apple files promise pasteboard type
com.apple.pasteboard.NSFilePromiseID
com.apple.pasteboard.promised-file-url
com.apple.finalcutpro.xml.v1-10
com.apple.finalcutpro.xml.v1-9
com.apple.finalcutpro.xml
What additional requirements or considerations are needed to make FCPX accept the dragged FCPXML content? Are there specific requirements for workflow extensions regarding drag and drop operations with titles that aren't documented?
Any insights, especially from those who have implemented similar functionality in FCPX workflow extensions, would be greatly appreciated.
Technical Details:
macOS Version: 15.5 (24F74)
FCPX Version: 11.1.1
Extension built with SwiftUI and AppKit integration
Using NSFilePromiseProvider and NSPasteboardItemDataProvider
Full pasteboard type support for FCPXML versions
Our Final Cut Pro workflow extension built with ProExtensionHost framework uses an advanced NSPasteboardItemDataProvider system with multi-version FCPXML support (1.9, 1.10, 1.13) and proper relative path
UIDs for Motion templates. We've implemented clip wrapper approach with placeholder assets and elements containing effects to enable direct timeline drag functionality. However, drag
and drop from our Final Cut Pro workflow extension directly to timeline is still not working despite proper element structure in our FCPXML. Our implementation creates valid clip elements with
effects applied, but Final Cut Pro timeline doesn't accept them during drag operations from our ProExtensionHost-based workflow extension.
Steps to Reproduce:
Create Final Cut Pro workflow extension using ProExtensionHost framework with NSPasteboardItemDataProvider implementation
Generate FCPXML with proper element structure:
Expected Result: Clip should be accepted by timeline and effect applied from workflow extension
Actual Result: Timeline rejects drag operation from ProExtensionHost-based workflow extension
Question: Are there additional requirements or ProExtensionHost API calls needed beyond standard NSPasteboardItemDataProvider for Final Cut Pro workflow extension timeline drag functionality?