视频框架Cabbage源码分析

在了解Cabbage之前可以查看github上的文档,里面有详细介绍AVFoundation,本文章就简单地过一下框架相关类。

AVFoundation 中,视频和音频数据可以用 AVAsset 表示,AVAsset 里面包含了 AVAssetTrack 数据,比如:一个视频文件里面包含了一个视频 track 和两个音频 track。可以使用 AVCompositiontrack 进行裁剪和变速等操作,也可以把多段 track 拼接到 AVComposition 里面。

先看个例子,这是视频转场的代码:

class ViewController: UITableViewController {
    func test() {
        let playerItem: AVPlayerItem? = transitionPlayerItem()//AVPlayerItem 的时间轴驱动视频数据的获取。
        let controller = AVPlayerViewController()
        controller.player = AVPlayer.init(playerItem: playerItem)//视频播放器
        navigationController?.pushViewController(controller, animated: true)
    }

    func transitionPlayerItem() -> AVPlayerItem? {
        let bambooTrackItem: TrackItem = { ... }()
        
        let overlayTrackItem: TrackItem = { ... }()
        
        let seaTrackItem: TrackItem = { ... }()
        
        let transitionDuration = CMTime(seconds: 2, preferredTimescale: 600)
        bambooTrackItem.videoTransition = PushTransition(duration: transitionDuration)
        bambooTrackItem.audioTransition = FadeInOutAudioTransition(duration: transitionDuration)
        
        overlayTrackItem.videoTransition = BoundingUpTransition(duration: transitionDuration)
        //Cabbage 核心类是 Timeline 和 CompositionGenerator
        let timeline = Timeline()//Timeline用于往时间轴上添加数据片段,可以提供视频相关数据和音频相关数据。
        timeline.videoChannel = [bambooTrackItem, overlayTrackItem, seaTrackItem]
        timeline.audioChannel = [bambooTrackItem, seaTrackItem]
        
        do {
            try Timeline.reloadVideoStartTime(providers: timeline.videoChannel)
        } catch { ... }
        timeline.renderSize = CGSize(width: 1920, height: 1080)
        /*CompositionGenerator 其实是 Timeline 和 AVFoundation 接口的桥接器。
        CompositionGenerator 用于把 Timeline 的数据合成为 AVComposition、AVVideoComposition 和 AVAudioMix,
        然后用这 3 个对象生成 AVPlayerItem、AVAssetImageGenerator 和 AVAssetExportSession 等用于处理视频的对象。*/
        let compositionGenerator = CompositionGenerator(timeline: timeline)
        let playerItem = compositionGenerator.buildPlayerItem()
        return playerItem
    }
}

Cabbage 核心类是 TimelineCompositionGenerator
Timeline用于往时间轴上添加数据片段,可以提供视频相关数据和音频相关数据。
CompositionGenerator 其实是 TimelineAVFoundation 接口的桥接器。 用于把 Timeline 的数据合成为 AVCompositionAVVideoCompositionAVAudioMix,然后用这 3 个对象生成 AVPlayerItemAVAssetImageGeneratorAVAssetExportSession 等用于处理视频的对象。

  1. 通过CompositionGenerator生成相关类,先是AVCompositionvideoAVCompositionTrackaudioAVCompositionTrack
public class CompositionGenerator {
    ...
    public func buildPlayerItem() -> AVPlayerItem {
        let composition = buildComposition()//创建AVComposition
        let playerItem = AVPlayerItem(asset: composition)
        playerItem.videoComposition = buildVideoComposition()//创建AVVideoComposition
        playerItem.audioMix = buildAudioMix()
        return playerItem
    }
    ...
    @discardableResult
    public func buildComposition() -> AVComposition {
        ...
        let composition = AVMutableComposition(urlAssetInitializationOptions: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
        ...
        timeline.videoChannel.enumerated().forEach({ (offset, provider) in
            for index in 0..<provider.numberOfVideoTracks() {
                let trackID: Int32 = getVideoTrackID(for: index) + Int32((offset % 2 + 1) * 1000)
                if let compositionTrack = provider.videoCompositionTrack(for: composition, at: index, preferredTrackID: trackID) { ... }
            }
        })
        ...
        timeline.audioChannel.enumerated().forEach { (offset, provider) in
            for index in 0..<provider.numberOfAudioTracks() {
                let trackID: Int32 = getAudioTrackID(for: index) + Int32((offset % 2 + 1) * 1000)
                if let compositionTrack = provider.audioCompositionTrack(for: composition, at: index, preferredTrackID: trackID) { ... }
            }
            ...
        }
        ...
        return composition//AVComposition 对 track 进行裁剪和变速等操作,也可以把多段 track 拼接到 AVComposition 里面。
    }
}
open class TrackItem: NSObject, NSCopying, TransitionableVideoProvider, TransitionableAudioProvider {
    ...
    open func videoCompositionTrack(for composition: AVMutableComposition, at index: Int, preferredTrackID: Int32) -> AVCompositionTrack? {
        let trackInfo = resource.trackInfo(for: .video, at: index)
        let track = trackInfo.track
        
        let compositionTrack: AVMutableCompositionTrack? = {
            if let track = composition.track(withTrackID: preferredTrackID) {
                return track
            }
            return composition.addMutableTrack(withMediaType: track.mediaType, preferredTrackID: preferredTrackID)
        }()
        
        if let compositionTrack = compositionTrack { ... }
        return compositionTrack
    }
    ...
    open func audioCompositionTrack(for composition: AVMutableComposition, at index: Int, preferredTrackID: Int32) -> AVCompositionTrack? {
        let trackInfo = resource.trackInfo(for: .audio, at: index)
        let compositionTrack: AVMutableCompositionTrack? = {
            if let track = composition.track(withTrackID: preferredTrackID) {
                return track
            }
            return composition.addMutableTrack(withMediaType: trackInfo.track.mediaType, preferredTrackID: preferredTrackID)
        }()
        if let compositionTrack = compositionTrack { ... }
        return compositionTrack
    }
}
  1. 然后是AVVideoComposition
public class CompositionGenerator {
    ...
    public func buildVideoComposition() -> AVVideoComposition? {
        ...
        let videoComposition = AVMutableVideoComposition()
        videoComposition.frameDuration = CMTime(value: 1, timescale: 30)
        videoComposition.renderSize = self.timeline.renderSize
        videoComposition.instructions = instructions
        videoComposition.customVideoCompositorClass = VideoCompositor.self
        self.videoComposition = videoComposition
        
        return videoComposition
    }
    ...
}

AVVideoComposition 可以用于设置帧率、画布大小、指定不同的 video track 应用何种编辑操作以及可以将视频画面嵌套在 CALayer 中。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容