fix(camera): modernize mp4 export
This commit is contained in:
@@ -199,25 +199,35 @@ actor CameraController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private nonisolated static func exportToMP4(inputURL: URL, outputURL: URL) async throws {
|
private nonisolated static func exportToMP4(inputURL: URL, outputURL: URL) async throws {
|
||||||
let asset = AVAsset(url: inputURL)
|
let asset = AVURLAsset(url: inputURL)
|
||||||
guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else {
|
guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else {
|
||||||
throw CameraError.exportFailed("Failed to create export session")
|
throw CameraError.exportFailed("Failed to create export session")
|
||||||
}
|
}
|
||||||
exporter.outputURL = outputURL
|
|
||||||
exporter.outputFileType = .mp4
|
|
||||||
exporter.shouldOptimizeForNetworkUse = true
|
exporter.shouldOptimizeForNetworkUse = true
|
||||||
|
|
||||||
try await withCheckedThrowingContinuation(isolation: nil) { cont in
|
if #available(iOS 18.0, tvOS 18.0, visionOS 2.0, *) {
|
||||||
exporter.exportAsynchronously {
|
do {
|
||||||
switch exporter.status {
|
try await exporter.export(to: outputURL, as: .mp4)
|
||||||
case .completed:
|
return
|
||||||
cont.resume(returning: ())
|
} catch {
|
||||||
case .failed:
|
throw CameraError.exportFailed(error.localizedDescription)
|
||||||
cont.resume(throwing: exporter.error ?? CameraError.exportFailed("Export failed"))
|
}
|
||||||
case .cancelled:
|
} else {
|
||||||
cont.resume(throwing: CameraError.exportFailed("Export cancelled"))
|
exporter.outputURL = outputURL
|
||||||
default:
|
exporter.outputFileType = .mp4
|
||||||
cont.resume(throwing: CameraError.exportFailed("Export did not complete"))
|
|
||||||
|
try await withCheckedThrowingContinuation(isolation: nil) { cont in
|
||||||
|
exporter.exportAsynchronously {
|
||||||
|
switch exporter.status {
|
||||||
|
case .completed:
|
||||||
|
cont.resume(returning: ())
|
||||||
|
case .failed:
|
||||||
|
cont.resume(throwing: exporter.error ?? CameraError.exportFailed("Export failed"))
|
||||||
|
case .cancelled:
|
||||||
|
cont.resume(throwing: CameraError.exportFailed("Export cancelled"))
|
||||||
|
default:
|
||||||
|
cont.resume(throwing: CameraError.exportFailed("Export did not complete"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,29 +200,39 @@ actor CameraCaptureService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private nonisolated static func exportToMP4(inputURL: URL, outputURL: URL) async throws {
|
private nonisolated static func exportToMP4(inputURL: URL, outputURL: URL) async throws {
|
||||||
let asset = AVAsset(url: inputURL)
|
let asset = AVURLAsset(url: inputURL)
|
||||||
guard let export = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality) else {
|
guard let export = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality) else {
|
||||||
throw CameraError.exportFailed("Failed to create export session")
|
throw CameraError.exportFailed("Failed to create export session")
|
||||||
}
|
}
|
||||||
export.outputURL = outputURL
|
|
||||||
export.outputFileType = .mp4
|
|
||||||
export.shouldOptimizeForNetworkUse = true
|
export.shouldOptimizeForNetworkUse = true
|
||||||
|
|
||||||
await withCheckedContinuation { cont in
|
if #available(macOS 15.0, *) {
|
||||||
export.exportAsynchronously {
|
do {
|
||||||
cont.resume()
|
try await export.export(to: outputURL, as: .mp4)
|
||||||
|
return
|
||||||
|
} catch {
|
||||||
|
throw CameraError.exportFailed(error.localizedDescription)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
export.outputURL = outputURL
|
||||||
|
export.outputFileType = .mp4
|
||||||
|
|
||||||
switch export.status {
|
await withCheckedContinuation { cont in
|
||||||
case .completed:
|
export.exportAsynchronously {
|
||||||
return
|
cont.resume()
|
||||||
case .failed:
|
}
|
||||||
throw CameraError.exportFailed(export.error?.localizedDescription ?? "export failed")
|
}
|
||||||
case .cancelled:
|
|
||||||
throw CameraError.exportFailed("export cancelled")
|
switch export.status {
|
||||||
default:
|
case .completed:
|
||||||
throw CameraError.exportFailed("export did not complete (\(export.status.rawValue))")
|
return
|
||||||
|
case .failed:
|
||||||
|
throw CameraError.exportFailed(export.error?.localizedDescription ?? "export failed")
|
||||||
|
case .cancelled:
|
||||||
|
throw CameraError.exportFailed("export cancelled")
|
||||||
|
default:
|
||||||
|
throw CameraError.exportFailed("export did not complete (\(export.status.rawValue))")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user