在 iOS 上使用 HEVC 编码器输出巨大的视频大小

Posted

技术标签:

【中文标题】在 iOS 上使用 HEVC 编码器输出巨大的视频大小【英文标题】:Output Video Size Huge Using HEVC Encoder on iOS 【发布时间】:2017-10-16 20:17:47 【问题描述】:

我有一个项目,目前使用 H.264 编码器在 ios 上录制视频。我想尝试在 iOS 11 中使用新的 HEVC 编码器来减小文件大小,但发现使用 HEVC 编码器会导致文件大小急剧膨胀。 Here's a project on GitHub that shows the issue - it simultaneously writes frames from the camera to files using the H.264 and H.265 (HEVC) encoders, and the resulting file sizes are printed to the console.

AVFoundation 类的设置如下:

class VideoWriter 
    var avAssetWriterInput: AVAssetWriterInput
    var avAssetWriter: AVassetWriter
    init() 
        if #available(iOS 11.0, *) 
            avAssetWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: [AVVideoCodecKey:AVVideoCodecType.hevc, AVVideoHeightKey:720, AVVideoWidthKey:1280])
        
        avAssetWriterInput.expectsMediaDataInRealTime = true
        do 
            let url = directory.appendingPathComponent(UUID.init().uuidString.appending(".hevc"))
            avAssetWriter = try AVAssetWriter(url: url, fileType: AVFileType.mp4)
            avAssetWriter.add(avAssetWriterInput)
            avAssetWriter.movieFragmentInterval = kCMTimeInvalid
         catch 
            fatalError("Could not initialize AVAssetWriter \(error)")
        
    
...

然后帧是这样写的:

    func write(sampleBuffer buffer: CMSampleBuffer) 
        if avAssetWriter.status == AVAssetWriterStatus.unknown 
            avAssetWriter.startWriting()
            avAssetWriter.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(buffer))
         
        if avAssetWriterInput.isReadyForMoreMediaData 
            avAssetWriterInput.append(buffer)
        
    

当他们进入AVCaptureVideoDataOutputSampleBufferDelegate 时。在我录制的质量(720p 或 1080p)下,HEVC 编码视频的文件大小应该是相同 H.264 编码视频的 40-60%,我在使用默认相机应用程序时看到了这一点iOS,但是当我使用上面的 AVAssetWriter(或在上面链接的项目中)时,我看到 HEVC 的文件大小大约是 H.264 的三倍。要么我做错了,要么 HEVC 编码器工作不正常。我是否遗漏了什么,或者是否有解决方法让 HEVC 通过 AVFoundation 工作?

【问题讨论】:

【参考方案1】:

您是否尝试过指定比特率等? 如下:

NSUInteger bitrate = 50 * 1024 * 1024;  // 50 Mbps
NSUInteger keyFrameInterval = 30;
NSString *videoProfile = AVVideoProfileLevelH264HighAutoLevel;
NSString *codec = AVVideoCodecH264;
if (@available(iOS 11, *)) 
    videoProfile = (NSString *)kVTProfileLevel_HEVC_Main_AutoLevel;
    codec = AVVideoCodecTypeHEVC;


NSDictionary *codecSettings = @AVVideoAverageBitRateKey: @(bitrate),
                              AVVideoMaxKeyFrameIntervalKey: @(keyFrameInterval),
                              AVVideoProfileLevelKey: videoProfile;
NSDictionary *videoSettings = @AVVideoCodecKey: codec,
                              AVVideoCompressionPropertiesKey: codecSettings,
                              AVVideoWidthKey: @((NSInteger)resolution.width),
                              AVVideoHeightKey: @((NSInteger)resolution.height);

AVAssetWriterInput *videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
...

据我了解,在相同的比特率下,H264 和 HEVC 的文件大小应该相同,但 HEVC 的质量应该更好。

【讨论】:

我收到了 Apple 的类似回复。显然,H.264 的默认比特率是 5mbit,而 HEVC 是 30mbit。如果我尝试一下并且有效,我会报告并接受您的回答! @jpetrichsr 我希望我能早点发现这一点。默认值的差异是惊人的。您不会认为简单地更改编解码器标志会在您预期的 相反 方向上导致完全疯狂的结果。通过提高比特率来利用 h265,我可以看到相同的输出大小是合理的,但是如果你不密切注意的话,这真的会烧死你。 大家好,我正在尝试同样的事情(Swift 除外),奇怪的是,使用 h.264 时,我可以将特定的视频文件(1 分钟)缩小到 10MB,而使用 hevc不管我把比特率多低,它都不会低于 19MB。使用 h.264,它下降到 6MB,之后比特率不再减小文件大小。使用 hevc / h.265 这只是发生的方式,方式更早。有什么办法吗? @unixb0y 你对此有进一步了解吗?我遇到了同样的问题 @skeg0 不,我不这么认为:/【参考方案2】:

使用exportSession.fileLengthLimit = 1048576 * 10 //10 MB

10MB 是硬编码数字。根据你需要的码率使用。

【讨论】:

以上是关于在 iOS 上使用 HEVC 编码器输出巨大的视频大小的主要内容,如果未能解决你的问题,请参考以下文章

无法在 HEVC 解码器 IMFTransform 上设置输出类型

HEVC视频编码技术

hevc和h.264的区别

iOS ijkplayer 硬解H265(hevc)4k视频问题解决

iOS ijkplayer 硬解H265(hevc)4k视频问题解决

Codecs系列H.265/HEVC视频编码技术汇总——导航页