@@ -374,6 +374,26 @@ defer { await UIApplication.shared.endBackgroundTask(taskID) }
374374try await exporter.export ()
375375```
376376
377+ ### Working with Photos Library
378+
379+ When exporting videos from the user's photo library, copy the file to your app's directory first to avoid permission issues:
380+
381+ ``` swift
382+ // ⚠️ NOT RECOMMENDED: Direct PHAsset access may cause cancelled errors
383+ let phAsset = // ... from photo library
384+ let avAsset = AVAsset (url : phAsset.url ) // May fail!
385+
386+ // ✅ RECOMMENDED: Copy to app directory first
387+ let tempURL = FileManager.default .temporaryDirectory
388+ .appendingPathComponent (" video.mov" )
389+
390+ // Export PHAsset to temp file, then create AVAsset
391+ let avAsset = AVAsset (url : tempURL)
392+ let exporter = NextLevelSessionExporter (withAsset : avAsset)
393+ ```
394+
395+ See the [ Troubleshooting section] ( #export-fails-with-cancelled-error-issue-37 ) for complete implementation.
396+
377397## Troubleshooting
378398
379399### Error -11819 "Cannot Complete Action" (iOS 14.5+)
@@ -417,6 +437,83 @@ func exportWithRetry(maxAttempts: Int = 3) async throws -> URL {
417437- [ Apple Forums Thread] ( https://developer.apple.com/forums/thread/679862 )
418438- [ Radar: FB8815719] ( https://openradar.appspot.com/FB8815719 )
419439
440+ ### Export Fails with "Cancelled" Error (Issue #37 )
441+
442+ ** Problem:** Some videos fail to compress with a cancelled/canceled error message, especially when selecting videos directly from the photo library.
443+
444+ ** Cause:** File access permissions or buffering issues when reading from certain storage locations.
445+
446+ ** Solution:** Copy the video to your app's writable directory before exporting:
447+
448+ ``` swift
449+ func exportVideoFromLibrary (asset : PHAsset) async throws -> URL {
450+ // 1. Export to temporary file first
451+ let tempURL = FileManager.default .temporaryDirectory
452+ .appendingPathComponent (UUID ().uuidString )
453+ .appendingPathExtension (" mov" )
454+
455+ // 2. Request video resource from Photos library
456+ let options = PHVideoRequestOptions ()
457+ options.version = .current
458+ options.deliveryMode = .highQualityFormat
459+
460+ try await withCheckedThrowingContinuation { continuation in
461+ PHImageManager.default ().requestExportSession (
462+ forVideo : asset,
463+ options : options,
464+ exportPreset : AVAssetExportPresetPassthrough
465+ ) { exportSession, _ in
466+ guard let session = exportSession else {
467+ continuation.resume (throwing : NSError (domain : " Export" , code : -1 ))
468+ return
469+ }
470+
471+ session.outputURL = tempURL
472+ session.outputFileType = .mov
473+ session.exportAsynchronously {
474+ if session.status == .completed {
475+ continuation.resume (returning : ())
476+ } else {
477+ continuation.resume (throwing : session.error ?? NSError (domain : " Export" , code : -1 ))
478+ }
479+ }
480+ }
481+ }
482+
483+ // 3. Now export with NextLevelSessionExporter
484+ let avAsset = AVAsset (url : tempURL)
485+ let exporter = NextLevelSessionExporter (withAsset : avAsset)
486+
487+ let outputURL = FileManager.default .temporaryDirectory
488+ .appendingPathComponent (UUID ().uuidString )
489+ .appendingPathExtension (" mp4" )
490+
491+ exporter.outputURL = outputURL
492+ exporter.videoOutputConfiguration = [/* your config */ ]
493+ exporter.audioOutputConfiguration = [/* your config */ ]
494+
495+ let result = try await exporter.export ()
496+
497+ // 4. Clean up temp file
498+ try ? FileManager.default .removeItem (at : tempURL)
499+
500+ return result
501+ }
502+ ```
503+
504+ ** Alternative (simpler):** Use ` AVAsset(url:) ` with a file URL rather than ` PHAsset ` directly:
505+
506+ ``` swift
507+ // Copy to caches directory first
508+ let cacheURL = FileManager.default .urls (for : .cachesDirectory , in : .userDomainMask )[0 ]
509+ .appendingPathComponent (" video.mov" )
510+
511+ // ... copy file to cacheURL ...
512+
513+ let asset = AVAsset (url : cacheURL)
514+ let exporter = NextLevelSessionExporter (withAsset : asset)
515+ ```
516+
420517### Export Fails with "Reading Failure"
421518
422519** Problem:** Export fails when reading the source asset.
@@ -425,6 +522,7 @@ func exportWithRetry(maxAttempts: Int = 3) async throws -> URL {
425522- Verify the source asset is not corrupted
426523- Check that the asset is a supported format (MP4, MOV, M4V, etc.)
427524- Ensure the asset is accessible and not protected by DRM
525+ - If reading from Photos library, see "Cancelled Error" above
428526
429527### Memory Issues on Long Videos
430528
0 commit comments