GPUImage3导出视频至文档目录异常:导出文件损坏求错误排查
导出带滤镜的视频文件损坏问题排查与修复方案
我仔细看了你的代码,发现几个很可能导致导出视频损坏的问题,咱们一个个拆解:
链路错误:Writer没有接收经过滤镜处理的帧
你当前的设置是让原视频(movie)直接输出到writer,但滤镜后的帧只到了renderView。这种情况下,writer拿到的是未处理的原视频帧,同时你硬编码了writer的尺寸为100x100,和原视频尺寸大概率不匹配,编码时帧尺寸不一致直接会导致文件损坏。正确的做法是让滤镜的输出同时连接到渲染视图和writer,保证writer拿到的是经过滤镜处理且尺寸匹配的帧。viewDidLayoutSubviews会重复执行
这个方法在视图布局变化(比如屏幕旋转、视图调整大小)时会多次触发,你现在的代码每次触发都会重新创建movie、writer、filter,还会重复启动录制,这会导致文件写入混乱,直接损坏输出文件。应该把视频处理的初始化逻辑移到只执行一次的地方,比如viewDidLoad,或者加个判断确保只初始化一次。LookupFilter的图片加载未做校验
如果UIImage(named: "Image")加载失败(比如图片不存在、名称写错),lookupImage会是无效状态,滤镜处理会出问题,进而导致输出的视频帧异常,最终损坏文件。最好加个非空校验。硬编码输出尺寸不合理
直接指定100x100的尺寸和原视频尺寸不匹配,编码时容易出现兼容性问题,建议使用原视频的尺寸movie.size来初始化writer。
修复后的代码示例
class ViewController: UIViewController { @IBOutlet weak var renderView: RenderView! var movie: MovieInput! var writer: MovieOutput! var filter: LookupFilter! override func viewDidLoad() { super.viewDidLoad() setupVideoProcessing() } private func setupVideoProcessing() { guard let bundleURL = Bundle.main.resourceURL else { print("无法获取资源目录") return } let movieURL = URL(string:"sample_iPod.m4v", relativeTo: bundleURL)! do { let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) let fileURL = documentDirectory.appendingPathComponent("TestVideo.mov") // 初始化视频输入,获取原视频尺寸 movie = try MovieInput(url: movieURL, playAtActualSpeed: true) // 使用原视频尺寸初始化writer,避免尺寸不匹配 writer = try MovieOutput(URL: fileURL, size: movie.size) // 校验lookup图片是否加载成功 guard let lookupImage = UIImage(named: "Image") else { print("Lookup图片加载失败") return } filter = LookupFilter() filter.lookupImage = PictureInput(image: lookupImage) // 建立正确的链路:原视频→滤镜→渲染视图;滤镜→writer movie --> filter --> renderView filter --> writer movie.runBenchmark = true movie.start() writer.startRecording() writer.finishRecording { print("视频导出完成") } } catch { print("处理视频出错: \(error)") } } }
内容的提问来源于stack exchange,提问作者Bhargav Soni
相关产品推荐
相关产品推荐

