完成app内视频拍摄完毕后的声音合成功能
This commit is contained in:
parent
40b5d1d7c5
commit
dc2fb63193
@ -30,9 +30,14 @@ class SpatialVideoWriter {
|
||||
let leftEyeAsset = AVURLAsset(url: leftEyeVideoURL)
|
||||
let rightEyeAsset = AVURLAsset(url: rightEyeVideoURL)
|
||||
|
||||
let assetWriter = try AVAssetWriter(outputURL: outputVideoURL, fileType: .mov)
|
||||
|
||||
|
||||
let leftVideoTrack = leftEyeAsset.tracks(withMediaType: .video).first!
|
||||
let rightVideoTrack = rightEyeAsset.tracks(withMediaType: .video).first!
|
||||
let letAudioTrack = leftEyeAsset.tracks(withMediaType: .audio).first!
|
||||
|
||||
// 创建视频输入
|
||||
let assetWriter = try AVAssetWriter(outputURL: outputVideoURL, fileType: .mov)
|
||||
let videoSettings: [String: Any] = [
|
||||
AVVideoWidthKey: leftVideoTrack.naturalSize.width,
|
||||
AVVideoHeightKey: leftVideoTrack.naturalSize.height,
|
||||
@ -43,13 +48,40 @@ class SpatialVideoWriter {
|
||||
kVTCompressionPropertyKey_HorizontalDisparityAdjustment: 200, // asset-specific
|
||||
]
|
||||
]
|
||||
let input = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings)
|
||||
assetWriter.add(input)
|
||||
let input_video = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings)
|
||||
input_video.expectsMediaDataInRealTime = true
|
||||
let adaptor_inputVideo = AVAssetWriterInputTaggedPixelBufferGroupAdaptor(assetWriterInput: input_video)
|
||||
assetWriter.add(input_video)
|
||||
|
||||
let adaptor = AVAssetWriterInputTaggedPixelBufferGroupAdaptor(assetWriterInput: input)
|
||||
|
||||
// 创建音频输入
|
||||
let inputSettings_Audio = [
|
||||
AVFormatIDKey: kAudioFormatLinearPCM, // 指定未压缩格式
|
||||
AVSampleRateKey: 44100,
|
||||
AVNumberOfChannelsKey: 2,
|
||||
AVLinearPCMIsBigEndianKey:true,
|
||||
AVLinearPCMIsFloatKey:true,
|
||||
AVLinearPCMBitDepthKey:32,
|
||||
AVLinearPCMIsNonInterleaved:false,
|
||||
] as [String:Any]
|
||||
|
||||
|
||||
let writerInput_Audio_left = AVAssetWriterInput.init(mediaType: .audio, outputSettings: inputSettings_Audio)
|
||||
|
||||
writerInput_Audio_left.expectsMediaDataInRealTime = false
|
||||
if assetWriter.canAdd(writerInput_Audio_left) {
|
||||
assetWriter.add(writerInput_Audio_left)
|
||||
print("assetWriter 添加writerInput_Audio_left成功...")
|
||||
}
|
||||
else {
|
||||
print("assetWriter 添加writerInput_Audio_left失败...")
|
||||
}
|
||||
|
||||
assetWriter.startWriting()
|
||||
assetWriter.startSession(atSourceTime: .zero)
|
||||
|
||||
|
||||
//创建视频读取
|
||||
let leftEyeReader = try AVAssetReader(asset: leftEyeAsset)
|
||||
let rightEyeReader = try AVAssetReader(asset: rightEyeAsset)
|
||||
|
||||
@ -60,13 +92,38 @@ class SpatialVideoWriter {
|
||||
]
|
||||
|
||||
let leftEyeOutput = AVAssetReaderTrackOutput(track: leftVideoTrack, outputSettings: readerOutputSettings)
|
||||
let rightEyeOutput = AVAssetReaderTrackOutput(track: rightEyeAsset.tracks(withMediaType: .video).first!, outputSettings: readerOutputSettings)
|
||||
let rightEyeOutput = AVAssetReaderTrackOutput(track:rightVideoTrack , outputSettings: readerOutputSettings)
|
||||
|
||||
leftEyeReader.add(leftEyeOutput)
|
||||
rightEyeReader.add(rightEyeOutput)
|
||||
|
||||
//加载音频轨道读取 从左眼视频读取
|
||||
let outputSettings_Audio = [
|
||||
AVFormatIDKey: kAudioFormatLinearPCM, // 指定未压缩格式
|
||||
AVSampleRateKey: 44100,
|
||||
AVNumberOfChannelsKey: 2,
|
||||
]
|
||||
//
|
||||
|
||||
|
||||
let output_audio_left = AVAssetReaderTrackOutput(
|
||||
track: letAudioTrack,
|
||||
outputSettings:outputSettings_Audio
|
||||
)
|
||||
|
||||
if leftEyeReader.canAdd(output_audio_left){
|
||||
leftEyeReader.add(output_audio_left)
|
||||
print("output_audio_left添加音频read output成功。。。。")
|
||||
}
|
||||
else{
|
||||
print("output_audio_left添加音频read output失败。。。。")
|
||||
}
|
||||
|
||||
|
||||
leftEyeReader.startReading()
|
||||
rightEyeReader.startReading()
|
||||
|
||||
|
||||
|
||||
while let leftBuffer = leftEyeOutput.copyNextSampleBuffer(),
|
||||
let rightBuffer = rightEyeOutput.copyNextSampleBuffer() {
|
||||
@ -87,16 +144,20 @@ class SpatialVideoWriter {
|
||||
let left = CMTaggedBuffer(tags: [.stereoView(.leftEye), .videoLayerID(0)], pixelBuffer: leftCVPixelBuffer)
|
||||
let right = CMTaggedBuffer(tags: [.stereoView(.rightEye), .videoLayerID(1)], pixelBuffer: rightCVPixelBuffer)
|
||||
|
||||
while !adaptor.assetWriterInput.isReadyForMoreMediaData {
|
||||
while !adaptor_inputVideo.assetWriterInput.isReadyForMoreMediaData {
|
||||
// 等待直到 writerInput 准备好接收下一个视频帧
|
||||
Thread.sleep(forTimeInterval: 0.1) // 暂停一段时间,避免过度占用资源
|
||||
}
|
||||
adaptor.appendTaggedBuffers([left, right], withPresentationTime: leftBuffer.presentationTimeStamp)
|
||||
adaptor_inputVideo.appendTaggedBuffers([left, right], withPresentationTime: leftBuffer.presentationTimeStamp)
|
||||
}
|
||||
|
||||
|
||||
self.addAudio(assetTrackOutput: output_audio_left, audio_input: writerInput_Audio_left)
|
||||
|
||||
// 完成写入
|
||||
print("完成写入")
|
||||
input.markAsFinished()
|
||||
writerInput_Audio_left.markAsFinished()
|
||||
input_video.markAsFinished()
|
||||
outputVideoURL.stopAccessingSecurityScopedResource()
|
||||
assetWriter.finishWriting { [self] in
|
||||
print("可以保存")
|
||||
@ -110,15 +171,32 @@ class SpatialVideoWriter {
|
||||
}
|
||||
}
|
||||
|
||||
private func saveVideoToLibrary(videoURL: URL, completion: @escaping (Bool, Error?) -> Void) {
|
||||
PHPhotoLibrary.shared().performChanges({
|
||||
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL)
|
||||
}) { success, error in
|
||||
if success {
|
||||
print("保存成功")
|
||||
} else if let error = error {
|
||||
print("保存失败")
|
||||
|
||||
//追加音频
|
||||
func addAudio(assetTrackOutput:AVAssetReaderTrackOutput,audio_input:AVAssetWriterInput) {
|
||||
while let sample = assetTrackOutput.copyNextSampleBuffer() {
|
||||
print("audio read buffer....")
|
||||
let formatDesc:CMFormatDescription = CMSampleBufferGetFormatDescription(sample)!
|
||||
let mediaType:CMMediaType = CMFormatDescriptionGetMediaType(formatDesc);
|
||||
if mediaType == kCMMediaType_Audio {
|
||||
if audio_input.isReadyForMoreMediaData {
|
||||
if audio_input.append(sample) == false {
|
||||
// print("追加音频失败....:\(String(describing: self.writer.error?.localizedDescription))")
|
||||
print("追加音频失败.....")
|
||||
}
|
||||
else{
|
||||
print("audio 追加成功....")
|
||||
}
|
||||
}
|
||||
else {
|
||||
print("audio 追加还未准备好...")
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
print("不是audio类型...")
|
||||
}
|
||||
}
|
||||
}
|
||||
print("audio func 执行完毕。。。。...")
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user