Inline all setup code in SampleWriter initializer

It seems like a bug that only one of these warns and when swapping
the order, whichever is first warns, it's just that both must be
present to trigger a warning which is the buggy part.

Anyway since it seems like a legit error, inline all the code so
things should work fine.
This commit is contained in:
Sami Samhuri 2025-10-30 19:06:45 -07:00
parent 93806c5ed0
commit 9c9e24d2bc
No known key found for this signature in database

View file

@ -68,9 +68,22 @@ actor SampleWriter {
if let timeRange {
reader.timeRange = timeRange
}
self.reader = reader
let writer = try AVAssetWriter(outputURL: outputURL, fileType: fileType)
writer.shouldOptimizeForNetworkUse = optimizeForNetworkUse
writer.metadata = metadata
self.writer = writer
self.audioOutputSettings = audioOutputSettings
self.audioMix = audioMix
self.videoOutputSettings = videoOutputSettings
self.videoComposition = videoComposition
self.timeRange = if let timeRange {
timeRange
} else {
try await CMTimeRange(start: .zero, duration: asset.load(.duration))
}
// Filter out disabled tracks to avoid problems encoding spatial audio. Ideally this would
// preserve track groups and make that all configurable.
@ -79,30 +92,6 @@ actor SampleWriter {
// 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)
.filterAsync { try await $0.load(.isEnabled) }
guard !videoTracks.isEmpty else { throw Error.setupFailure(.videoTracksEmpty) }
try Self.validateVideo(outputSettings: videoOutputSettings, writer: writer)
Self.warnAboutMismatchedVideoSize(
renderSize: videoComposition.renderSize,
settings: videoOutputSettings
)
self.audioOutputSettings = audioOutputSettings
self.audioMix = audioMix
self.videoOutputSettings = videoOutputSettings
self.videoComposition = videoComposition
self.reader = reader
self.writer = writer
self.timeRange = if let timeRange {
timeRange
} else {
try await CMTimeRange(start: .zero, duration: asset.load(.duration))
}
// This used to be a separate method but that doesn't build in Xcode 26.0 RC
if !audioTracks.isEmpty {
let audioOutput = AVAssetReaderAudioMixOutput(audioTracks: audioTracks, audioSettings: nil)
audioOutput.alwaysCopiesSampleData = false
audioOutput.audioMix = audioMix
@ -121,7 +110,33 @@ actor SampleWriter {
self.audioInput = audioInput
}
try await setUpVideo(videoTracks: videoTracks)
let videoTracks = try await asset.loadTracks(withMediaType: .video)
.filterAsync { try await $0.load(.isEnabled) }
guard !videoTracks.isEmpty else { throw Error.setupFailure(.videoTracksEmpty) }
try Self.validateVideo(outputSettings: videoOutputSettings, writer: writer)
Self.warnAboutMismatchedVideoSize(
renderSize: videoComposition.renderSize,
settings: videoOutputSettings
)
let videoOutput = AVAssetReaderVideoCompositionOutput(
videoTracks: videoTracks,
videoSettings: nil
)
videoOutput.alwaysCopiesSampleData = false
videoOutput.videoComposition = videoComposition
guard reader.canAdd(videoOutput) else {
throw Error.setupFailure(.cannotAddVideoOutput)
}
reader.add(videoOutput)
self.videoOutput = videoOutput
let videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoOutputSettings)
videoInput.expectsMediaDataInRealTime = false
guard writer.canAdd(videoInput) else {
throw Error.setupFailure(.cannotAddVideoInput)
}
writer.add(videoInput)
self.videoInput = videoInput
}
func writeSamples() async throws {
@ -184,32 +199,6 @@ actor SampleWriter {
}
}
// MARK: - Setup
private func setUpVideo(videoTracks: [AVAssetTrack]) throws {
precondition(!videoTracks.isEmpty, "Video tracks must be provided")
let videoOutput = AVAssetReaderVideoCompositionOutput(
videoTracks: videoTracks,
videoSettings: nil
)
videoOutput.alwaysCopiesSampleData = false
videoOutput.videoComposition = videoComposition
guard let reader, reader.canAdd(videoOutput) else {
throw Error.setupFailure(.cannotAddVideoOutput)
}
reader.add(videoOutput)
self.videoOutput = videoOutput
let videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoOutputSettings)
videoInput.expectsMediaDataInRealTime = false
guard let writer, writer.canAdd(videoInput) else {
throw Error.setupFailure(.cannotAddVideoInput)
}
writer.add(videoInput)
self.videoInput = videoInput
}
// MARK: - Encoding
private func startEncodingAudioTracks() {