iOS:调整/裁剪录制的视频

6
什么是在iPhone上调整用户录制视频大小的最佳方法?
我目前有两种获取视频数据的方法:
1)在视频被录制后,从UIImagePickerController获取文件URL;
2)通过AVCaptureSession发送视频时获取其帧。
对于1),我需要某种可以读取.mov h.264文件并输出单个帧的工具。是否有这样的工具?
对于2),我考虑为每个帧获取UIImage,调整图像大小,然后使用类似AVAssetWriter的东西重新编译视频。但是这似乎是一项非常密集的操作,我想知道是否有更好的方法来解决这个问题。
调整视频大小的一般方法是调整每个单独的帧,然后重新编译视频吗?还是有一种直接调整整个视频大小的方法?
我只需要用户录制视频,然后将该视频调整大小为320x320,不需要任何高级编辑。
感谢您提供的任何帮助。
编辑:也许“调整大小”这个词用错了。 我真正需要做的是裁剪视频,使其从480x360变为320x320。此外,这种裁剪不需要实时进行,我可以在视频录制后进行。
4个回答

5
如果有人遇到这个问题,我发现您可以使用AVFoundation来实现,只需使用AVMutableComposition和AVMutableVideoComposition。然后在视频合成中设置renderSize,这将影响视频的输出大小。接下来,您需要使用AVMutableVideoCompositionLayerInstruction将视频定位到所需位置。在这里有一篇很好的文章介绍如何使用所有这些类,他的示例项目在末尾有用于导出的代码(注释掉了)。

4

最好的方法是使用AVAssetReader读取视频文件,然后使用AVAssetWriter将该视频文件再次写入新的视频文件中。您可以为编写器输入设置输出设置:

NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:
                                  AVVideoCodecH264, AVVideoCodecKey,
                                  [NSNumber numberWithInt: 480], AVVideoWidthKey,
                                  [NSNumber numberWithInt: 480], AVVideoHeightKey,
                                      AVVideoScalingModeResizeAspectFill,AVVideoScalingModeKey,
                                  nil];
        NSLog(@"%@",[assetVideoTrack mediaType]);
assetWriterVideoInput = [AVAssetWriterInput assetWriterInputWithMediaType: [assetVideoTrack mediaType]
                                                                   outputSettings:settings];
        [assetWriter addInput:assetWriterVideoInput];

您搜索苹果开发者文档以查找有关AVAssetReader的指导方针。


3

替代方案2在实时情况下不可行。

对于替代方案1,使用初始化为所需预设之一的AVAssetExportSession - 例如AVAssetExportPreset640x480

尝试使用AVAssetExportPresetLowQualityAVAssetExportPresetMediumQualityAVAssetExportPresetHighestQuality获取其他分辨率的视频。

请注意,视频文件通常具有16:9(或4:3)的宽高比,因此320x320不是有效选项。除非您计划分发到其他手机,否则没有理由将大小调整为不支持的分辨率,在这种情况下,服务器端转码是可用的。


我已经能够直接将视频录制到其中一个预设中了。我正在寻找的是一种将视频裁剪到不属于这些预设的自定义尺寸的方法。难道不能像处理图像一样裁剪视频到自定义尺寸吗? - nebs
抱歉,我错过了“裁剪”部分。我认为视频格式的大小不像图像那样灵活,即移动设备仅支持某些分辨率。裁剪通常很丑陋,我不建议使用它,如果需要更改纵横比,请使用填充。 - ThomasRS

1

你需要考虑视频方向。这里是一个Swift 2的解决方案。它可以裁剪和缩放视频。

extension AVAsset {

  private var g_naturalSize: CGSize {
    return tracksWithMediaType(AVMediaTypeVideo).first?.naturalSize ?? .zero
  }

  var g_correctSize: CGSize {
    return g_isPortrait ? CGSize(width: g_naturalSize.height, height: g_naturalSize.width) : g_naturalSize
  }

  var g_isPortrait: Bool {
    let portraits: [UIInterfaceOrientation] = [.Portrait, .PortraitUpsideDown]
    return portraits.contains(g_orientation)

  // Same as UIImageOrientation
  var g_orientation: UIInterfaceOrientation {
    guard let transform = tracksWithMediaType(AVMediaTypeVideo).first?.preferredTransform else {
      return .Portrait
    }

    switch (transform.tx, transform.ty) {
    case (0, 0):
      return .LandscapeRight
    case (g_naturalSize.width, g_naturalSize.height):
      return .LandscapeLeft
    case (0, g_naturalSize.width):
      return .PortraitUpsideDown
    default:
      return .Portrait
    }
  }
}

这里是获取变换的方法

func transform(avAsset: AVAsset, scaleFactor: CGFloat) -> CGAffineTransform {
    let offset: CGPoint
    let angle: Double

    switch avAsset.g_orientation {
    case .LandscapeLeft:
      offset = CGPoint(x: avAsset.g_correctSize.width, y: avAsset.g_correctSize.height)
      angle = M_PI
    case .LandscapeRight:
      offset = CGPoint.zero
      angle = 0
    case .PortraitUpsideDown:
      offset = CGPoint(x: 0, y: avAsset.g_correctSize.height)
      angle = -M_PI_2
    default:
      offset = CGPoint(x: avAsset.g_correctSize.width, y: 0)
      angle = M_PI_2
    }

    let scale = CGAffineTransformMakeScale(scaleFactor, scaleFactor)
    let translation = CGAffineTransformTranslate(scale, offset.x, offset.y)
    let rotation = CGAffineTransformRotate(translation, CGFloat(angle))

    return rotation
  }

如何在层指令中使用它

let layer = AVMutableVideoCompositionLayerInstruction(assetTrack: track)
layer.setTransform(transform(avAsset, scaleFactor: 0.8), atTime: kCMTimeZero)

参考资料


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接