IOS视频压缩

一. 首先说视频压缩的几个维度

  1. 宽高
  2. 码率
  3. 帧率
  4. 编码方式
  5. GOP

二. 如果视频中有音轨,同时也可以压缩音轨

  1. 码率
  2. 采样率 但是对音轨体积的压缩相对于视频整体体积来说意义不大

三. 参数讲解

  1. 宽高:就是视频或者图像的宽高,一般单位用像素表示
  2. 码率:单位时间(每秒)内传输数据长度
  3. 帧率:单位时间(每秒)内播放的画面数量
  4. 通常是h264、h265,x264,x265
  5. GOP:两个关键帧的距离,关键帧中间有多少个非关键帧 一般情况下短视频或者直播使用264编码即可,因为现在带宽都够,数据量大一些可以接受,264相对264压缩率会更高,但是转码过程中功耗相对较大,可以权衡利弊。 h和x的区别无非就是硬编码和软编码,硬编、解码就是使用硬件,一般是gpu去编码,厂家会自己去针对自己的gpu或者cpu去实现264和265的编码协议,所以硬编、解码一般功耗小,速度快。 软编码、解码是软件厂商使用系统上层api去实现的265和264协议,所以一般无法做到效率很高,但是优势在于可以跨平台,无视硬件。

目前游戏直播,斗鱼,全民这些都使用265编码,因为一般观看者和主播很多都使用pc,性能够,而且支持动态切换分辨率(宽高)

手机端秀场直播一般采用264编码,视频尺寸大约在1000x2500这样,帧率在16-24之间,码率 20081024,可以设置为动态码率,适应手机性能和网络波动。 码率影响的东西比较多,比如画面压缩程度,非关键帧的压缩程度

GOP:加入视频帧率是16帧,那么GOP一般设置为32,也就是两个关键帧就可以播放2s的视频,但同时也需要完全加载完两个关键帧才可以播放视频,如果是直播,那么用户和主播间的视频时差最小就是2s,这个根据业务尔定

四. 代码实现

方法声明
+ (void)compressWithVideoURL:(NSURL *)videoURL          // 视频数据源路径
                   outputURL:(NSURL *)outputURL         // 压缩后输出路径
                         fps:(NSInteger)fps             // 帧率
                     bitRate:(NSInteger)bitRate         // 码率
              dimensionScale:(CGFloat)dimensionScale
                  completion:(void(^)(BOOL success))completion;
// 创建视频asset
AVAsset *videoAsset = [AVAsset assetWithURL:videoURL];
NSError *readerError;
// asset读取器
AVAssetReader *reader = [AVAssetReader assetReaderWithAsset:videoAsset error:&readerError];
NSError *writerError;
// asset写入器
AVAssetWriter *writer = [AVAssetWriter assetWriterWithURL:outputURL fileType:AVFileTypeMPEG4 error:&writerError];
// 获取视频轨道
AVAssetTrack *videoTrack = [videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
AVAssetWriterInput *videoInput;
AVAssetReaderOutput *videoOutput;
    if (videoTrack) {
        NSDictionary *videoOutputSetting = @{
              (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_422YpCbCr8]
            };
            
        videoOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack outputSettings:videoOutputSetting];
        
        NSDictionary *videoCompressProperties = @{
            AVVideoAverageBitRateKey : @(bitRate),        // 码率
            AVVideoExpectedSourceFrameRateKey : @(fps),   // 帧率
            AVVideoProfileLevelKey : AVVideoProfileLevelH264HighAutoLevel
        };
        
        CGSize videoSize = [self sizeWithVideoURL:videoURL];
        CGFloat videoWidth = videoSize.width;
        CGFloat videoHeight = videoSize.height;
        NSDictionary *videoCompressSettings = @{
            AVVideoCodecKey : AVVideoCodecTypeH264,
            AVVideoWidthKey : @(videoWidth * dimensionScale),
            AVVideoHeightKey :@(videoHeight * dimensionScale),
            AVVideoCompressionPropertiesKey : videoCompressProperties,
            AVVideoScalingModeKey : AVVideoScalingModeResizeAspectFill
        };
        
        videoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoCompressSettings];
        videoInput.transform = videoTrack.preferredTransform;
        if ([reader canAddOutput:videoOutput]) {
            [reader addOutput:videoOutput];
        }
        
        if ([writer canAddInput:videoInput]) {
            [writer addInput:videoInput];
        }
    }

音频大致相同,省略。。。。

代码地址 https://github.com/Alienchang/VideoCompresser

Continue reading

Author's picture

刘畅

记录生活学习

iOS资深开发工程师

中国