首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >同时使用AVComposition和AVVideoComposition时转换错误

同时使用AVComposition和AVVideoComposition时转换错误
EN

Stack Overflow用户
提问于 2020-10-12 18:49:09
回答 1查看 554关注 0票数 2

我正在创建一个AVMutableComposition。我需要将资产水平翻转,所以我正在设置如下组合轨道的转换:

代码语言:javascript
复制
compositionTrack.preferredTransform = assetTrack.preferredTransform.scaledBy(x: -1, y: 1)

如果我导出这个(我使用AVAssetPreset960x640作为我的预置),它就会像预期的那样工作。

不过,我还需要添加一个AVMutableVideoComposition覆盖,以便与此复制呈现。这个覆盖层不应该水平翻转。我是这样说的:

代码语言:javascript
复制
// Create video composition
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
)
let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: compositionTrack)
layerInstruction.setTransform(assetTrack.preferredTransform, at: .zero)
    
instruction.layerInstructions = [layerInstruction]
videoComposition.instructions = [instruction]

当我用这个导出视频时,它不是水平翻转的。它阻止应用于组合的preferredTransform被执行。大概是这条线造成了这种情况:

代码语言:javascript
复制
layerInstruction.setTransform(assetTrack.preferredTransform, at: .zero)

如果我将图层转换设置为assetTrack.preferredTransform.scaledBy(x: -1, y: 1)compositionTrack.preferredTransform,则会在导出时显示一个黑色屏幕。

苹果让这些医生在AVVideoComposition上解释转换。如果我理解正确的话,他们说我应该设置图层指令的转换。如果我这样做--对图层指令而不是构图进行转换--我仍然会看到一个黑色屏幕。

这是为什么,我怎么能解决这个问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-12 19:21:49

编辑:成功的转换是

代码语言:javascript
复制
CGAffineTransform(a: -1.0, b: 0.0, c: 0.0, d: 1.0, tx: videoSize.width, ty: 0.0)

因此,我在前一段时间遇到了这个问题,遵循这个RayWenderlich 教程 (您的代码看起来也非常熟悉!)。问题是assetTrack.preferredTransform不可靠,在一些视频中它可以工作,而在另一些视频上,它将是一个黑色的屏幕。

而不是

代码语言:javascript
复制
let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: compositionTrack)
layerInstruction.setTransform(assetTrack.preferredTransform, at: .zero)

试试这个:

代码语言:javascript
复制
func compositionLayerInstruction(for track: AVCompositionTrack, assetTrack: AVAssetTrack, orientation: UIImage.Orientation) -> AVMutableVideoCompositionLayerInstruction {

    let instruction = AVMutableVideoCompositionLayerInstruction(assetTrack: track)
    
    var transform = CGAffineTransform.identity
    let assetSize = assetTrack.naturalSize
    
    /// you should be able to play with these values to make a horizontal flip (try changing `a` and `d`)
    switch orientation {
    case .up:
        transform = CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0)
    case .down:
        transform = CGAffineTransform(a: -1, b: 0, c: 0, d: -1, tx: assetSize.width, ty: assetSize.height)
    case .left:
        transform = CGAffineTransform(a: 0, b: -1, c: 1, d: 0, tx: 0, ty: assetSize.width)
    case .right:
        transform = CGAffineTransform(a: 0, b: 1, c: -1, d: 0, tx: assetSize.height, ty: 0)
     default:
        print("Unsupported orientation")
    }
    
    instruction.setTransform(transform, at: .zero)
    
    return instruction
}

let layerInstruction = compositionLayerInstruction(
    for: compositionTrack, assetTrack: assetTrack, orientation: videoInfo.orientation)
/// assetTrack is the original video

我是根据另一个答案得出的,所以,我记不起在哪里了。

下面是一个帮助函数,用于获取orientation

代码语言:javascript
复制
/// adjust the video orientation is the source has a different orientation
private func orientation(from transform: CGAffineTransform) -> (orientation: UIImage.Orientation, isPortrait: Bool) {
    var assetOrientation = UIImage.Orientation.up
    var isPortrait = false
    if transform.a == 0 && transform.b == 1.0 && transform.c == -1.0 && transform.d == 0 {
        assetOrientation = .right
        isPortrait = true
    } else if transform.a == 0 && transform.b == -1.0 && transform.c == 1.0 && transform.d == 0 {
        assetOrientation = .left
        isPortrait = true
    } else if transform.a == 1.0 && transform.b == 0 && transform.c == 0 && transform.d == 1.0 {
        assetOrientation = .up
    } else if transform.a == -1.0 && transform.b == 0 && transform.c == 0 && transform.d == -1.0 {
        assetOrientation = .down
    }
    return (assetOrientation, isPortrait)
}

充分使用:

代码语言:javascript
复制
/// get adjusted orientation of the video
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
}


 /// the video
let videoLayer = CALayer()
videoLayer.frame = CGRect(origin: .zero, size: videoSize)
        
/// overlay where you add graphics and other stuff
let overlayLayer = CALayer()
overlayLayer.frame = CGRect(origin: .zero, size: videoSize)

let outputLayer = CALayer()
outputLayer.frame = CGRect(origin: .zero, size: videoSize)
outputLayer.addSublayer(videoLayer)
outputLayer.addSublayer(overlayLayer)

let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = videoSize
videoComposition.frameDuration = CMTime(value: 1, timescale: 30)
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(
postProcessingAsVideoLayer: videoLayer,
in: outputLayer)

// MARK: - previous `let layerInstruction` code goes here...

instruction.layerInstructions = [layerInstruction]

/// export session code here...
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64323672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档