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

时间:2011-02-14 22:30:42

标签: iphone ios video resize avfoundation

在iphone上调整用户录制视频大小的最佳方法是什么?

我目前有能力以两种方式获取视频数据:

1)在录制视频后从UIImagePickerController获取文件网址

2)获取AVCaptureSession

发送的视频帧

对于1)我需要能够读取.mov h.264文件并吐出单个帧的东西。有这样的事吗?

对于2)我想到为每个帧获取UIImage,调整图像大小,然后使用类似AVAssetWriter的内容重新编译视频。但这似乎是一个非常密集的操作,我想知道是否有更好的方法来解决这个问题。

调整视频大小的一般想法是调整每个帧的大小,然后重新编译视频吗?或者有没有办法直接调整整个视频的大小?

我只是基本上需要用户录制视频,然后将该视频调整为320x320,没有花哨的编辑。

感谢您提供的任何帮助。

编辑:也许'调整大小'是错误的词。我真的只需要裁剪视频,使其从480x360变为320x320。此裁剪也不需要实时进行,我可以在录制视频后进行裁剪。

4 个答案:

答案 0 :(得分:3)

如果有人遇到过AVMutableVideoComposition和AVMutableComposition,我发现你可以用AVFoundation做到这一点。然后,您在视频合成上设置renderSize,这将影响视频的输出大小。然后使用AVMutableVideoCompositionLayerInstruction将视频定位在您想要的位置。关于所有这些类的入门有一篇很好的文章here,他的示例项目在最后注释了代码以便导出它。

答案 1 :(得分:3)

完美的方法是使用AVAssetReader来阅读视频文件,并使用AVAssetWriter将此视频文件再次写入新的视频文件。您可以为writer输入设置outputSetting:

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];

您搜索Apple开发人员文档以查找有关AVAssetReader

的guid行

答案 2 :(得分:2)

备选方案2无法实时运作。

对于备选方案1,请使用已使用所需预设之一初始化的AVAssetExportSession - 例如AVAssetExportPreset640x480

尝试使用AVAssetExportPresetLowQualityAVAssetExportPresetMediumQualityAVAssetExportPresetHighestQuality进行其他解析。

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

答案 3 :(得分:0)

您需要考虑视频方向。这是一个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)

参考