Как объединить AVVideoCompositions для разных AVCompositions в одну

#ios #swift #avvideocomposition #avcomposition

#iOS #swift #avvideocomposition #avcomposition

Вопрос:

У меня есть несколько AVAsset видео, которые я объединяю, используя временные интервалы в AVComposition . У каждого видео есть связанный AVVideoComposition , который использует animationTool для добавления слоя наложения к видео. Я хочу иметь возможность объединять их AVVideoCompositions аналогично тому AVComposition , чтобы слои, связанные с каждым AVAsset, отображались / скрывались в указанное время начала / окончания. Как я могу это сделать?

В настоящее время я использую этот код для создания AVVideoComposition for AVComposition с одним AVAsset:

 // Create video composition
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = videoSize
videoComposition.frameDuration = CMTime(value: 1, timescale: 30)
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(
  postProcessingAsVideoLayer: videoLayer,
  in: outputLayer
)

let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRange(
  start: .zero,
  duration: composition.duration
)
let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: compositionTrack)
layerInstruction.setTransform(assetTrack.preferredTransform, at: .zero)
instruction.layerInstructions = [layerInstruction]
videoComposition.instructions = [instruction]
  

Это мой код для создания AVComposition с несколькими активами:

 static func createFullVideo(from videos: [VideoItem]) -> AVComposition? {
    let newComposition = AVMutableComposition()
    
    guard let compositionTrack = newComposition.addMutableTrack(
        withMediaType: .video,
        preferredTrackID: kCMPersistentTrackID_Invalid) else {
        return nil
    }
    guard let compositionAudioTrack = newComposition.addMutableTrack(
            withMediaType: .audio,
            preferredTrackID: kCMPersistentTrackID_Invalid) else {
        return nil
    }

    var endTimeOfPreviousTrack: CMTime = .zero

    for video in videos {
        let composition = video.composition

        guard let assetTrack = composition.tracks(withMediaType: .video).first else {
            return nil
        }
        compositionTrack.preferredTransform = assetTrack.preferredTransform
        do {
            // Insert time range for video track in composition
            let timeRange = assetTrack.timeRange
            try compositionTrack.insertTimeRange(timeRange, of: assetTrack, at: endTimeOfPreviousTrack)

            // Get the audio track from the asset
            guard let audioAssetTrack = composition.tracks(withMediaType: .audio).first else {
                return nil
            }

            // Insert time range for audio track in composition
            try compositionAudioTrack.insertTimeRange(
              timeRange,
              of: audioAssetTrack,
              at: endTimeOfPreviousTrack
            )

            // Store end time of track
            endTimeOfPreviousTrack = CMTimeAdd(endTimeOfPreviousTrack,  assetTrack.timeRange.duration)
        } catch {
            return nil
        }
    return newComposition
}