optimize the appicon of iOS

This commit is contained in:
2026-08-26 17:14:59 +08:00
parent 76b0332035
commit bb677ea8cf
11 changed files with 406 additions and 11 deletions

View File

@@ -0,0 +1,62 @@
import AVFoundation
import Foundation
enum DubbingCompositorError: LocalizedError {
case noAudioTracks
case cannotReadDuration
var errorDescription: String? {
switch self {
case .noAudioTracks:
return "录音没有音频轨道"
case .cannotReadDuration:
return "无法读取录音时长"
}
}
}
enum DubbingCompositor {
static func merge(urls: [URL], outputURL: URL) async throws {
try await mergeSync(urls: urls, outputURL: outputURL)
}
private static func mergeSync(urls: [URL], outputURL: URL) async throws {
try? FileManager.default.removeItem(at: outputURL)
let composition = AVMutableComposition()
var currentTime = CMTime.zero
for url in urls {
let source = AVURLAsset(url: url)
let tracks = try await source.loadTracks(withMediaType: .audio)
guard let track = tracks.first else {
throw DubbingCompositorError.noAudioTracks
}
let duration = try await source.load(.duration)
guard duration.seconds.isFinite, duration.seconds > 0 else {
throw DubbingCompositorError.cannotReadDuration
}
let timeRange = CMTimeRange(start: .zero, duration: duration)
let compositionTrack = composition.addMutableTrack(
withMediaType: .audio,
preferredTrackID: kCMPersistentTrackID_Invalid
)
guard let compositionTrack else {
throw DubbingCompositorError.noAudioTracks
}
try compositionTrack.insertTimeRange(timeRange, of: track, at: currentTime)
currentTime = currentTime + duration
}
guard let exporter = AVAssetExportSession(
asset: composition,
presetName: AVAssetExportPresetAppleM4A
) else {
throw DubbingCompositorError.noAudioTracks
}
exporter.outputURL = outputURL
exporter.outputFileType = .m4a
await exporter.export()
guard exporter.status == .completed else {
throw exporter.error ?? DubbingCompositorError.noAudioTracks
}
}
}