ios - 在视频上覆盖文本非常慢,任何更快的替代方案

标签 ios swift

    let asset = AVURLAsset(url: videoURL)
    let composition = AVMutableComposition()
    
    guard
        let compositionTrack = composition.addMutableTrack(
            withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid),
        let assetTrack = asset.tracks(withMediaType: .video).first
        else {
            print("Something is wrong with the asset.")
            onComplete(nil)
            return
    }
    
    do {
        let timeRange = CMTimeRange(start: .zero, duration: asset.duration)
        try compositionTrack.insertTimeRange(timeRange, of: assetTrack, at: .zero)
        
        if let audioAssetTrack = asset.tracks(withMediaType: .audio).first,
            let compositionAudioTrack = composition.addMutableTrack(
                withMediaType: .audio,
                preferredTrackID: kCMPersistentTrackID_Invalid) {
            try compositionAudioTrack.insertTimeRange(
                timeRange,
                of: audioAssetTrack,
                at: .zero)
        }
    } catch {
        //print(error)
        onComplete(nil)
        return
    }
    
    compositionTrack.preferredTransform = assetTrack.preferredTransform
    let videoInfo = orientation(from: assetTrack.preferredTransform)
    
    let videoSize: CGSize
    if videoInfo.isPortrait {
        videoSize = CGSize(
            width: assetTrack.naturalSize.height,
            height: assetTrack.naturalSize.width)
    } else {
        videoSize = assetTrack.naturalSize
    }
    
    let videoLayer = CALayer()
    videoLayer.frame = CGRect(origin: .zero, size: videoSize)

    let textLayer = CATextLayer()
    textLayer.string = mainTextview.text
    textLayer.shouldRasterize = true
    textLayer.rasterizationScale = UIScreen.main.scale
    //textLayer.backgroundColor = UIColor.black.cgColor
    
    switch textAlignment {
    case .center:
        textLayer.alignmentMode = .center
    case .justified:
        textLayer.alignmentMode = .justified
    case .left:
        textLayer.alignmentMode = .left
    case .right:
        textLayer.alignmentMode = .right
    default:
        textLayer.alignmentMode = .center
    }
    
    textLayer.isWrapped = true
    textLayer.foregroundColor = mainTextview.textColor?.cgColor
    
    textLayer.fontSize = 70
    
    switch textWeight {
    case .bold:
        textLayer.font = UIFont.systemFont(ofSize: 0, weight: .bold)
    case .light:
        textLayer.font = UIFont.systemFont(ofSize: 0, weight: .light)
    case .regular:
        textLayer.font = UIFont.systemFont(ofSize: 0, weight: .regular)
    case .medium:
        textLayer.font = UIFont.systemFont(ofSize: 0, weight: .medium)
    }
    
    switch textviewPosition {
    case .Center:
        textLayer.frame = CGRect(x: 0, y: videoSize.height * 0.30, width: videoSize.width, height: 500)
    case .Top:
        textLayer.frame = CGRect(x: 0, y: videoSize.height * 0.60, width: videoSize.width, height: 500)
    case .Bottom:
        textLayer.frame = CGRect(x: 10, y: 0, width: videoSize.width, height: 500)
    }
    textLayer.displayIfNeeded()
    
    let outputLayer = CALayer()
    outputLayer.frame = CGRect(origin: .zero, size: videoSize)
    outputLayer.addSublayer(videoLayer)
    outputLayer.addSublayer(textLayer)
    
    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)
    videoComposition.instructions = [instruction]
    let layerInstruction = compositionLayerInstruction(
        for: compositionTrack,
        assetTrack: assetTrack)
    instruction.layerInstructions = [layerInstruction]
    
    guard let export = AVAssetExportSession(
        asset: composition,
        presetName: AVAssetExportPresetHighestQuality)
        else {
            //print("Cannot create export session.")
            onComplete(nil)
            return
    }
    
    let videoName = UUID().uuidString
    let exportURL = URL(fileURLWithPath: NSTemporaryDirectory())
        .appendingPathComponent(videoName)
        .appendingPathExtension(".mp4")
    
    export.videoComposition = videoComposition
    export.outputFileType = .mp4
    export.outputURL = exportURL
    
    export.exportAsynchronously {
        DispatchQueue.main.async {
            switch export.status {
            case .completed:
                onComplete(exportURL)
            default:
                onComplete(nil)
                break
            }
        }
    }
}
这是我用来在视频上覆盖文本的功能(videoURL),我传入保存在文档目录中的视频的 url,并使用已经为用户创建的 TextView 来检索文本、重量、字体和对齐覆盖谢谢。这个过程的大部分时间需要 15 秒,这对于用户来说是很长的等待时间。

最佳答案

导出视频是劳动密集型的,需要大量时间,对此您无能为力。
但是,该过程是异步的,因此无需让用户“等待”。此外,导出器提供一个 Progress 对象,因此您可以轻松地将进度显示为一种心理技巧(当您观看进度指示器时,时间过得真快)。

关于ios - 在视频上覆盖文本非常慢,任何更快的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63208051/

相关文章:

ios - 作为 SubView VS ChildViewController 查看

ios - 如何将数据发送到 ios Swift 中的自定义标签栏 Controller

ios - 如何在不将私有(private) header 包含到框架中的情况下创建私有(private)模块?

swift - 检测 WKWebView 中的图片点击?

swift - 我可以改进我的 Firebase 结构吗?

ios - 我无法在注册表单中添加性别的 UIPickerview

iphone - 在应用程序中打开,从 launchOptions 获取 UIApplicationLaunchOptionsURLKey

ios - 如何匹配两个TableView中的值

ios - 无法识别带有 UILocalizedIndexedCollat​​ion.current().section(for :collationStringSelector:#selector(getter: UIPreviewAction. title)) 的选择器

swift - 如何避免 Parse.com 上出现多个实例?