SJSAssetExportSession
是 AVAssetExportSession
的替代方案,它允许您提供自定义的音频和视频设置,而无需深入到 AVAssetReader
和 AVAssetWriter
的世界中。它具有类似于 SDAVAssetExportSession 的功能,但 API 完全不同,代码是用 Swift 编写的,并且已为严格的并发世界做好准备。
您不必通读 音频设置 和 视频设置 仅仅为了设置比特率,并且设置帧速率可能很棘手,因此这里提供了一个更友好的 API,它使用一些常用的设置来构建这些设置字典。
安装此软件包的唯一方法是使用 Swift Package Manager (SPM)。如果您想使用其他方法,请提交新 issue 或提交 pull 请求。
此软件包支持 iOS 17.0+、macOS Sonoma 14.0+ 和 visionOS 1.3+。
当您将此软件包集成到 Xcode 中的应用程序时,请转到您项目的“Package Dependencies”(软件包依赖项),然后输入 URL https://github.com/samsonjs/SJSAssetExportSession
,然后按照通常的流程添加软件包。
当您单独使用 SPM 集成此软件包时,请将其添加到您的 Package.swift 文件中的依赖项列表中
.package(url: "https://github.com/samsonjs/SJSAssetExportSession.git", .upToNextMajor(from: "0.3.7"))
然后将 "SJSAssetExportSession"
也添加到您的目标中的依赖项列表中。
导出 asset 有两种方法:一种是像使用 SDAVAssetExportSession
一样使用字典进行音频和视频设置,另一种是使用类似构建器的 API 以及用于常用设置的数据结构。
这应该是相当不言自明的
let sourceURL = URL.documentsDirectory.appending(component: "some-video.mov")
let sourceAsset = AVURLAsset(url: sourceURL, options: [
AVURLAssetPreferPreciseDurationAndTimingKey: true,
])
let destinationURL = URL.temporaryDirectory.appending(component: "shiny-new-video.mp4")
let exporter = ExportSession()
Task {
for await progress in exporter.progressStream {
print("Export progress: \(progress)")
}
}
try await exporter.export(
asset: sourceAsset,
video: .codec(.h264, width: 1280, height: 720),
to: destinationURL,
as: .mp4
)
大多数音频和视频配置是可选的,这就是为什么这里没有指定音频设置的原因。默认情况下,您将获得 AAC,具有 2 个声道,采样率为 44.1 KHz。
以下是您可以传递到友好导出方法中的所有参数
let sourceURL = URL.documentsDirectory.appending(component: "some-video.mov")
let sourceAsset = AVURLAsset(url: sourceURL, options: [
AVURLAssetPreferPreciseDurationAndTimingKey: true,
])
let destinationURL = URL.temporaryDirectory.appending(component: "shiny-new-video.mp4")
let exporter = ExportSession()
Task {
for await progress in exporter.progressStream {
print("Export progress: \(progress)")
}
}
let locationMetadata = AVMutableMetadataItem()
locationMetadata.key = AVMetadataKey.commonKeyLocation.rawValue as NSString
locationMetadata.keySpace = .common
locationMetadata.value = "+48.50176+123.34368/" as NSString
try await exporter.export(
asset: sourceAsset,
optimizeForNetworkUse: true,
metadata: [locationMetadata],
timeRange: CMTimeRange(start: .zero, duration: .seconds(1)),
audio: .format(.mp3).channels(1).sampleRate(22_050),
video: .codec(.h264, width: 1280, height: 720)
.fps(24)
.bitrate(1_000_000)
.color(.sdr),
to: destinationURL,
as: .mp4
)
当您需要所有控制权时,您可以深入到细节中。此代码与上面的代码执行完全相同的操作
let sourceURL = URL.documentsDirectory.appending(component: "some-video.mov")
let sourceAsset = AVURLAsset(url: sourceURL, options: [
AVURLAssetPreferPreciseDurationAndTimingKey: true,
])
let destinationURL = URL.temporaryDirectory.appending(component: "shiny-new-video.mp4")
let exporter = ExportSession()
Task {
for await progress in exporter.progressStream {
print("Export progress: \(progress)")
}
}
let locationMetadata = AVMutableMetadataItem()
locationMetadata.key = AVMetadataKey.commonKeyLocation.rawValue as NSString
locationMetadata.keySpace = .common
locationMetadata.value = "+48.50176+123.34368/" as NSString
let videoComposition = try await AVMutableVideoComposition.videoComposition(withPropertiesOf: sourceAsset)
videoComposition.renderSize = CGSize(width: 1280, height: 720)
videoComposition.sourceTrackIDForFrameTiming = kCMPersistentTrackID_Invalid
videoComposition.frameDuration = CMTime(value: 600 / 24, timescale: 600) // 24 fps
videoComposition.colorPrimaries = AVVideoColorPrimaries_ITU_R_709_2
videoComposition.colorTransferFunction = AVVideoTransferFunction_ITU_R_709_2
videoComposition.colorYCbCrMatrix = AVVideoYCbCrMatrix_ITU_R_709_2
try await exporter.export(
asset: sourceAsset,
optimizeForNetworkUse: true,
metadata: [locationMetadata],
timeRange: CMTimeRange(start: .zero, duration: .seconds(1)),
audioOutputSettings: [
AVFormatIDKey: kAudioFormatMPEGLayer3,
AVNumberOfChannelsKey: NSNumber(value: 1),
AVSampleRateKey: NSNumber(value: 22_050),
],
videoOutputSettings: [
AVVideoCodecKey: AVVideoCodecType.h264.rawValue,
AVVideoCompressionPropertiesKey: [
AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel,
AVVideoAverageBitRateKey: NSNumber(value: 1_000_000),
] as [String: any Sendable],
AVVideoColorPropertiesKey: [
AVVideoColorPrimariesKey: AVVideoColorPrimaries_ITU_R_709_2,
AVVideoTransferFunctionKey: AVVideoTransferFunction_ITU_R_709_2,
AVVideoYCbCrMatrixKey: AVVideoYCbCrMatrix_ITU_R_709_2,
],
],
composition: videoComposition,
to: destinationURL,
as: .mp4
)
这有效地说明了为什么需要更友好的 API,对吧?但是当您需要这种灵活性时,它也为您提供。
AudioOutputSettings
和 VideoOutputSettings
都有一个名为 settingsDictionary
的属性,您可以使用它来引导您自己的自定义设置。
let sourceURL = URL.documentsDirectory.appending(component: "some-video.mov")
let sourceAsset = AVURLAsset(url: sourceURL, options: [
AVURLAssetPreferPreciseDurationAndTimingKey: true,
])
let destinationURL = URL.temporaryDirectory.appending(component: "shiny-new-video.mp4")
let exporter = ExportSession()
Task {
for await progress in exporter.progressStream {
print("Export progress: \(progress)")
}
}
var audioSettings = AudioOutputSettings.default.settingsDictionary
audioSettings[AVVideoAverageBitRateKey] = 65_536
let videoSettings = VideoOutputSettings
.codec(.hevc, width: 1280, height: 720)
.settingsDictionary
try await exporter.export(
asset: sourceAsset,
audioOutputSettings: audioSettings,
videoOutputSettings: videoSettings,
to: destinationURL,
as: .mp4
)
版权所有 © 2024 Sami Samhuri sami@samhuri.net。根据 MIT 许可证 的条款发布。