我正在使用 AVCaptureSession
从设备摄像头捕获视频,然后使用 AVAssetWriterInput
和 AVAssetTrack
在上传视频之前压缩/调整视频大小到服务器。最终视频将通过 html5 视频元素在网络上观看。
我在尝试使视频的方向正确时遇到了多个问题。我的应用程序只支持横向,所有捕获的视频都应该是横向的。但是,我想允许用户在任一横向方向握住他们的设备(即左侧或右侧的主页按钮)。
我可以使用以下代码行以正确的方向显示视频预览
_previewLayer.connection.videoOrientation = UIDevice.currentDevice.orientation;
当通过 AVAssetWriterInput
和 friend 处理视频时,问题就开始了。结果似乎没有考虑到拍摄视频时采用的左右横向模式。IOW,有时视频会颠倒过来。经过一些谷歌搜索后,我发现很多人建议以下代码行可以解决这个问题
writerInput.transform = videoTrack.preferredTransform;
...但这似乎不起作用。经过一些调试后,我发现 videoTrack.preferredTransform
始终是相同的值,无论视频的捕获方向如何。
我尝试手动跟踪捕获视频的方向,并根据需要将 writerInput.transform
设置为 CGAffineTransformMakeRotation(M_PI)
。哪个解决了问题!!!
...有点
当我在设备上查看结果时,此解决方案按预期工作。无论录制时的左右方向如何,视频都是正面朝上的。不幸的是,当我在另一个浏览器(mac book 上的 chrome)中观看完全相同的视频时,它们全都颠倒了!?!?!?
我做错了什么?
编辑
这是一些代码,以防有帮助...
-(void)compressFile:(NSURL*)inUrl;
{
NSString* fileName = [@"compressed." stringByAppendingString:inUrl.lastPathComponent];
NSError* error;
NSURL* outUrl = [PlatformHelper getFilePath:fileName error:&error];
NSDictionary* compressionSettings = @{ AVVideoProfileLevelKey: AVVideoProfileLevelH264Main31,
AVVideoAverageBitRateKey: [NSNumber numberWithInt:2500000],
AVVideoMaxKeyFrameIntervalKey: [NSNumber numberWithInt: 30] };
NSDictionary* videoSettings = @{ AVVideoCodecKey: AVVideoCodecH264,
AVVideoWidthKey: [NSNumber numberWithInt:1280],
AVVideoHeightKey: [NSNumber numberWithInt:720],
AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
AVVideoCompressionPropertiesKey: compressionSettings };
NSDictionary* videoOptions = @{ (id)kCVPixelBufferPixelFormatTypeKey: [NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] };
AVAssetWriterInput* writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
writerInput.expectsMediaDataInRealTime = YES;
AVAssetWriter* assetWriter = [AVAssetWriter assetWriterWithURL:outUrl fileType:AVFileTypeMPEG4 error:&error];
assetWriter.shouldOptimizeForNetworkUse = YES;
[assetWriter addInput:writerInput];
AVURLAsset* asset = [AVURLAsset URLAssetWithURL:inUrl options:nil];
AVAssetTrack* videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
// !!! this line does not work as expected and causes all sorts of issues (videos display sideways in some cases) !!!
//writerInput.transform = videoTrack.preferredTransform;
AVAssetReaderTrackOutput* readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack outputSettings:videoOptions];
AVAssetReader* assetReader = [AVAssetReader assetReaderWithAsset:asset error:&error];
[assetReader addOutput:readerOutput];
[assetWriter startWriting];
[assetWriter startSessionAtSourceTime:kCMTimeZero];
[assetReader startReading];
[writerInput requestMediaDataWhenReadyOnQueue:_processingQueue usingBlock:
^{
/* snip */
}];
}
最佳答案
问题在于,修改 writerInput.transform
属性只会在视频文件元数据中添加一个标记,指示视频播放器在播放期间旋转文件。这就是视频在您的设备上以正确方向播放的原因(我猜它们在 Quicktime 播放器中也能正确播放)。
相机捕获的像素缓冲区仍然按照捕获时的方向排列。许多视频播放器不会检查首选方向元数据标签,只会以原始像素方向播放文件。
如果您希望用户能够在任一横向模式下手持手机录制视频,您需要在压缩前通过对每个视频的 CVPixelBuffer 执行转换在 AVCaptureSession
级别纠正此问题框架。这个 Apple Q&A 涵盖了它(也请查看 AVCaptureVideoOutput
文档):
https://developer.apple.com/library/ios/qa/qa1744/_index.html
调查上面的链接是解决问题的正确方法。解决相同问题的另一种快又脏方法是将应用的录制 UI 锁定为仅一个横向方向,然后使用 ffmpeg 在服务器端旋转所有视频。 p>
关于objective-c - AVFoundation - 为什么我不能获得正确的视频方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21845997/