76 lines
2.9 KiB
Swift
76 lines
2.9 KiB
Swift
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
|
|
}
|
|
}
|