mirror of
https://github.com/samsonjs/SJSAssetExportSession.git
synced 2026-04-27 14:57:46 +00:00
Make SampleWriter.init nonisolated so it can load tracks
This commit is contained in:
parent
996251cfde
commit
8f049aed95
5 changed files with 19 additions and 19 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
7B7AE3092C36615700DB7391 /* SampleWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7AE3082C36615700DB7391 /* SampleWriter.swift */; };
|
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 */; };
|
7B9BC00E2C305D2C00C160C2 /* SJSAssetExportSession.docc in Sources */ = {isa = PBXBuildFile; fileRef = 7B9BC00D2C305D2C00C160C2 /* SJSAssetExportSession.docc */; };
|
||||||
7B9BC0142C305D2C00C160C2 /* SJSAssetExportSession.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B9BC0092C305D2C00C160C2 /* SJSAssetExportSession.framework */; };
|
7B9BC0142C305D2C00C160C2 /* SJSAssetExportSession.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B9BC0092C305D2C00C160C2 /* SJSAssetExportSession.framework */; };
|
||||||
7B9BC0192C305D2C00C160C2 /* SJSAssetExportSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9BC0182C305D2C00C160C2 /* SJSAssetExportSessionTests.swift */; };
|
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 */; };
|
7BC5FC772C3B8C5A0090B757 /* SendableWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC762C3B8C5A0090B757 /* SendableWrapper.swift */; };
|
||||||
7BC5FC792C3B90F70090B757 /* AutoDestructingURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC782C3B90F70090B757 /* AutoDestructingURL.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 */; };
|
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 */; };
|
7BC5FC902C3BB2030090B757 /* AudioOutputSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC8F2C3BB2030090B757 /* AudioOutputSettings.swift */; };
|
||||||
7BC5FC922C3BB4BD0090B757 /* VideoOutputSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC912C3BB4BD0090B757 /* VideoOutputSettings.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 */; };
|
7BC5FC942C3BC3AD0090B757 /* CMTime+seconds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC932C3BC3AD0090B757 /* CMTime+seconds.swift */; };
|
||||||
|
|
@ -95,7 +95,6 @@
|
||||||
children = (
|
children = (
|
||||||
7BC5FC8F2C3BB2030090B757 /* AudioOutputSettings.swift */,
|
7BC5FC8F2C3BB2030090B757 /* AudioOutputSettings.swift */,
|
||||||
7BC5FC912C3BB4BD0090B757 /* VideoOutputSettings.swift */,
|
7BC5FC912C3BB4BD0090B757 /* VideoOutputSettings.swift */,
|
||||||
7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */,
|
|
||||||
7BC5FC932C3BC3AD0090B757 /* CMTime+seconds.swift */,
|
7BC5FC932C3BC3AD0090B757 /* CMTime+seconds.swift */,
|
||||||
7B9BC0272C30612C00C160C2 /* ExportSession.swift */,
|
7B9BC0272C30612C00C160C2 /* ExportSession.swift */,
|
||||||
7BC5FC892C3BAA150090B757 /* ExportSession+Error.swift */,
|
7BC5FC892C3BAA150090B757 /* ExportSession+Error.swift */,
|
||||||
|
|
@ -110,6 +109,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7BC5FC782C3B90F70090B757 /* AutoDestructingURL.swift */,
|
7BC5FC782C3B90F70090B757 /* AutoDestructingURL.swift */,
|
||||||
|
7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */,
|
||||||
7BC5FC812C3B9E3D0090B757 /* Resources */,
|
7BC5FC812C3B9E3D0090B757 /* Resources */,
|
||||||
7BC5FC762C3B8C5A0090B757 /* SendableWrapper.swift */,
|
7BC5FC762C3B8C5A0090B757 /* SendableWrapper.swift */,
|
||||||
7B9BC0182C305D2C00C160C2 /* SJSAssetExportSessionTests.swift */,
|
7B9BC0182C305D2C00C160C2 /* SJSAssetExportSessionTests.swift */,
|
||||||
|
|
@ -233,7 +233,6 @@
|
||||||
7B7AE3092C36615700DB7391 /* SampleWriter.swift in Sources */,
|
7B7AE3092C36615700DB7391 /* SampleWriter.swift in Sources */,
|
||||||
7BC5FC902C3BB2030090B757 /* AudioOutputSettings.swift in Sources */,
|
7BC5FC902C3BB2030090B757 /* AudioOutputSettings.swift in Sources */,
|
||||||
7B9BC0282C30612C00C160C2 /* ExportSession.swift in Sources */,
|
7B9BC0282C30612C00C160C2 /* ExportSession.swift in Sources */,
|
||||||
7BC5FC8C2C3BB0180090B757 /* AVAsset+sending.swift in Sources */,
|
|
||||||
7BC5FC922C3BB4BD0090B757 /* VideoOutputSettings.swift in Sources */,
|
7BC5FC922C3BB4BD0090B757 /* VideoOutputSettings.swift in Sources */,
|
||||||
7B9BC00E2C305D2C00C160C2 /* SJSAssetExportSession.docc in Sources */,
|
7B9BC00E2C305D2C00C160C2 /* SJSAssetExportSession.docc in Sources */,
|
||||||
7BC5FC8A2C3BAA150090B757 /* ExportSession+Error.swift in Sources */,
|
7BC5FC8A2C3BAA150090B757 /* ExportSession+Error.swift in Sources */,
|
||||||
|
|
@ -246,6 +245,7 @@
|
||||||
files = (
|
files = (
|
||||||
7B9BC0192C305D2C00C160C2 /* SJSAssetExportSessionTests.swift in Sources */,
|
7B9BC0192C305D2C00C160C2 /* SJSAssetExportSessionTests.swift in Sources */,
|
||||||
7BC5FC792C3B90F70090B757 /* AutoDestructingURL.swift in Sources */,
|
7BC5FC792C3B90F70090B757 /* AutoDestructingURL.swift in Sources */,
|
||||||
|
7B9867982C6AF57C001353BC /* AVAsset+sending.swift in Sources */,
|
||||||
7BC5FC772C3B8C5A0090B757 /* SendableWrapper.swift in Sources */,
|
7BC5FC772C3B8C5A0090B757 /* SendableWrapper.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,12 @@ actor SampleWriter {
|
||||||
private var videoInput: AVAssetWriterInput?
|
private var videoInput: AVAssetWriterInput?
|
||||||
private var isCancelled = false
|
private var isCancelled = false
|
||||||
|
|
||||||
init(
|
nonisolated init(
|
||||||
asset: sending AVAsset,
|
asset: sending AVAsset,
|
||||||
audioOutputSettings: sending [String: (any Sendable)],
|
audioOutputSettings: sending [String: (any Sendable)],
|
||||||
audioMix: AVAudioMix?,
|
audioMix: sending AVAudioMix?,
|
||||||
videoOutputSettings: sending [String: (any Sendable)],
|
videoOutputSettings: sending [String: (any Sendable)],
|
||||||
videoComposition: AVVideoComposition,
|
videoComposition: sending AVVideoComposition,
|
||||||
timeRange: CMTimeRange? = nil,
|
timeRange: CMTimeRange? = nil,
|
||||||
optimizeForNetworkUse: Bool = false,
|
optimizeForNetworkUse: Bool = false,
|
||||||
outputURL: URL,
|
outputURL: URL,
|
||||||
|
|
@ -67,10 +67,14 @@ actor SampleWriter {
|
||||||
let writer = try AVAssetWriter(outputURL: outputURL, fileType: fileType)
|
let writer = try AVAssetWriter(outputURL: outputURL, fileType: fileType)
|
||||||
writer.shouldOptimizeForNetworkUse = optimizeForNetworkUse
|
writer.shouldOptimizeForNetworkUse = optimizeForNetworkUse
|
||||||
|
|
||||||
let audioTracks = try await asset.sendTracks(withMediaType: .audio)
|
let audioTracks = try await asset.loadTracks(withMediaType: .audio)
|
||||||
try Self.validateAudio(tracks: audioTracks, outputSettings: audioOutputSettings, writer: writer)
|
// Audio is optional so only validate output settings when it's applicable.
|
||||||
let videoTracks = try await asset.sendTracks(withMediaType: .video)
|
if !audioTracks.isEmpty {
|
||||||
try Self.validateVideo(tracks: videoTracks, outputSettings: videoOutputSettings, writer: writer)
|
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(
|
Self.warnAboutMismatchedVideoSize(
|
||||||
renderSize: videoComposition.renderSize,
|
renderSize: videoComposition.renderSize,
|
||||||
settings: videoOutputSettings
|
settings: videoOutputSettings
|
||||||
|
|
@ -85,8 +89,8 @@ actor SampleWriter {
|
||||||
self.duration = duration
|
self.duration = duration
|
||||||
self.timeRange = timeRange ?? CMTimeRange(start: .zero, duration: duration)
|
self.timeRange = timeRange ?? CMTimeRange(start: .zero, duration: duration)
|
||||||
|
|
||||||
try setUpAudio(audioTracks: audioTracks)
|
try await setUpAudio(audioTracks: audioTracks)
|
||||||
try setUpVideo(videoTracks: videoTracks)
|
try await setUpVideo(videoTracks: videoTracks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeSamples() async throws {
|
func writeSamples() async throws {
|
||||||
|
|
@ -281,11 +285,9 @@ actor SampleWriter {
|
||||||
// MARK: Input validation
|
// MARK: Input validation
|
||||||
|
|
||||||
private static func validateAudio(
|
private static func validateAudio(
|
||||||
tracks: [AVAssetTrack],
|
|
||||||
outputSettings: [String: any Sendable],
|
outputSettings: [String: any Sendable],
|
||||||
writer: AVAssetWriter
|
writer: AVAssetWriter
|
||||||
) throws {
|
) throws {
|
||||||
guard !tracks.isEmpty else { return } // Audio is optional so this isn't a failure.
|
|
||||||
guard !outputSettings.isEmpty else { throw Error.setupFailure(.audioSettingsEmpty) }
|
guard !outputSettings.isEmpty else { throw Error.setupFailure(.audioSettingsEmpty) }
|
||||||
guard writer.canApply(outputSettings: outputSettings, forMediaType: .audio) else {
|
guard writer.canApply(outputSettings: outputSettings, forMediaType: .audio) else {
|
||||||
throw Error.setupFailure(.audioSettingsInvalid)
|
throw Error.setupFailure(.audioSettingsInvalid)
|
||||||
|
|
@ -293,11 +295,9 @@ actor SampleWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func validateVideo(
|
private static func validateVideo(
|
||||||
tracks: [AVAssetTrack],
|
|
||||||
outputSettings: [String: any Sendable],
|
outputSettings: [String: any Sendable],
|
||||||
writer: AVAssetWriter
|
writer: AVAssetWriter
|
||||||
) throws {
|
) throws {
|
||||||
guard !tracks.isEmpty else { throw Error.setupFailure(.videoTracksEmpty) }
|
|
||||||
guard writer.canApply(outputSettings: outputSettings, forMediaType: .video) else {
|
guard writer.canApply(outputSettings: outputSettings, forMediaType: .video) else {
|
||||||
throw Error.setupFailure(.videoSettingsInvalid)
|
throw Error.setupFailure(.videoSettingsInvalid)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// Created by Sami Samhuri on 2024-07-07.
|
// Created by Sami Samhuri on 2024-07-07.
|
||||||
//
|
//
|
||||||
|
|
||||||
public import AVFoundation
|
import AVFoundation
|
||||||
|
|
||||||
public struct VideoOutputSettings {
|
public struct VideoOutputSettings {
|
||||||
public enum H264Profile {
|
public enum H264Profile {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
//
|
||||||
// AVAsset+sending.swift
|
// AVAsset+sending.swift
|
||||||
// SJSAssetExportSession
|
// SJSAssetExportSessionTests
|
||||||
//
|
//
|
||||||
// Created by Sami Samhuri on 2024-07-07.
|
// Created by Sami Samhuri on 2024-07-07.
|
||||||
//
|
//
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// Created by Sami Samhuri on 2024-06-29.
|
// Created by Sami Samhuri on 2024-06-29.
|
||||||
//
|
//
|
||||||
|
|
||||||
import AVFoundation
|
internal import AVFoundation
|
||||||
@testable import SJSAssetExportSession
|
@testable import SJSAssetExportSession
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue