import AVFoundation enum RCTVideoSave { static func save( options _: NSDictionary!, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock, playerItem: AVPlayerItem? ) { let asset: AVAsset! = playerItem?.asset guard asset != nil else { reject("ERROR_ASSET_NIL", "Asset is nil", nil) return } guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else { reject("ERROR_COULD_NOT_CREATE_EXPORT_SESSION", "Could not create export session", nil) return } #if !os(visionOS) var path: String! path = RCTVideoSave.generatePathInDirectory( directory: URL(fileURLWithPath: RCTVideoSave.cacheDirectoryPath() ?? "").appendingPathComponent("Videos").path, withExtension: ".mp4" ) let url: NSURL! = NSURL.fileURL(withPath: path) as NSURL exportSession.outputFileType = .mp4 exportSession.outputFileType = AVFileType.mp4 exportSession.outputURL = url as URL? exportSession.videoComposition = playerItem?.videoComposition exportSession.shouldOptimizeForNetworkUse = true exportSession.exportAsynchronously(completionHandler: { switch exportSession.status { case .failed: reject("ERROR_COULD_NOT_EXPORT_VIDEO", "Could not export video", exportSession.error) case .cancelled: reject("ERROR_EXPORT_SESSION_CANCELLED", "Export session was cancelled", exportSession.error) default: resolve(["uri": url.absoluteString]) } }) #else reject("ERROR_EXPORT_SESSION_CANCELLED", "this function is not supported on visionOS", nil) #endif } static func generatePathInDirectory(directory: String?, withExtension extension: String?) -> String? { let fileName = UUID().uuidString + (`extension` ?? "") RCTVideoSave.ensureDirExists(withPath: directory) return URL(fileURLWithPath: directory ?? "").appendingPathComponent(fileName).path } static func cacheDirectoryPath() -> String? { let array = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).map(\.path) return array[0] } static func ensureDirExists(withPath path: String?) -> Bool { var isDir: ObjCBool = false var error: Error? let exists = FileManager.default.fileExists(atPath: path ?? "", isDirectory: &isDir) if !(exists && isDir.boolValue) { do { try FileManager.default.createDirectory(atPath: path ?? "", withIntermediateDirectories: true, attributes: nil) } catch {} if error != nil { return false } } return true } }