【问题标题】:iOS: Resizing/Cropping recorded videoiOS:调整大小/裁剪录制的视频
【发布时间】:2011-06-27 06:00:53
【问题描述】:

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

我目前可以通过两种方式获取视频数据:

1) 视频录制完成后从UIImagePickerController获取文件URL

2) 获取AVCaptureSession发送的视频帧

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

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

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

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

感谢您提供的任何帮助。

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

【问题讨论】:

    标签: iphone ios video resize avfoundation


    【解决方案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)
    

    参考

    【讨论】:

      【解决方案2】:

      完美的方法是使用AVAssetReader 读取视频文件并使用AVAssetWriter 将此视频文件再次写入新的视频文件。您可以为编写器输入设置 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];
      

      您搜索苹果开发者文档以找到关于 AVAssetReader 的指导线

      【讨论】:

        【解决方案3】:

        替代方案 2 无法实时工作。

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

        使用AVAssetExportPresetLowQualityAVAssetExportPresetMediumQualityAVAssetExportPresetHighestQuality 进行实验以获得其他分辨率。

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

        【讨论】:

        • 我已经能够将视频直接录制到其中一个预设中。我正在寻找一种将视频裁剪为不属于这些预设的自定义尺寸的方法。是否不能像裁剪图像一样将视频裁剪为自定义尺寸?
        • 抱歉,我错过了“裁剪”部分。我认为视频格式的大小不如图像灵活,即手机只支持某些分辨率。裁剪通常很难看,我不推荐它,如果需要更改纵横比,请使用填充。
        【解决方案4】:

        如果有人遇到此问题,我发现如果您使用 AVMutableVideoComposition 和 AVMutableComposition,您可以使用 AVFoundation 执行此操作。然后在视频合成上设置 renderSize,这将影响视频的输出大小。然后,您使用 AVMutableVideoCompositionLayerInstruction 将视频放置在您想要的位置。有一篇很好的文章 here 介绍了所有这些类的入门,他的示例项目在末尾注释掉了用于导出它的代码。

        【讨论】:

          猜你喜欢
          • 2014-11-13
          • 1970-01-01
          • 2010-10-03
          • 1970-01-01
          • 2017-02-15
          • 2018-09-22
          • 2011-11-11
          • 2013-03-01
          • 2010-10-10
          相关资源
          最近更新 更多