From 8f049aed95934aaae99193862e3aa76a7a76cd38 Mon Sep 17 00:00:00 2001 From: Sami Samhuri Date: Mon, 12 Aug 2024 19:01:21 -0700 Subject: [PATCH] Make SampleWriter.init nonisolated so it can load tracks --- .../project.pbxproj | 6 ++--- SJSAssetExportSession/SampleWriter.swift | 26 +++++++++---------- .../VideoOutputSettings.swift | 2 +- .../AVAsset+sending.swift | 2 +- .../SJSAssetExportSessionTests.swift | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) rename {SJSAssetExportSession => SJSAssetExportSessionTests}/AVAsset+sending.swift (90%) diff --git a/SJSAssetExportSession.xcodeproj/project.pbxproj b/SJSAssetExportSession.xcodeproj/project.pbxproj index 5a65854..b0ba426 100644 --- a/SJSAssetExportSession.xcodeproj/project.pbxproj +++ b/SJSAssetExportSession.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 7B7AE3092C36615700DB7391 /* SampleWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7AE3082C36615700DB7391 /* SampleWriter.swift */; }; + 7B9867982C6AF57C001353BC /* AVAsset+sending.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */; }; 7B9BC00E2C305D2C00C160C2 /* SJSAssetExportSession.docc in Sources */ = {isa = PBXBuildFile; fileRef = 7B9BC00D2C305D2C00C160C2 /* SJSAssetExportSession.docc */; }; 7B9BC0142C305D2C00C160C2 /* SJSAssetExportSession.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B9BC0092C305D2C00C160C2 /* SJSAssetExportSession.framework */; }; 7B9BC0192C305D2C00C160C2 /* SJSAssetExportSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9BC0182C305D2C00C160C2 /* SJSAssetExportSessionTests.swift */; }; @@ -16,7 +17,6 @@ 7BC5FC772C3B8C5A0090B757 /* SendableWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC762C3B8C5A0090B757 /* SendableWrapper.swift */; }; 7BC5FC792C3B90F70090B757 /* AutoDestructingURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC782C3B90F70090B757 /* AutoDestructingURL.swift */; }; 7BC5FC8A2C3BAA150090B757 /* ExportSession+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC892C3BAA150090B757 /* ExportSession+Error.swift */; }; - 7BC5FC8C2C3BB0180090B757 /* AVAsset+sending.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */; }; 7BC5FC902C3BB2030090B757 /* AudioOutputSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC8F2C3BB2030090B757 /* AudioOutputSettings.swift */; }; 7BC5FC922C3BB4BD0090B757 /* VideoOutputSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC912C3BB4BD0090B757 /* VideoOutputSettings.swift */; }; 7BC5FC942C3BC3AD0090B757 /* CMTime+seconds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC932C3BC3AD0090B757 /* CMTime+seconds.swift */; }; @@ -95,7 +95,6 @@ children = ( 7BC5FC8F2C3BB2030090B757 /* AudioOutputSettings.swift */, 7BC5FC912C3BB4BD0090B757 /* VideoOutputSettings.swift */, - 7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */, 7BC5FC932C3BC3AD0090B757 /* CMTime+seconds.swift */, 7B9BC0272C30612C00C160C2 /* ExportSession.swift */, 7BC5FC892C3BAA150090B757 /* ExportSession+Error.swift */, @@ -110,6 +109,7 @@ isa = PBXGroup; children = ( 7BC5FC782C3B90F70090B757 /* AutoDestructingURL.swift */, + 7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */, 7BC5FC812C3B9E3D0090B757 /* Resources */, 7BC5FC762C3B8C5A0090B757 /* SendableWrapper.swift */, 7B9BC0182C305D2C00C160C2 /* SJSAssetExportSessionTests.swift */, @@ -233,7 +233,6 @@ 7B7AE3092C36615700DB7391 /* SampleWriter.swift in Sources */, 7BC5FC902C3BB2030090B757 /* AudioOutputSettings.swift in Sources */, 7B9BC0282C30612C00C160C2 /* ExportSession.swift in Sources */, - 7BC5FC8C2C3BB0180090B757 /* AVAsset+sending.swift in Sources */, 7BC5FC922C3BB4BD0090B757 /* VideoOutputSettings.swift in Sources */, 7B9BC00E2C305D2C00C160C2 /* SJSAssetExportSession.docc in Sources */, 7BC5FC8A2C3BAA150090B757 /* ExportSession+Error.swift in Sources */, @@ -246,6 +245,7 @@ files = ( 7B9BC0192C305D2C00C160C2 /* SJSAssetExportSessionTests.swift in Sources */, 7BC5FC792C3B90F70090B757 /* AutoDestructingURL.swift in Sources */, + 7B9867982C6AF57C001353BC /* AVAsset+sending.swift in Sources */, 7BC5FC772C3B8C5A0090B757 /* SendableWrapper.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/SJSAssetExportSession/SampleWriter.swift b/SJSAssetExportSession/SampleWriter.swift index 3b816ce..76bd36f 100644 --- a/SJSAssetExportSession/SampleWriter.swift +++ b/SJSAssetExportSession/SampleWriter.swift @@ -45,12 +45,12 @@ actor SampleWriter { private var videoInput: AVAssetWriterInput? private var isCancelled = false - init( + nonisolated init( asset: sending AVAsset, audioOutputSettings: sending [String: (any Sendable)], - audioMix: AVAudioMix?, + audioMix: sending AVAudioMix?, videoOutputSettings: sending [String: (any Sendable)], - videoComposition: AVVideoComposition, + videoComposition: sending AVVideoComposition, timeRange: CMTimeRange? = nil, optimizeForNetworkUse: Bool = false, outputURL: URL, @@ -67,10 +67,14 @@ actor SampleWriter { let writer = try AVAssetWriter(outputURL: outputURL, fileType: fileType) writer.shouldOptimizeForNetworkUse = optimizeForNetworkUse - let audioTracks = try await asset.sendTracks(withMediaType: .audio) - try Self.validateAudio(tracks: audioTracks, outputSettings: audioOutputSettings, writer: writer) - let videoTracks = try await asset.sendTracks(withMediaType: .video) - try Self.validateVideo(tracks: videoTracks, outputSettings: videoOutputSettings, writer: writer) + let audioTracks = try await asset.loadTracks(withMediaType: .audio) + // Audio is optional so only validate output settings when it's applicable. + if !audioTracks.isEmpty { + try Self.validateAudio(outputSettings: audioOutputSettings, writer: writer) + } + let videoTracks = try await asset.loadTracks(withMediaType: .video) + guard !videoTracks.isEmpty else { throw Error.setupFailure(.videoTracksEmpty) } + try Self.validateVideo(outputSettings: videoOutputSettings, writer: writer) Self.warnAboutMismatchedVideoSize( renderSize: videoComposition.renderSize, settings: videoOutputSettings @@ -85,8 +89,8 @@ actor SampleWriter { self.duration = duration self.timeRange = timeRange ?? CMTimeRange(start: .zero, duration: duration) - try setUpAudio(audioTracks: audioTracks) - try setUpVideo(videoTracks: videoTracks) + try await setUpAudio(audioTracks: audioTracks) + try await setUpVideo(videoTracks: videoTracks) } func writeSamples() async throws { @@ -281,11 +285,9 @@ actor SampleWriter { // MARK: Input validation private static func validateAudio( - tracks: [AVAssetTrack], outputSettings: [String: any Sendable], writer: AVAssetWriter ) throws { - guard !tracks.isEmpty else { return } // Audio is optional so this isn't a failure. guard !outputSettings.isEmpty else { throw Error.setupFailure(.audioSettingsEmpty) } guard writer.canApply(outputSettings: outputSettings, forMediaType: .audio) else { throw Error.setupFailure(.audioSettingsInvalid) @@ -293,11 +295,9 @@ actor SampleWriter { } private static func validateVideo( - tracks: [AVAssetTrack], outputSettings: [String: any Sendable], writer: AVAssetWriter ) throws { - guard !tracks.isEmpty else { throw Error.setupFailure(.videoTracksEmpty) } guard writer.canApply(outputSettings: outputSettings, forMediaType: .video) else { throw Error.setupFailure(.videoSettingsInvalid) } diff --git a/SJSAssetExportSession/VideoOutputSettings.swift b/SJSAssetExportSession/VideoOutputSettings.swift index 0864869..d6256ae 100644 --- a/SJSAssetExportSession/VideoOutputSettings.swift +++ b/SJSAssetExportSession/VideoOutputSettings.swift @@ -5,7 +5,7 @@ // Created by Sami Samhuri on 2024-07-07. // -public import AVFoundation +import AVFoundation public struct VideoOutputSettings { public enum H264Profile { diff --git a/SJSAssetExportSession/AVAsset+sending.swift b/SJSAssetExportSessionTests/AVAsset+sending.swift similarity index 90% rename from SJSAssetExportSession/AVAsset+sending.swift rename to SJSAssetExportSessionTests/AVAsset+sending.swift index 4f1def3..af4a601 100644 --- a/SJSAssetExportSession/AVAsset+sending.swift +++ b/SJSAssetExportSessionTests/AVAsset+sending.swift @@ -1,6 +1,6 @@ // // AVAsset+sending.swift -// SJSAssetExportSession +// SJSAssetExportSessionTests // // Created by Sami Samhuri on 2024-07-07. // diff --git a/SJSAssetExportSessionTests/SJSAssetExportSessionTests.swift b/SJSAssetExportSessionTests/SJSAssetExportSessionTests.swift index 3d30e64..19b463a 100644 --- a/SJSAssetExportSessionTests/SJSAssetExportSessionTests.swift +++ b/SJSAssetExportSessionTests/SJSAssetExportSessionTests.swift @@ -5,7 +5,7 @@ // Created by Sami Samhuri on 2024-06-29. // -import AVFoundation +internal import AVFoundation @testable import SJSAssetExportSession import Testing