在iphone上调整用户录制视频大小的最佳方法是什么?
我目前有能力以两种方式获取视频数据:
1)在录制视频后从UIImagePickerController
获取文件网址
2)获取AVCaptureSession
对于1)我需要能够读取.mov h.264文件并吐出单个帧的东西。有这样的事吗?
对于2)我想到为每个帧获取UIImage,调整图像大小,然后使用类似AVAssetWriter
的内容重新编译视频。但这似乎是一个非常密集的操作,我想知道是否有更好的方法来解决这个问题。
调整视频大小的一般想法是调整每个帧的大小,然后重新编译视频吗?或者有没有办法直接调整整个视频的大小?
我只是基本上需要用户录制视频,然后将该视频调整为320x320,没有花哨的编辑。
感谢您提供的任何帮助。
编辑:也许'调整大小'是错误的词。我真的只需要裁剪视频,使其从480x360变为320x320。此裁剪也不需要实时进行,我可以在录制视频后进行裁剪。
答案 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
答案 2 :(得分:2)
备选方案2无法实时运作。
对于备选方案1,请使用已使用所需预设之一初始化的AVAssetExportSession
- 例如AVAssetExportPreset640x480
。
尝试使用AVAssetExportPresetLowQuality
,AVAssetExportPresetMediumQuality
,AVAssetExportPresetHighestQuality
进行其他解析。
请注意,视频文件的宽高比通常为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)
参考