SJSAssetExportSession

0 dependencies!

概述

SJSAssetExportSessionAVAssetExportSession 的替代方案,它允许您提供自定义的音频和视频设置,而无需深入到 AVAssetReaderAVAssetWriter 的世界中。它具有类似于 SDAVAssetExportSession 的功能,但 API 完全不同,代码是用 Swift 编写的,并且已为严格的并发世界做好准备。

您不必通读 音频设置视频设置 仅仅为了设置比特率,并且设置帧速率可能很棘手,因此这里提供了一个更友好的 API,它使用一些常用的设置来构建这些设置字典。

安装

安装此软件包的唯一方法是使用 Swift Package Manager (SPM)。如果您想使用其他方法,请提交新 issue 或提交 pull 请求。

支持的平台

此软件包支持 iOS 17.0+、macOS Sonoma 14.0+ 和 visionOS 1.3+。

Xcode

当您将此软件包集成到 Xcode 中的应用程序时,请转到您项目的“Package Dependencies”(软件包依赖项),然后输入 URL https://github.com/samsonjs/SJSAssetExportSession,然后按照通常的流程添加软件包。

Swift Package Manager (SPM)

当您单独使用 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,对吧?但是当您需要这种灵活性时,它也为您提供。

混合搭配

AudioOutputSettingsVideoOutputSettings 都有一个名为 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 许可证 的条款发布。