Best way to export massive video file on iOS?

I am about to release a Mac app which (among other things) uses AVAssetExportSession to export a (potentially) massive video file after the user selects a URL from an NSSavePanel. These videos can take minutes to render, and take gigabytes of file space, so it needs to be asynchronus, and AVAssetExportSession demands a url to write to which does not already exist.


I'd love to build an iOS version as long as it also runs on the Mac, i.e. UIKitForMac. Now that the iPad will support attached USB drives, it's more likely that someone could use the ipad app to import massive video files that could be used in my app & then export the results back to the drive to share with another computer. Opening the existing video files in place seems doable with UIDocumentPickerViewController, but I'm unsure of how to properly export potentially massive files.


Looking at the UIDocumentPickerViewController API, it looks like I can't export a file to outside the app sandbox unless the file already exists in the sandbox. This is a bad experience for the person who renders a 5 minute 4K video and won't know until after several minutes of rendering that they can't find where they need to save it (which is what normally happens to me when I use a UIDocumentPickerViewController!).

It looks like I can save like a 1-byte file to a local url and retain security-scoped access to the exported URL and perhaps write more data to it. But AVAssetExportSession "just doesn't work" with pre-existing urls. So I'd have to render the entire video before picking where to save it, and potentially, there's not enough room on the ipad's internal storage for the original anyway. (Unless someone can tell me how to make AVAssetExportSession ok with overwriting an existing file.)


The WWDC 2010 session 407 says "

Well, an AVAssetExportSession will not let you overwrite an existing file, and attempting to do so will cause your handlerBlock to be called with a failed status. If you'd like to overwrite an existing file, you should remove the old one first. Perhaps you already know this, AVAssetExportSession will also not let you write two files outside of your application sandbox.

"


So that looks hopeless. Or does a security-scoped url count as in my sandbox from the session's perspective? Does deleting the file still give me access to it a moment later?


The other major option I see is UIActivityViewController, which seems like a good idea, since it might not only save as a file, but serve directly to other apps that might handle videos specifically. It supports UIActivityItemProvider, which lets me pick the export service first, and says it can do things asynchronously, but again, I'd have to write the file inside my sandbox with the AVAssetExportSession and then move it out. (boo). What I don't understand is how much fidelity do I need to put into the placeholder file? Does it only need the right file type (file extension), or do I need to write out a real movie in the same format as my final file in order for the system to understand what activities can share it?


So.... What's the best practice on iOS to export potentially-massive videos files writing once to external storage, with the intention of replacing my Mac app which has no problem doing this with a UIKitforMac app?

Replies

I actully coded up a sample of the idea of exporting a 1 byte file, then deleting it, then having the AVAssetExportSession write to that url. it seemed to work until I opened the final file. It contained all my audio, but only the first frame of the video. I tried my original mac app with the nssavepanel, and I got the same result (they share almost exactly the same AVAssetExportSession / AVVideoCompositionCoreAnimationTool code). There was an error in the debugger for both the original mac app (which works fine in macos 10.14) and the UIKitForMac app:


[] [01:46:24.698] openglVideoCompositor_SetProperty signalled err=-12784 (kFigBaseObjectError_PropertyNotFound) (unrecognised property) at /BuildRoot/Library/Caches/com.apple.xbs/Sources/CoreMedia/CoreMedia-2479.0.2/Prototypes/MediaConverter/VideoCompositing/FigVideoCompositor_OpenGL.c:1547


which appears to be en error in AVFoundation, so I reported it through feedback assistant. It would appear this is a workable path, but with the system error, I can't be sure.

Ok, here's the multi step path I found:


1) Prompt the user to select the file type. AVFileType, typically AVAssetExportSessions gives me 3 file types compatible with the composition.

2) Create a 0-byte file with a user-presentable name & the extension chosen in the previous step. Store it in a new uuid-named sub directory inside a temporary directory on the main volume.

3) present the document picker with that 0-byte file in "move" mode, which retains access to the file after the picker is done.

4) delete the uuid-named sub temp directory

5) using the final user-supplied url, use FileManager to find the "itemReplacementDirectory" on the volume where the user wants the export done.

6) have AVAssetExportSession export to a UUID-generated file name on the output volume.

7) replace the 0-byte file which has been moved to the volume & location picked by the user with the uuid-file containing the final video.

8) enable a share button which triggers an UIActivityViewController using the final user-selected url, which is a substitute for a mac-based NSWorkspace "Reveal in Finder", since it allows the user to do anything they want directly with the output file without needing to go anywhere else to do it.