【问题标题】:Trouble applying scaleTimeRange on multiple videos in a AVMutableComposition video在 AVMutableComposition 视频中的多个视频上应用 scaleTimeRange 时遇到问题
【发布时间】:2020-11-07 08:51:51
【问题描述】:

我正在尝试将视频与 scaleTimeRanges 合并(以使它们慢动作或加速);但是,它没有按预期工作。只有第一个视频具有时间范围效果...不是全部。

这项工作是在合并视频功能中完成的;这很简单...但是我不确定为什么时间范围的缩放仅适用于第一个视频而不适用于下一个视频...

这是一个测试项目,它有我当前的代码https://github.com/meyesyesme/creationMergeProj

这是我使用的合并功能,当前已注释掉时间范围缩放(您可以取消注释以查看它不起作用):

func mergeVideosTestSQ(arrayVideos:[VideoSegment], completion:@escaping (URL?, Error?) -> ()) {


let mixComposition = AVMutableComposition()


var instructions: [AVMutableVideoCompositionLayerInstruction] = []
var insertTime = CMTime(seconds: 0, preferredTimescale: 1)

print(arrayVideos, "<- arrayVideos")
/// for each URL add the video and audio tracks and their duration to the composition
for videoSegment in arrayVideos {
    
    let sourceAsset = AVAsset(url: videoSegment.videoURL!)
    
    let frameRange = CMTimeRange(start: CMTime(seconds: 0, preferredTimescale: 1), duration: sourceAsset.duration)
    
    guard
        let nthVideoTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)),
        let nthAudioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)), //0 used to be kCMPersistentTrackID_Invalid
        let assetVideoTrack = sourceAsset.tracks(withMediaType: .video).first
    else {
        print("didnt work")
        return
    }
    
    var assetAudioTrack: AVAssetTrack?
    assetAudioTrack = sourceAsset.tracks(withMediaType: .audio).first
    print(assetAudioTrack, ",-- assetAudioTrack???", assetAudioTrack?.asset, "<-- hes", sourceAsset)
    
    do {
        
        try nthVideoTrack.insertTimeRange(frameRange, of: assetVideoTrack, at: insertTime)
        try nthAudioTrack.insertTimeRange(frameRange, of: assetAudioTrack!, at: insertTime)
        
        //MY CURRENT SPEED ATTEMPT:
        let newDuration = CMTimeMultiplyByFloat64(frameRange.duration, multiplier: videoSegment.videoSpeed)
        nthVideoTrack.scaleTimeRange(frameRange, toDuration: newDuration)
        nthAudioTrack.scaleTimeRange(frameRange, toDuration: newDuration)
        
        print(insertTime.value, "<-- fiji, newdur --->", newDuration.value, "sourceasset duration--->", sourceAsset.duration.value, "frameRange.duration -->", frameRange.duration.value)
        
        //instructions:
        let nthInstruction = ViewController.videoCompositionInstruction(nthVideoTrack, asset: sourceAsset)
        nthInstruction.setOpacity(0.0, at: CMTimeAdd(insertTime, newDuration)) //sourceasset.duration
        
        instructions.append(nthInstruction)
        insertTime = insertTime + newDuration //sourceAsset.duration
        
        
    } catch {
        DispatchQueue.main.async {
            print("didnt wor2k")
        }
    }
    
}


let mainInstruction = AVMutableVideoCompositionInstruction()
mainInstruction.timeRange = CMTimeRange(start: CMTime(seconds: 0, preferredTimescale: 1), duration: insertTime)

mainInstruction.layerInstructions = instructions

let mainComposition = AVMutableVideoComposition()
mainComposition.instructions = [mainInstruction]
mainComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
mainComposition.renderSize = CGSize(width: 1080, height: 1920)

let outputFileURL = URL(fileURLWithPath: NSTemporaryDirectory() + "merge.mp4")

//below to clear the video form docuent folder for new vid...
let fileManager = FileManager()
try? fileManager.removeItem(at: outputFileURL)

print("<now will export: ???? ????????????????????????????????????????????????????????????????????????????????????????????????????????????")


/// try to start an export session and set the path and file type
if let exportSession = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) { //DOES NOT WORK WITH AVAssetExportPresetPassthrough
    exportSession.outputFileType = .mov
    exportSession.outputURL = outputFileURL
    exportSession.videoComposition = mainComposition
    exportSession.shouldOptimizeForNetworkUse = true
    
    /// try to export the file and handle the status cases
    exportSession.exportAsynchronously {
        if let url = exportSession.outputURL{
            completion(url, nil)
        }
        if let error = exportSession.error {
            completion(nil, error)
        }
    }
    
}

}

您会看到这种行为:第一个视频运行良好,但接下来的视频没有,并且在设置不透明度时遇到问题,等等...我尝试了不同的组合,这是最接近的组合.

我已经被困了一段时间了!

【问题讨论】:

    标签: ios swift avfoundation swift4 avmutablecomposition


    【解决方案1】:
    1. 缩放视频后,合成的持续时间会重新计算,因此您需要根据此更改附加下一部分。替换

       insertTime = insertTime + duration
      

       insertTime = insertTime + newDuration
      
    2. 您还需要更新 setOpacity at 值,我建议您在 insertTime 更新后移动该行并使用新值,以删除此处的重复工作

    3. 当你应用比例时,它被应用到新的构图上,所以你需要使用相对范围:

       let currentRange = CMTimeRange(start: insertTime, duration: frameRange.duration)
       nthVideoTrack.scaleTimeRange(currentRange, toDuration: newDuration)
       nthAudioTrack.scaleTimeRange(currentRange, toDuration: newDuration)
      

    【讨论】:

    • 是的,我将代码更新为该代码,但它仍然无法正常工作。您可以查看是否进行测试,例如,如果您制作三个视频,假设速度为 0.3,则第一个视频效果很好,但第二个和第三个视频效果不佳。似乎任何包含 >= 3 个视频的合并都不起作用……至少从我的测试来看
    • 我在您的代码中发现了第二个问题,请查看更新后的答案
    • 好的!从我的测试来看,这很好用!我会做更多的测试然后告诉你!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多