swift - 合成视频和音频 - 视频的音频消失了

标签 swift avfoundation avmutablecomposition avkit

我的问题是,我正在使用下面的功能来合成视频和音频。我想保留视频的原始声音,但它以某种方式消失了,我没有任何线索。

我从 this answer 得到这个函数

我试图在添加 AVMutableCompositionTrack 后立即更改音量,但它没有用

例如;

mutableVideoCompositionTrack.prefferedVolume = 1.0
mutableAudioCompositionTrack.prefferedVolume = 0.05

但是,您仍然只能听到音频文件。

函数;

private func mergeAudioAndVideo(audioUrl: URL, videoUrl: URL, completion: @escaping (Bool)->Void){

    let mixComposition = AVMutableComposition()
    var mutableCompositionVideoTrack : [AVMutableCompositionTrack] = []
    var mutableCompositionAudioTrack : [AVMutableCompositionTrack] = []
    let totalVideoCompositionInstruction = AVMutableVideoCompositionInstruction()

    let videoAsset = AVAsset(url: videoUrl)
    let audioAsset = AVAsset(url: audioUrl)

    mutableCompositionVideoTrack.append(mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid))
    mutableCompositionAudioTrack.append(mixComposition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid))
    mutableCompositionAudioTrack[0].preferredVolume = 0.05
    mutableCompositionVideoTrack[0].preferredVolume = 1.0        


    let videoAssetTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0]
    let audioAssetTrack = audioAsset.tracks(withMediaType: AVMediaTypeAudio)[0]

    do {
        try mutableCompositionVideoTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAssetTrack.timeRange.duration), of: videoAssetTrack, at: kCMTimeZero)
        try mutableCompositionAudioTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAssetTrack.timeRange.duration), of: audioAssetTrack, at: kCMTimeZero)
    }catch{
        print("ERROR#1")
    }

    totalVideoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAssetTrack.timeRange.duration)

    let mutableVideoComposition = AVMutableVideoComposition()
    mutableVideoComposition.frameDuration = CMTimeMake(1, 30)
    mutableVideoComposition.renderSize = CGSize(width: 1280, height: 720)

    //exporting

    savePathUrl = try! FileManager.default.url(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("merged").appendingPathExtension("mov")

    let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)!
    assetExport.outputFileType = AVFileTypeMPEG4
    assetExport.outputURL = savePathUrl
    assetExport.shouldOptimizeForNetworkUse = true

    do {
        try FileManager.default.removeItem(at: savePathUrl)
    }catch {
        print(error)
    }

    assetExport.exportAsynchronously { 
        switch assetExport.status{
        case .completed:
            print("completed")
            completion(true)
        default:
            print("failed \(assetExport.error!)")
            completion(false)
        }
    }

}

最佳答案

您可以单独调整视频和音频的音量@Faruk,这里有一些代码。

        //Extract audio from the video and the music
let audioMix: AVMutableAudioMix = AVMutableAudioMix()
var audioMixParam: [AVMutableAudioMixInputParameters] = []

let assetVideoTrack: AVAssetTrack = assetVideo.tracksWithMediaType(AVMediaTypeAudio)[0]
let assetMusicTrack: AVAssetTrack = assetMusic.tracksWithMediaType(AVMediaTypeAudio)[0]

let videoParam: AVMutableAudioMixInputParameters = AVMutableAudioMixInputParameters(track: assetVideoTrack)
videoParam.trackID = compositionAudioVideo.trackID

let musicParam: AVMutableAudioMixInputParameters = AVMutableAudioMixInputParameters(track: assetMusicTrack)
musicParam.trackID = compositionAudioMusic.trackID

//Set final volume of the audio record and the music
videoParam.setVolume(volumeVideo, atTime: kCMTimeZero)
musicParam.setVolume(volumeAudio, atTime: kCMTimeZero)

//Add setting
audioMixParam.append(musicParam)
audioMixParam.append(videoParam)

//Add audio on final record
//First: the audio of the record and Second: the music
do {
try compositionAudioVideo.insertTimeRange(CMTimeRangeMake(kCMTimeZero, assetVideo.duration), ofTrack: assetVideoTrack, atTime: kCMTimeZero)
} catch _ {
assertionFailure()
}

do {
try compositionAudioMusic.insertTimeRange(CMTimeRangeMake(CMTimeMake(Int64(startAudioTime * 10000), 10000), assetVideo.duration), ofTrack: assetMusicTrack, atTime: kCMTimeZero)
} catch _ {
assertionFailure()
}

//Add parameter
audioMix.inputParameters = audioMixParam

let completeMovie = "\(docsDir)/\(randomString(5)).mp4"
let completeMovieUrl = NSURL(fileURLWithPath: completeMovie)
let exporter: AVAssetExportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)!

exporter.outputURL = completeMovieUrl
exporter.outputFileType = AVFileTypeMPEG4
exporter.audioMix = audioMix
exporter.exportAsynchronouslyWithCompletionHandler({ 

switch exporter.status {

case AVAssetExportSessionStatus.Completed:
    print("success with output url \(completeMovieUrl)")
    case  AVAssetExportSessionStatus.Failed:
        print("failed \(String(exporter.error))")
    case AVAssetExportSessionStatus.Cancelled:
        print("cancelled \(String(exporter.error))")
    default:
        print("complete")
    }            
})

关于swift - 合成视频和音频 - 视频的音频消失了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45313680/

相关文章:

iOS:如何拦截和操作 AVPlayer 中的字节

ios - 在 AVMutableVideoComposition 中创建一个按时间间隔更改的 CATextlayer

iphone - 如果视频持续时间比音频持续时间长,如何重复音轨

ios - 在 collectionViewCell 中为 imageview 添加约束

ios - 如何使用 SwiftUI 在导航栏上添加按钮

ios - 使用 AVPlayer 播放本地 GIF

iOS 在模拟器上播放音频成功,但在设备上播放失败

ios - 使用 AVMutableCompositionTrack 合并 AVMutableComposition 中的视频和图像,而不是 AVVideoCompositionCoreAnimationTool?

Swift:导出依赖的API

ios - View 中的手势识别器并使用 View Controller 作为目标,我的设计是否错误?