奇怪的裁剪行为

时间:2015-11-27 12:11:17

标签: ios encoding camera avassetexportsession

当尝试使用带有readme示例的SDAVAssetExportSession将MOV重新编码为MP4时,我使用后置摄像头设备左右边框,并使用前置摄像头进行方形裁剪。

没有任何重新编码,我的播放器(PBJVideoPlayerController,使用AVLayerVideoGravityResizeAspectFill)正确显示全屏视频。

我猜SDAVAssetExportSession的renderSize有问题,但我真的不明白为什么其他人似乎没有这个问题。

以下是重新编码后前后摄像头的屏幕截图:

没有重新编码的视频截图,后置摄像头(完全全屏): Screenshot of video without re-encoding, rear camera (perfectly fullscreen)

带有重新编码的视频截图,后置摄像头: Screenshot of video with re-encoding, rear camera

带有重新编码的视频截图,前置摄像头 Screenshot of video with re-encoding, front camera

正如您所看到的,播放器应该不是问题,因为没有重新编码就一切正常。但出口后,边框出现在后面,我不知道 - 真的知道 - 前置摄像头会发生什么......

任何帮助?

谢谢!

PS:像我的咖啡碗一样?

1 个答案:

答案 0 :(得分:1)

我也在使用SDAVAssetExportSession,并且我已经意识到如果你给肖像视频的宽度超过高度并偏离它所需的宽高比,就会发生糟糕的视频裁剪。如果你给它的高度超过宽度,那么景观视频也会出现同样的情况。

我的解决方案是在转码前先获取视频宽高比和当前尺寸,然后根据当前尺寸计算较小的宽度和高度,以保持纵横比。这将使得到的视频不会出现黑色边框。

更新:这是相关代码 -

这显示了如何调整大小并保持纵横比并避免裁剪问题。请注意,widthheight是由用户控制的整数变量。如果没有提供,我会使用原始视频宽度和高度进行转码。

AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:assetPath] options:nil];

NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *outputPath = [NSString stringWithFormat:@"%@/%@%@", cacheDir, videoFileName, outputExtension];
NSURL *outputURL = [NSURL fileURLWithPath:outputPath];

NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeVideo];
AVAssetTrack *track = [tracks objectAtIndex:0];
CGSize mediaSize = track.naturalSize;

float videoWidth = mediaSize.width;
float videoHeight = mediaSize.height;
float aspectRatio = videoWidth / videoHeight;
int newWidth = (width && height) ? height * aspectRatio : videoWidth;
int newHeight = (width && height) ? newWidth / aspectRatio : videoHeight;

NSLog(@"input videoWidth: %f", videoWidth);
NSLog(@"input videoHeight: %f", videoHeight);
NSLog(@"output newWidth: %d", newWidth);
NSLog(@"output newHeight: %d", newHeight);

SDAVAssetExportSession *encoder = [SDAVAssetExportSession.alloc initWithAsset:avAsset];
encoder.outputFileType = stringOutputFileType;
encoder.outputURL = outputURL;
encoder.videoSettings = @
{
    AVVideoCodecKey: AVVideoCodecH264,
    AVVideoWidthKey: [NSNumber numberWithInt: newWidth],
    AVVideoHeightKey: [NSNumber numberWithInt: newHeight],
    AVVideoCompressionPropertiesKey: @
    {
        AVVideoAverageBitRateKey: [NSNumber numberWithInt: videoBitRate],
        AVVideoProfileLevelKey: AVVideoProfileLevelH264High40
    },
};