You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift实现视频指定颜色透明化并保存编辑后的视频

在Swift中实现视频指定颜色透明化并保存

核心思路

要实现视频指定颜色透明,本质是对每一帧图像做颜色抠图处理,生成带Alpha通道的视频帧后重新编码合成。核心依赖AVFoundation(视频读写与合成)和CoreImage(帧图像滤镜处理)框架,步骤如下:

  • 读取原视频轨道
  • 用CoreImage滤镜将目标颜色区域转为透明
  • 生成带Alpha通道的视频合成项用于播放或导出

完整实现代码

1. 颜色抠图滤镜工具函数

封装生成颜色抠图滤镜的逻辑,可通过容差参数控制颜色匹配范围:

import AVFoundation
import CoreImage

func createColorKeyFilter(targetColor: UIColor, tolerance: CGFloat = 0.1) -> CIFilter? {
    guard let ciColor = CIColor(color: targetColor) else { return nil }
    
    // 1. 计算颜色差值,分离目标颜色区域
    let colorMatrixFilter = CIFilter(name: "CIColorMatrix")!
    let redVector = CIVector(x: 1, y: 0, z: 0, w: -ciColor.red)
    let greenVector = CIVector(x: 0, y: 1, z: 0, w: -ciColor.green)
    let blueVector = CIVector(x: 0, y: 0, z: 1, w: -ciColor.blue)
    let alphaVector = CIVector(x: 0, y: 0, z: 0, w: 1)
    
    colorMatrixFilter.setValue(redVector, forKey: "inputRVector")
    colorMatrixFilter.setValue(greenVector, forKey: "inputGVector")
    colorMatrixFilter.setValue(blueVector, forKey: "inputBVector")
    colorMatrixFilter.setValue(alphaVector, forKey: "inputAVector")
    
    // 2. 模糊+阈值处理,生成平滑的透明度遮罩
    let blurFilter = CIFilter(name: "CIGaussianBlur")!
    blurFilter.setValue(colorMatrixFilter.outputImage, forKey: kCIInputImageKey)
    blurFilter.setValue(tolerance * 10, forKey: kCIInputRadiusKey)
    
    let thresholdFilter = CIFilter(name: "CIColorThreshold")!
    thresholdFilter.setValue(blurFilter.outputImage, forKey: kCIInputImageKey)
    thresholdFilter.setValue(tolerance, forKey: kCIInputThresholdKey)
    
    // 3. 将遮罩转为Alpha通道,实现透明效果
    let maskToAlphaFilter = CIFilter(name: "CIMaskToAlpha")!
    maskToAlphaFilter.setValue(thresholdFilter.outputImage, forKey: kCIInputImageKey)
    
    return maskToAlphaFilter
}

2. 生成带透明效果的AVPlayerItem

对应你代码中的createTransparentItem函数,生成可直接播放的透明视频项:

func createTransparentItem(url: URL, targetColor: UIColor = .green) -> AVPlayerItem? {
    let asset = AVAsset(url: url)
    
    // 创建视频合成轨道
    let composition = AVMutableComposition()
    guard let sourceVideoTrack = asset.tracks(withMediaType: .video).first else { return nil }
    let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)!
    
    do {
        try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: asset.duration), of: sourceVideoTrack, at: .zero)
    } catch {
        print("插入视频轨道失败: \(error)")
        return nil
    }
    
    // 配置视频帧处理逻辑
    let videoComposition = AVMutableVideoComposition(asset: asset) { request in
        let sourceImage = request.sourceImage
        guard let filter = createColorKeyFilter(targetColor: targetColor) else {
            request.finish(with: sourceImage, context: nil)
            return
        }
        
        filter.setValue(sourceImage, forKey: kCIInputImageKey)
        guard let outputImage = filter.outputImage else {
            request.finish(with: sourceImage, context: nil)
            return
        }
        
        // 确保输出图像带Alpha通道
        let context = CIContext(options: [.workingColorSpace: kCFNull!])
        let cgImage = context.createCGImage(outputImage, from: outputImage.extent)!
        let finalImage = CIImage(cgImage: cgImage)
        
        request.finish(with: finalImage, context: nil)
    }
    
    // 设置合成属性,支持透明背景
    videoComposition.renderSize = sourceVideoTrack.naturalSize
    videoComposition.frameDuration = sourceVideoTrack.minFrameDuration
    videoComposition.backgroundColor = UIColor.clear.cgColor
    
    let playerItem = AVPlayerItem(asset: composition)
    playerItem.videoComposition = videoComposition
    
    return playerItem
}

3. 保存处理后的视频到本地

如果需要将透明视频导出保存,用AVAssetExportSession实现:

func exportTransparentVideo(from url: URL, targetColor: UIColor, outputURL: URL, completion: @escaping (Error?) -> Void) {
    guard let playerItem = createTransparentItem(url: url, targetColor: targetColor) else {
        completion(NSError(domain: "VideoProcessing", code: -1, userInfo: [NSLocalizedDescriptionKey: "无法创建透明视频项"]))
        return
    }
    
    let asset = playerItem.asset
    // 选择支持Alpha通道的导出预设
    guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHEVCWithAlpha) else {
        completion(NSError(domain: "VideoProcessing", code: -2, userInfo: [NSLocalizedDescriptionKey: "无法创建导出会话"]))
        return
    }
    
    exportSession.outputURL = outputURL
    exportSession.outputFileType = .mov // MOV格式原生支持Alpha通道
    exportSession.videoComposition = playerItem.videoComposition
    
    exportSession.exportAsynchronously {
        if exportSession.status == .completed {
            completion(nil)
        } else {
            completion(exportSession.error)
        }
    }
}

4. 适配你的原有代码

补充目标颜色参数,即可直接使用:

let player = AVPlayerView(frame: CGRect(origin: .zero, size: videoSize))
let url: URL = Bundle.main.url(forResource: "video", withExtension: "mp4")!
// 指定要抠除的颜色,示例为绿色
let playerItem = createTransparentItem(url: url, targetColor: .green)
        
player.loadPlayerItem(playerItem) { [weak self] result in
    switch result {
    case .failure(let error):
        print("加载失败", error)
    case .success(let player):
        player.play()
        self?.animateBackgroundColor()
    }
}

关键注意事项

  • 格式限制:只有MOV、ProRes等格式支持Alpha通道,导出时需选择对应格式和预设
  • 容差调整:tolerance值越大,越接近目标颜色的区域会被转为透明,可根据实际视频调整
  • 性能优化:处理高分辨率视频时,建议将帧处理逻辑放在后台队列,避免阻塞主线程

内容的提问来源于stack exchange,提问作者CYAD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 15:32:53