音频文件播放正常但无法添加到 AVMutableVideoComposition
audio file plays fine but can't add in AVMutableVideoComposition
我正在尝试将使用 MPMediaPickerController 选择的音频文件添加到使用 AVMutableVideoComposition 的视频中,但它给出了错误并且不起作用。
像这样挑选音频:
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
if let musicUrl: NSURL = mediaItemCollection.items.first?.assetURL as NSURL? {
musicURL = musicUrl as URL
print("Music URL in did select \(musicUrl) !!!")
}
}
并像这样混合音频和视频:
func testMerge(url: URL) {
let firstVideo = AVAsset(url: url)
var audioAsset = AVAsset(url: musicURL!)
print("Music URL\(musicURL)")
let firstVideoTrack = firstVideo.tracks(withMediaType: AVMediaType.video).first
let mixComposition = AVMutableComposition()
let audioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
let firstTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
do {
try firstTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: firstVideo.duration), of: firstVideoTrack!, at: .zero)
if musicURL.isFileURL {
try audioTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: firstVideo.duration), of: audioAsset.tracks(withMediaType: AVMediaType.audio).first, at: .zero)
}
} catch {
debugPrint("Can't get track from the Video URL!")
}
let mainInstruction = AVMutableVideoCompositionInstruction()
mainInstruction.timeRange = CMTimeRangeMake(start: .zero, duration: firstVideo.duration)
let firstLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: firstTrack!)
let scale = CGAffineTransform(scaleX: 1, y: 1)
firstLayerInstruction.setTransform(scale, at: .zero)
mainInstruction.layerInstructions = [firstLayerInstruction]
let mainCompositionInstruction = AVMutableVideoComposition()
mainCompositionInstruction.instructions = [mainInstruction]
mainCompositionInstruction.frameDuration = CMTimeMake(value: 1, timescale: 30)
mainCompositionInstruction.renderSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
guard let documentDirectory = FileManager.default.urls (
for: .documentDirectory,
in: .userDomainMask).first else { print("ERROR"); return }
let url = documentDirectory.appendingPathComponent("mergeVideo-\(arc4random() % 10000).mp4")
guard let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else {print("ERROR"); return }
assetExport.videoComposition = mainCompositionInstruction
assetExport.outputFileType = .mp4
assetExport.shouldOptimizeForNetworkUse = true
assetExport.outputURL = url
assetExport.exportAsynchronously {
switch assetExport.status {
case AVAssetExportSessionStatus.failed:
print("failed \(String(describing: assetExport.error))")
case AVAssetExportSessionStatus.cancelled:
print("cancelled \(String(describing: assetExport.error))")
case AVAssetExportSessionStatus.completed:
print("Completed")
print(url)
default:
print("unknown")
}
DispatchQueue.main.async {
self.exportDidFinish(assetExport)
}
}
}
如果我用 AVAudioPlayer 播放那个音频然后它正在播放但是如果我添加视频它给出错误 {Error Domain=NSOSStatusErrorDomain Code=-12109 "(null)"}, NSLocalizedFailureReason=The operation此媒体不支持。, NSLocalizedDescription=Operation Stopped}
非常感谢任何帮助或提示,谢谢。
如果我将音频文件添加到项目目录,然后使用包 url 访问它,那么它工作正常,只是不适用于通过 MPMediaPicker 挑选的音频。
这就是我让它工作的方式:
像这样在变量中将其存储为 AVPlayerItem
var playerItem: AVPlayerItem!
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
if let musicUrl: NSURL = mediaItemCollection.items.first?.assetURL as NSURL? {
musicURL = musicUrl as URL
print("Music URL in did select \(musicUrl) !!!")
}
playerItem = AVPlayerItem(url: musicURL)
}
然后在 mergeVideo 函数中访问它的轨道是这样的
do {
try firstTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: durationTrack.duration), of: firstVideoTrack!, at: .zero)
try secondTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: durationTrack.duration), of: secondVideoTrack!, at: .zero)
if playerItem != nil {
let sourceAudio = playerItem.asset.tracks(withMediaType: .audio).first
let audioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
try audioTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: durationTrack.duration), of: sourceAudio!, at: .zero)
}
} catch {
debugPrint("Can't get track from the Video URL!")
}
我正在尝试将使用 MPMediaPickerController 选择的音频文件添加到使用 AVMutableVideoComposition 的视频中,但它给出了错误并且不起作用。
像这样挑选音频:
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
if let musicUrl: NSURL = mediaItemCollection.items.first?.assetURL as NSURL? {
musicURL = musicUrl as URL
print("Music URL in did select \(musicUrl) !!!")
}
}
并像这样混合音频和视频:
func testMerge(url: URL) {
let firstVideo = AVAsset(url: url)
var audioAsset = AVAsset(url: musicURL!)
print("Music URL\(musicURL)")
let firstVideoTrack = firstVideo.tracks(withMediaType: AVMediaType.video).first
let mixComposition = AVMutableComposition()
let audioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
let firstTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
do {
try firstTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: firstVideo.duration), of: firstVideoTrack!, at: .zero)
if musicURL.isFileURL {
try audioTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: firstVideo.duration), of: audioAsset.tracks(withMediaType: AVMediaType.audio).first, at: .zero)
}
} catch {
debugPrint("Can't get track from the Video URL!")
}
let mainInstruction = AVMutableVideoCompositionInstruction()
mainInstruction.timeRange = CMTimeRangeMake(start: .zero, duration: firstVideo.duration)
let firstLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: firstTrack!)
let scale = CGAffineTransform(scaleX: 1, y: 1)
firstLayerInstruction.setTransform(scale, at: .zero)
mainInstruction.layerInstructions = [firstLayerInstruction]
let mainCompositionInstruction = AVMutableVideoComposition()
mainCompositionInstruction.instructions = [mainInstruction]
mainCompositionInstruction.frameDuration = CMTimeMake(value: 1, timescale: 30)
mainCompositionInstruction.renderSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
guard let documentDirectory = FileManager.default.urls (
for: .documentDirectory,
in: .userDomainMask).first else { print("ERROR"); return }
let url = documentDirectory.appendingPathComponent("mergeVideo-\(arc4random() % 10000).mp4")
guard let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else {print("ERROR"); return }
assetExport.videoComposition = mainCompositionInstruction
assetExport.outputFileType = .mp4
assetExport.shouldOptimizeForNetworkUse = true
assetExport.outputURL = url
assetExport.exportAsynchronously {
switch assetExport.status {
case AVAssetExportSessionStatus.failed:
print("failed \(String(describing: assetExport.error))")
case AVAssetExportSessionStatus.cancelled:
print("cancelled \(String(describing: assetExport.error))")
case AVAssetExportSessionStatus.completed:
print("Completed")
print(url)
default:
print("unknown")
}
DispatchQueue.main.async {
self.exportDidFinish(assetExport)
}
}
}
如果我用 AVAudioPlayer 播放那个音频然后它正在播放但是如果我添加视频它给出错误 {Error Domain=NSOSStatusErrorDomain Code=-12109 "(null)"}, NSLocalizedFailureReason=The operation此媒体不支持。, NSLocalizedDescription=Operation Stopped}
非常感谢任何帮助或提示,谢谢。
如果我将音频文件添加到项目目录,然后使用包 url 访问它,那么它工作正常,只是不适用于通过 MPMediaPicker 挑选的音频。
这就是我让它工作的方式:
像这样在变量中将其存储为 AVPlayerItem
var playerItem: AVPlayerItem!
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
if let musicUrl: NSURL = mediaItemCollection.items.first?.assetURL as NSURL? {
musicURL = musicUrl as URL
print("Music URL in did select \(musicUrl) !!!")
}
playerItem = AVPlayerItem(url: musicURL)
}
然后在 mergeVideo 函数中访问它的轨道是这样的
do {
try firstTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: durationTrack.duration), of: firstVideoTrack!, at: .zero)
try secondTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: durationTrack.duration), of: secondVideoTrack!, at: .zero)
if playerItem != nil {
let sourceAudio = playerItem.asset.tracks(withMediaType: .audio).first
let audioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
try audioTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: durationTrack.duration), of: sourceAudio!, at: .zero)
}
} catch {
debugPrint("Can't get track from the Video URL!")
}