objective-c - AVFoundation - 为什么我不能获得正确的视频方向

标签 objective-c avfoundation

我正在使用 AVCaptureSession 从设备摄像头捕获视频,然后使用 AVAssetWriterInputAVAssetTrack 在上传视频之前压缩/调整视频大小到服务器。最终视频将通过 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/

相关文章:

objective-c - 向 CGPoint 类型参数发送 nil

ios - 将 Assets 放入声音缓冲区

ios - 如何识别 AVPlayer 处于暂停状态并且用户正在清理

swift - 如何在录制时获取 AVCaptureMovieFileOutput 的当前长度以显示在屏幕上?

macos - 从 AVPlayerItemVideoOutput 到 openGL 纹理的最佳路径

iphone - iphone 无法解释的段错误

ios - 无法从呈现的 View Controller 访问委托(delegate)方法

objective-c - Xcode 4.5 中数组的新语法?

iPhone:从一个位置选择一个文件上传到服务器

ios - AVPlayer 不播放本地视频