@@ -65,10 +65,8 @@ public class Recorder {
6565 }
6666
6767 public func setupRecording( ) {
68- let tempDirectoryURL = FileManager . default. temporaryDirectory
69- let outputURL = tempDirectoryURL. appendingPathComponent ( UUID ( ) . uuidString) . appendingPathExtension ( " mp4 " )
7068 do {
71- assetWriter = try AVAssetWriter ( outputURL: outputURL , fileType: . mp4)
69+ assetWriter = try AVAssetWriter ( outputURL: renderSettings . tempOutputURL , fileType: . mp4)
7270
7371 videoRecorder. setupVideoInput ( )
7472 audioRecorder. setupAudioInput ( )
@@ -130,14 +128,13 @@ public class Recorder {
130128 }
131129 }
132130
133- func finishRecording( ) {
131+ func finishRecording( ) async {
134132 print ( " FINISH recording " )
135133 guard state != . idle else { return }
136134
137135 audioRecorder. stopRecording ( )
138136
139- finishWriting ( )
140- recordingCompletionContinuation. continuation. finish ( )
137+ await finishWriting ( )
141138 state = . idle
142139 }
143140
@@ -169,25 +166,34 @@ public class Recorder {
169166
170167 public func waitForRecordingCompletion( ) async {
171168 for await _ in recordingCompletionContinuation. stream { }
172- try ? await Task . sleep ( for: . seconds( 1.0 ) )
173169 }
174170
175- private func finishWriting( ) {
176- print ( " finish writing " )
177- if renderSettings. saveVideoFile {
178- assetWriter? . finishWriting {
179- print ( " Recording finished and saved to \( String ( describing: self . assetWriter? . outputURL) ) " )
180- // DispatchQueue.main.async {
181- // NSApplication.shared.terminate(nil)
182- // }
183-
184- if let outputURL = self . assetWriter? . outputURL, let duration = self . renderSettings. captureDuration {
185- self . trimVideo ( at: outputURL, to: duration) { trimmedURL in
186- print ( " Recording finished and saved to \( String ( describing: trimmedURL) ) " )
187- }
188- }
171+ private func finishWriting( ) async {
172+ print ( " Finish writing " )
173+ guard renderSettings. saveVideoFile else {
174+ recordingCompletionContinuation. continuation. finish ( )
175+ return
176+ }
177+
178+ await assetWriter? . finishWriting ( )
179+
180+ guard let tempOutputURL = assetWriter? . outputURL else {
181+ print ( " No output URL available " )
182+ recordingCompletionContinuation. continuation. finish ( )
183+ return
184+ }
185+
186+ if let outputURL = assetWriter? . outputURL, let duration = renderSettings. captureDuration {
187+ if let trimmedURL = await trimVideo ( at: outputURL, to: duration) {
188+ print ( " Recording trimmed and saved to \( trimmedURL) " )
189+ try ? FileManager . default. removeItem ( at: tempOutputURL)
189190 }
191+ } else {
192+ try ? FileManager . default. moveItem ( at: tempOutputURL, to: renderSettings. outputURL)
193+ print ( " Recording finished and saved to \( String ( describing: assetWriter? . outputURL) ) " )
190194 }
195+
196+ recordingCompletionContinuation. continuation. finish ( )
191197 }
192198
193199// Audio
@@ -237,35 +243,36 @@ public class Recorder {
237243 }
238244 }
239245
240- private func trimVideo( at url: URL , to duration: Duration , completion : @escaping ( URL ? ) -> Void ) {
246+ private func trimVideo( at url: URL , to duration: Duration ) async -> URL ? {
241247 let asset = AVAsset ( url: url)
242248 let startTime = CMTime . zero
243249 let endTime = CMTime ( seconds: Double ( duration. components. seconds) , preferredTimescale: 600 )
244250
245251 guard let exportSession = AVAssetExportSession ( asset: asset, presetName: AVAssetExportPresetHighestQuality) else {
246252 print ( " Failed to create export session " )
247- completion ( nil )
248- return
253+ return nil
249254 }
250255
251- let trimmedOutputURL = url . deletingLastPathComponent ( ) . appendingPathComponent ( UUID ( ) . uuidString ) . appendingPathExtension ( " mp4 " )
256+ let trimmedOutputURL = renderSettings . outputURL
252257 exportSession. outputURL = trimmedOutputURL
253258 exportSession. outputFileType = . mp4
254259 exportSession. timeRange = CMTimeRange ( start: startTime, end: endTime)
255260
256- exportSession. exportAsynchronously {
257- switch exportSession. status {
258- case . completed:
259- print ( " Trimming completed successfully " )
260- completion ( trimmedOutputURL)
261- case . failed:
262- print ( " Trimming failed: \( String ( describing: exportSession. error) ) " )
263- completion ( nil )
264- case . cancelled:
265- print ( " Trimming cancelled " )
266- completion ( nil )
267- default :
268- break
261+ return await withCheckedContinuation { continuation in
262+ exportSession. exportAsynchronously {
263+ switch exportSession. status {
264+ case . completed:
265+ print ( " Trimming completed successfully " )
266+ continuation. resume ( returning: trimmedOutputURL)
267+ case . failed:
268+ print ( " Trimming failed: \( String ( describing: exportSession. error) ) " )
269+ continuation. resume ( returning: nil )
270+ case . cancelled:
271+ print ( " Trimming cancelled " )
272+ continuation. resume ( returning: nil )
273+ default :
274+ continuation. resume ( returning: nil )
275+ }
269276 }
270277 }
271278 }
0 commit comments