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

设置AVAssetExportSession的videoComposition时AVAsset视频旋转不生效

解决AVAssetExportSession旋转视频不生效的问题

我之前也碰到过类似的坑,你用AVAssetWriter写完视频后,用AVAssetExportSession设置旋转没生效,大概率是没处理好原视频的轨道信息、导出参数或者transform的组合方式。下面给你一步步排查和解决的方法:

1. 先检查原视频的旋转元数据

有时候你捕获的视频本身已经带有旋转信息,直接叠加新的transform会导致冲突。先打印原视频轨道的preferredTransform看看:

let firstAsset = AVURLAsset(url: self.movieURL() as URL)
if let videoTrack = firstAsset.tracks(withMediaType: .video).first {
    print("原视频轨道旋转信息:\(videoTrack.preferredTransform)")
}

如果输出不是.identity,说明原视频已经有旋转设置,后续要基于这个transform来叠加你需要的90度旋转。

2. 正确组合旋转Transform

不要直接给exportSession设置单一的旋转transform,要和原视频的transform拼接起来,这样才会生效。比如你要顺时针旋转90度,可以这么写:

guard let exporter = AVAssetExportSession(asset: firstAsset, presetName: AVAssetExportPresetHighestQuality) else { 
    print("创建导出会话失败")
    return 
}

// 获取原视频轨道的transform
guard let videoTrack = firstAsset.tracks(withMediaType: .video).first else { return }
let originalTransform = videoTrack.preferredTransform

// 组合90度顺时针旋转的transform(如果要逆时针就用 -.pi/2)
let rotation90 = CGAffineTransform(rotationAngle: .pi/2)
let finalTransform = originalTransform.concatenating(rotation90)

exporter.outputTransform = finalTransform

3. 确保导出格式支持旋转元数据

有些视频格式对旋转信息的兼容性不好,建议优先用.mov格式,或者确认.mp4的设置正确:

exporter.outputFileType = .mov

4. 输出路径必须唯一

如果导出的URL和原视频URL相同,会导致覆盖失败或者读取异常,一定要设置一个新的输出路径:

// 生成临时输出路径,你也可以改成自定义的沙盒路径
let outputURL = FileManager.default.temporaryDirectory.appendingPathComponent("rotated_video_\(Date().timeIntervalSince1970).mov")
// 如果路径已存在,先删除
if FileManager.default.fileExists(atPath: outputURL.path) {
    try? FileManager.default.removeItem(at: outputURL)
}
exporter.outputURL = outputURL

5. 完善导出回调的错误处理

导出完成后一定要检查状态,看看有没有报错,方便定位问题:

exporter.exportAsynchronously { [weak self] in
    DispatchQueue.main.async {
        switch exporter.status {
        case .completed:
            print("旋转完成!视频路径:\(outputURL)")
            // 这里可以把视频保存到相册或者做其他处理
        case .failed:
            print("导出失败:\(exporter.error?.localizedDescription ?? "未知错误")")
        case .cancelled:
            print("导出被取消")
        default:
            break
        }
    }
}

额外提醒:写入视频时的方向处理

如果上面的方法还是没效果,可能是你用AVAssetWriter写入的时候就没正确设置方向。捕获视频时,要把设备方向转换成AVAssetWriterInput的transform,比如:

// 自定义方法,根据当前设备方向返回对应的transform
func getCaptureTransform() -> CGAffineTransform {
    let orientation = UIDevice.current.orientation
    switch orientation {
    case .portraitUpsideDown:
        return CGAffineTransform(rotationAngle: .pi)
    case .landscapeLeft:
        return CGAffineTransform(rotationAngle: .pi/2)
    case .landscapeRight:
        return CGAffineTransform(rotationAngle: -.pi/2)
    default:
        return .identity
    }
}

// 给AVAssetWriterInput设置transform
videoInput.transform = getCaptureTransform()

按照这些步骤调整,应该就能解决旋转不生效的问题了。

内容的提问来源于stack exchange,提问作者Chewie The Chorkie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:26:37