react-native-video/ios/Video/Features/RCTVideoSave.swift

76 lines
2.9 KiB
Swift
Raw Normal View History

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
}
}