mirror of
https://github.com/samsonjs/SJSAssetExportSession.git
synced 2026-03-25 08:45:50 +00:00
Add support for writing metadata on the asset
This commit is contained in:
parent
8f049aed95
commit
8e46d79376
3 changed files with 44 additions and 0 deletions
|
|
@ -25,6 +25,7 @@ public final class ExportSession: @unchecked Sendable {
|
|||
public func export(
|
||||
asset: sending AVAsset,
|
||||
optimizeForNetworkUse: Bool = false,
|
||||
metadata: sending [AVMetadataItem] = [],
|
||||
timeRange: CMTimeRange? = nil,
|
||||
audio: sending AudioOutputSettings = .default,
|
||||
video: sending VideoOutputSettings,
|
||||
|
|
@ -42,6 +43,7 @@ public final class ExportSession: @unchecked Sendable {
|
|||
videoComposition: videoComposition,
|
||||
timeRange: timeRange,
|
||||
optimizeForNetworkUse: optimizeForNetworkUse,
|
||||
metadata: metadata,
|
||||
outputURL: outputURL,
|
||||
fileType: fileType
|
||||
)
|
||||
|
|
@ -61,6 +63,8 @@ public final class ExportSession: @unchecked Sendable {
|
|||
|
||||
- optimizeForNetworkUse: Setting this value to `true` writes the output file in a form that enables a player to begin playing the media after downloading only a small portion of it. Defaults to `false`.
|
||||
|
||||
- metadata: Optional array of `AVMetadataItem`s to be written out with the exported asset.
|
||||
|
||||
- timeRange: Providing a time range exports a subset of the asset instead of the entire duration, which is the default behaviour.
|
||||
|
||||
- audioOutputSettings: Audio settings using [audio settings keys from AVFoundation](https://developer.apple.com/documentation/avfoundation/audio_settings) and values must be suitable for consumption by Objective-C. Required keys are:
|
||||
|
|
@ -83,6 +87,7 @@ public final class ExportSession: @unchecked Sendable {
|
|||
public func export(
|
||||
asset: sending AVAsset,
|
||||
optimizeForNetworkUse: Bool = false,
|
||||
metadata: sending [AVMetadataItem] = [],
|
||||
timeRange: CMTimeRange? = nil,
|
||||
audioOutputSettings: [String: (any Sendable)],
|
||||
mix: sending AVAudioMix? = nil,
|
||||
|
|
@ -118,6 +123,7 @@ public final class ExportSession: @unchecked Sendable {
|
|||
videoComposition: videoComposition,
|
||||
timeRange: timeRange,
|
||||
optimizeForNetworkUse: optimizeForNetworkUse,
|
||||
metadata: metadata,
|
||||
outputURL: outputURL,
|
||||
fileType: fileType
|
||||
)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ actor SampleWriter {
|
|||
videoComposition: sending AVVideoComposition,
|
||||
timeRange: CMTimeRange? = nil,
|
||||
optimizeForNetworkUse: Bool = false,
|
||||
metadata: [AVMetadataItem] = [],
|
||||
outputURL: URL,
|
||||
fileType: AVFileType
|
||||
) async throws {
|
||||
|
|
@ -66,6 +67,7 @@ actor SampleWriter {
|
|||
}
|
||||
let writer = try AVAssetWriter(outputURL: outputURL, fileType: fileType)
|
||||
writer.shouldOptimizeForNetworkUse = optimizeForNetworkUse
|
||||
writer.metadata = metadata
|
||||
|
||||
let audioTracks = try await asset.loadTracks(withMediaType: .audio)
|
||||
// Audio is optional so only validate output settings when it's applicable.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
internal import AVFoundation
|
||||
import CoreLocation
|
||||
@testable import SJSAssetExportSession
|
||||
import Testing
|
||||
|
||||
|
|
@ -321,4 +322,39 @@ final class ExportSessionTests {
|
|||
try? await task.value // Wait for task to complete
|
||||
NSLog("Task has finished executing")
|
||||
}
|
||||
|
||||
@Test func test_writing_metadata() async throws {
|
||||
let sourceURL = resourceURL(named: "test-720p-h264-24fps", withExtension: "mov")
|
||||
let destinationURL = makeTemporaryURL()
|
||||
let locationMetadata = AVMutableMetadataItem()
|
||||
locationMetadata.key = AVMetadataKey.commonKeyLocation.rawValue as NSString
|
||||
locationMetadata.keySpace = .common
|
||||
locationMetadata.value = "+48.50176+123.34368/" as NSString
|
||||
|
||||
let subject = ExportSession()
|
||||
try await subject.export(
|
||||
asset: makeAsset(url: sourceURL),
|
||||
metadata: [locationMetadata],
|
||||
video: .codec(.h264, size: CGSize(width: 1280, height: 720)),
|
||||
to: destinationURL.url,
|
||||
as: .mov
|
||||
)
|
||||
|
||||
let exportedAsset = AVURLAsset(url: destinationURL.url)
|
||||
let exportedMetadata = try await exportedAsset.load(.metadata)
|
||||
print(exportedMetadata)
|
||||
#expect(exportedMetadata.count == 1)
|
||||
let metadataValue = try await exportedMetadata.first(where: { item in
|
||||
item.key as! String == AVMetadataKey.quickTimeMetadataKeyLocationISO6709.rawValue
|
||||
})?.load(.value) as? NSString
|
||||
#expect(metadataValue == "+48.50176+123.34368/")
|
||||
|
||||
let exportedCommonMetadata = try await exportedAsset.load(.commonMetadata)
|
||||
print(exportedCommonMetadata)
|
||||
#expect(exportedCommonMetadata.count == 1)
|
||||
let commonMetadataValue = try await exportedCommonMetadata.first(where: { item in
|
||||
item.commonKey == .commonKeyLocation
|
||||
})?.load(.value) as? NSString
|
||||
#expect(commonMetadataValue == "+48.50176+123.34368/")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue