//自定义裁剪视频
+ (void)getclipingVideoWithVideoAsset:(AVAsset *)asset
success:(void (^)(NSString *))success
failure:(void (^)(NSString *))failure{
NSString *outPutPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"/video/video1.mp4"];
NSLog(@"video outputPath:\n %@\n",outPutPath);
AVAssetReader *reader = [AVAssetReader assetReaderWithAsset:asset error:nil];
AVAssetWriter *write = [AVAssetWriter assetWriterWithURL:[NSURL URLWithString:outPutPath] fileType:AVFileTypeMPEG4 error:nil];
//video part
AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
AVAssetReaderTrackOutput *videoOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack outputSettings:[self videoOutputSettings]];//输出
AVAssetWriterInput *videoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:[self videoCompressSettings]];//输入
if ([reader canAddOutput:videoOutput]) {
[reader addOutput:videoOutput];
}
if ([write canAddInput:videoInput]) {
[write addInput:videoInput];
}
//audio part
AVAssetTrack *audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;
AVAssetReaderTrackOutput *audioOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:[self audioOutputSettings]];
AVAssetWriterInput *audioInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:[self audioCompressSettings]];
if ([reader canAddOutput:audioOutput]) {
[reader addOutput:audioOutput];
}
if ([write canAddInput:audioInput]) {
[write addInput:audioInput];
}
//开始读写
[reader startReading];
[write startWriting];
[write startSessionAtSourceTime:kCMTimeZero];
dispatch_queue_t video_compression_queue = dispatch_queue_create("com.video_compression_queue.queue", NULL);
dispatch_queue_t audio_compression_queue = dispatch_queue_create("com.video_compression_queue.queue", NULL);
dispatch_group_t group = dispatch_group_create();
//视频逐帧写入
dispatch_group_enter(group);
[videoInput requestMediaDataWhenReadyOnQueue:video_compression_queue usingBlock:^{
while ([videoInput isReadyForMoreMediaData]) {
CMSampleBufferRef sampleBuffer;
if (reader.status == AVAssetReaderStatusReading && (sampleBuffer = [videoOutput copyNextSampleBuffer])) {
BOOL reslut = [videoInput appendSampleBuffer:sampleBuffer];
CFRelease(sampleBuffer);
if (!reslut) {
[reader cancelReading];
break;
}
}else{
[videoInput markAsFinished];
dispatch_group_leave(group);
break;
}
}
}];
//音频逐帧写入
dispatch_group_enter(group);
[audioInput requestMediaDataWhenReadyOnQueue:audio_compression_queue usingBlock:^{
while ([audioInput isReadyForMoreMediaData]) {
CMSampleBufferRef sampleBuffer;
if (reader.status == AVAssetReaderStatusReading && (sampleBuffer = [audioOutput copyNextSampleBuffer])) {
BOOL result = [audioInput appendSampleBuffer:sampleBuffer];
if (!result) {
[reader cancelReading];
break;
}
}else{
[audioInput markAsFinished];
dispatch_group_leave(group);
break;
}
}
}];
//完成压缩
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (reader.status == AVAssetReaderStatusReading) {
[reader cancelReading];
}
switch (write.status) {
case AVAssetWriterStatusWriting:{
[write finishWritingWithCompletionHandler:^{
NSLog(@"the size video at %@ is %0.2f M",outPutPath, [NSString getFileSize:outPutPath]);
}];
}break;
default:
break;
}
});
}
//视频输出配置
+(NSDictionary *)videoOutputSettings{
NSDictionary *videoOutputSettings = @{
(id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_422YpCbCr8),
(id)kCVPixelBufferIOSurfacePropertiesKey :@{}
};
return videoOutputSettings;
}
//视频输入配置
+(NSDictionary *)videoCompressSettings{
NSDictionary *compressionProperties = @{
AVVideoAverageBitRateKey:@(200 * 8 * 1024),
AVVideoExpectedSourceFrameRateKey:@25,
AVVideoProfileLevelKey : AVVideoProfileLevelH264HighAutoLevel
};
NSDictionary *videoCompressSettings = @{
AVVideoCodecKey : UIDevice.systemVersion >= 11.0 ? AVVideoCodecTypeH264:AVVideoCodecH264,
AVVideoWidthKey : @960,
AVVideoHeightKey : @540,
AVVideoCompressionPropertiesKey : compressionProperties,
AVVideoScalingModeKey : AVVideoScalingModeResizeAspectFill
};
return videoCompressSettings;
}
//音频输出配置
+(NSDictionary *)audioOutputSettings{
NSDictionary *audioOutputSettings = @{
AVFormatIDKey : @(kAudioFormatLinearPCM)
};
return audioOutputSettings;
}
//音频输入配置
+(NSDictionary *)audioCompressSettings{
AudioChannelLayout stereoChannelLayout = {
.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo,
.mChannelBitmap = 0,
.mNumberChannelDescriptions = 0
};
NSData *channelLayoutAsData = [NSData dataWithBytes:&stereoChannelLayout length:offsetof(AudioChannelLayout, mChannelDescriptions)];
NSDictionary *audioCompressSettings = @{
AVFormatIDKey : @(kAudioFormatMPEG4AAC),
AVEncoderBitRateKey:@96000,
AVSampleRateKey:@44100,
AVChannelLayoutKey: channelLayoutAsData,
AVNumberOfChannelsKey : @2
};
return audioCompressSettings;
}