一. 首先说视频压缩的几个维度
- 宽高
- 码率
- 帧率
- 编码方式
- GOP
二. 如果视频中有音轨,同时也可以压缩音轨
- 码率
- 采样率 但是对音轨体积的压缩相对于视频整体体积来说意义不大
三. 参数讲解
- 宽高:就是视频或者图像的宽高,一般单位用像素表示
- 码率:单位时间(每秒)内传输数据长度
- 帧率:单位时间(每秒)内播放的画面数量
- 通常是h264、h265,x264,x265
- 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];
}
}
音频大致相同,省略。。。。