使用 AVMutableVideoComposition 导出后呈现为横向的纵向视频

Portrait video rendered as landscape after exporting with AVMutableVideoComposition

你好,我将两个视频与 AVMutableVideoComposition() 组合在一起,它适用于从 youtube 下载的横向视频和纵向视频,但是当尝试在 iPhone 或 android 中录制的纵向视频时,导出的视频出现 landscape/horizontal 而不是原始纵向/垂直。

如果对堆栈溢出和 google 进行了大量研究,但找不到任何可行的解决方案。

这篇 raywenderlich 的文章很好地解释了为什么视频处于横向模式,并在文章的 Orienting Video 部分提供了解决方法,首先检查视频是否为纵向,然后设置它的高度宽度和首选方向。但它不再起作用了。

我尝试手动将 AVAssetTrack 的 .preferredTransform 设置为 CGAffineTransform(a: 0.0, b: 1.0, c: -1.0, d: 0.0, tx: 0.0, ty: 0.0) 但不起作用。

许多旧答案建议将 AVAssetTrack 的 .preferredTransform 设置为 AvAsset 的 preferredTransform 但它不起作用。

从 AVAssetTrack 的 .preferredTransform 我可以知道视频是否为纵向但无法更改它,非常感谢任何帮助,谢谢。

在搜索并尝试了很多事情之后,我这样做来解决问题,首先我使用 raywenderlich 文章中的这个功能检查方向。

  func orientationFromTransform(
  _ transform: CGAffineTransform
) -> (orientation: UIImage.Orientation, isPortrait: Bool) {
  var assetOrientation = UIImage.Orientation.up
  var isPortrait = false
  let tfA = transform.a
  let tfB = transform.b
  let tfC = transform.c
  let tfD = transform.d

  if tfA == 0 && tfB == 1.0 && tfC == -1.0 && tfD == 0 {
    assetOrientation = .right
    isPortrait = true
  } else if tfA == 0 && tfB == -1.0 && tfC == 1.0 && tfD == 0 {
    assetOrientation = .left
    isPortrait = true
  } else if tfA == 1.0 && tfB == 0 && tfC == 0 && tfD == 1.0 {
    assetOrientation = .up
  } else if tfA == -1.0 && tfB == 0 && tfC == 0 && tfD == -1.0 {
    assetOrientation = .down
  }
  return (assetOrientation, isPortrait)
}

并存储它

let firstAssetInfo = orientationFromTransform(firstVideoTrack!.preferredTransform)

然后在添加转换指令之前,我检查它是否为纵向,然后手动将其转换为纵向并根据其设置缩放比例,并将其宽度用作高度,将高度用作宽度,如果它不是纵向,则执行我正在做的事情之前。

    let firstLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: firstTrack!)
    
    if firstAssetInfo.isPortrait {
        
        let rotate = __CGAffineTransformMake(0.0, 1.0, -1.0, 0.0, 0.0, 0.0)
        let scale = CGAffineTransform(scaleX: firstPosScale.videoScale.x, y: firstPosScale.videoScale.y)
        let move = CGAffineTransform(translationX: firstPosScale.videoLocation.x, y: firstPosScale.videoLocation.y)
        let transform = rotate.concatenating(scale).concatenating(move)
        firstLayerInstruction.setTransform(transform, at: .zero)
        
    } else {
        
        let scale = CGAffineTransform(scaleX: firstPosScale.videoScale.x, y: firstPosScale.videoScale.y)
        let move = CGAffineTransform(translationX: firstPosScale.videoLocation.x, y: firstPosScale.videoLocation.y)
        let transform = scale.concatenating(move)
        firstLayerInstruction.setTransform(transform, at: .zero)
    }

07:16:45.410 I/TrackGather updateClient client=TrackClient@51a7a21a{tag=5c2da814} 07:16:45.411 I/TrackUpload updateClient client=TrackClient@51a7a21a{tag=5c2da814} 07:16:45.414 I/TrackController onAppStateChanged state=FOREGROUND page=SplashActivity 07:16:45.484 I/TrackUploadCacheTask 上传任务因客户端存在而被忽略 07:16:45.872 I/TrackController onAppStateChanged state=FOREGROUND page=HomePageActivity 07:16:46.199 I/TrackController onAppStateChanged state=FOREGROUND page=HomePageActivity 07:16:46.628 I/TrackLoc onDirectLocError