奇怪的裁剪行为
Strange cropping behaviour
当尝试使用来自 readme 的示例使用 SDAVAssetExportSession 将 MOV 重新编码为 MP4 时,我在使用后置摄像头设备时得到左右边框,使用前置摄像头时得到方形裁剪。
在没有任何重新编码的情况下,我的播放器(PBJVideoPlayerController,使用 AVLayerVideoGravityResizeAspectFill)可以正确显示全屏视频。
我猜想 SDAVAssetExportSession 的 renderSize 有问题,但我真的不明白为什么其他人似乎没有这个问题。
以下是重新编码后前后摄像头的截图:
没有重新编码的视频截图,后置摄像头(完美全屏):
重新编码后的视频截图,后置摄像头:
重新编码后的视频截图,前置摄像头
如您所见,播放器应该不是问题,因为无需重新编码一切正常。但是导出后,边框出现在后方,我不知道真的不知道前置摄像头会发生什么...
有什么帮助吗?
谢谢!
PS : 喜欢我的咖啡碗吗?
我也在使用 SDAVAssetExportSession 并且我意识到如果您给纵向视频的宽度大于高度并且偏离它需要的宽高比,将会发生错误的视频裁剪。如果你给它的高度大于宽度,横向视频也会发生同样的情况。
我的解决办法是在转码前先获取视频的宽高比和当前尺寸,然后根据当前尺寸计算出较小的宽度和高度,以保持宽高比。这将使生成的视频没有黑边。
更新:这是相关代码 -
这显示了如何调整大小并保持纵横比并避免裁剪问题。请注意,width
和 height
是由用户控制的整数变量。如果没有提供,我会使用原始视频的宽度和高度进行转码。
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
},
};
当尝试使用来自 readme 的示例使用 SDAVAssetExportSession 将 MOV 重新编码为 MP4 时,我在使用后置摄像头设备时得到左右边框,使用前置摄像头时得到方形裁剪。
在没有任何重新编码的情况下,我的播放器(PBJVideoPlayerController,使用 AVLayerVideoGravityResizeAspectFill)可以正确显示全屏视频。
我猜想 SDAVAssetExportSession 的 renderSize 有问题,但我真的不明白为什么其他人似乎没有这个问题。
以下是重新编码后前后摄像头的截图:
没有重新编码的视频截图,后置摄像头(完美全屏):
重新编码后的视频截图,后置摄像头:
重新编码后的视频截图,前置摄像头
如您所见,播放器应该不是问题,因为无需重新编码一切正常。但是导出后,边框出现在后方,我不知道真的不知道前置摄像头会发生什么...
有什么帮助吗?
谢谢!
PS : 喜欢我的咖啡碗吗?
我也在使用 SDAVAssetExportSession 并且我意识到如果您给纵向视频的宽度大于高度并且偏离它需要的宽高比,将会发生错误的视频裁剪。如果你给它的高度大于宽度,横向视频也会发生同样的情况。
我的解决办法是在转码前先获取视频的宽高比和当前尺寸,然后根据当前尺寸计算出较小的宽度和高度,以保持宽高比。这将使生成的视频没有黑边。
更新:这是相关代码 -
这显示了如何调整大小并保持纵横比并避免裁剪问题。请注意,width
和 height
是由用户控制的整数变量。如果没有提供,我会使用原始视频的宽度和高度进行转码。
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
},
};