AVAssetWriter破坏由AVAssetExportSession修剪的video

我正在修剪,然后压缩一个video文件。

  1. 为了修剪,我正在使用AVAssetExportSession
  2. 对于压缩,我正在使用AVAssetWriter

如果我单独使用这两个代码,每件事情都可以正常工作,但是如果我修剪,然后input压缩输出进行压缩,我得到了压缩,但损坏的video。

 - (void)viewDidLoad { [super viewDidLoad]; [self trimVideo]; } 

修剪代码

 -(void)trimVideo { AVAsset *anAsset = [[AVURLAsset alloc]initWithURL:[self.asset valueForProperty:ALAssetPropertyAssetURL] options:nil]; AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:anAsset presetName:AVAssetExportPresetPassthrough]; NSString *fName = [NSString stringWithFormat:@"%@.%@", @"tempVid", @"mp4"]; saveURL = [NSURL fileURLWithPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:fName]]; NSString *fName1 = [NSString stringWithFormat:@"%@.%@", @"tempVid1", @"mp4"]; saveURL1 = [NSURL fileURLWithPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:fName1]]; exportSession.outputURL = saveURL; exportSession.outputFileType = AVFileTypeMPEG4; CMTime start = CMTimeMakeWithSeconds(1.0, 600); CMTime duration = CMTimeMakeWithSeconds(180.0, 600); CMTimeRange range = CMTimeRangeMake(start, duration); exportSession.timeRange = range; [exportSession exportAsynchronouslyWithCompletionHandler:^{ switch ([exportSession status]) { case AVAssetExportSessionStatusFailed: NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]); break; case AVAssetExportSessionStatusCancelled: NSLog(@"Export canceled"); break; case AVAssetExportSessionStatusCompleted: [self convertVideoToLowQuailtyWithInputURL:saveURL outputURL:saveURL1]; break; default: break; } }]; } 

压缩代码

 - (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL { AVAsset *videoAsset = [[AVURLAsset alloc] initWithURL:inputURL options:nil]; AVAssetTrack *videoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; //CGSize videoSize = videoTrack.naturalSize; NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey, [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:960000],AVVideoAverageBitRateKey, AVVideoProfileLevelH264Main32, AVVideoProfileLevelKey, [NSNumber numberWithInt:24], AVVideoMaxKeyFrameIntervalKey, [NSNumber numberWithInt:0.0], AVVideoMaxKeyFrameIntervalDurationKey, nil], AVVideoCompressionPropertiesKey, [NSNumber numberWithInt:640], AVVideoWidthKey, [NSNumber numberWithInt:320], AVVideoHeightKey, nil]; AVAssetWriterInput* videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:settings]; videoWriterInput.expectsMediaDataInRealTime = YES; videoWriterInput.transform = videoTrack.preferredTransform; AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:outputURL fileType:AVFileTypeQuickTimeMovie error:nil]; [videoWriter addInput:videoWriterInput]; NSDictionary *videoReaderSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]; AVAssetReaderTrackOutput *videoReaderOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:videoTrack outputSettings:videoReaderSettings]; AVAssetReader *videoReader = [[AVAssetReader alloc] initWithAsset:videoAsset error:nil]; [videoReader addOutput:videoReaderOutput]; AVAssetWriterInput* audioWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:nil]; audioWriterInput.expectsMediaDataInRealTime = NO; [videoWriter addInput:audioWriterInput]; AVAssetTrack* audioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; AVAssetReaderOutput *audioReaderOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:nil]; AVAssetReader *audioReader = [AVAssetReader assetReaderWithAsset:videoAsset error:nil]; [audioReader addOutput:audioReaderOutput]; [videoWriter startWriting]; [videoReader startReading]; [videoWriter startSessionAtSourceTime:kCMTimeZero]; dispatch_queue_t processingQueue = dispatch_queue_create("processingQueue1", NULL); [videoWriterInput requestMediaDataWhenReadyOnQueue:processingQueue usingBlock: ^{ while ([videoWriterInput isReadyForMoreMediaData]) { CMSampleBufferRef sampleBuffer; if ([videoReader status] == AVAssetReaderStatusReading && (sampleBuffer = [videoReaderOutput copyNextSampleBuffer])) { [videoWriterInput appendSampleBuffer:sampleBuffer]; CFRelease(sampleBuffer); } else { [videoWriterInput markAsFinished]; if ([videoReader status] == AVAssetReaderStatusCompleted) { //start writing from audio reader [audioReader startReading]; [videoWriter startSessionAtSourceTime:kCMTimeZero]; dispatch_queue_t processingQueue = dispatch_queue_create("processingQueue2", NULL); [audioWriterInput requestMediaDataWhenReadyOnQueue:processingQueue usingBlock:^{ while (audioWriterInput.readyForMoreMediaData) { CMSampleBufferRef sampleBuffer; if ([audioReader status] == AVAssetReaderStatusReading && (sampleBuffer = [audioReaderOutput copyNextSampleBuffer])) { [audioWriterInput appendSampleBuffer:sampleBuffer]; CFRelease(sampleBuffer); } else { [audioWriterInput markAsFinished]; if ([audioReader status] == AVAssetReaderStatusCompleted) { [videoWriter finishWritingWithCompletionHandler:^(){ NSLog(@"Success"); }]; } } } } ]; } } } } ]; } 

您必须使用AVMutableCompositionTrack类和媒体文件修剪,您必须使用- (void)removeTimeRange:(CMTimeRange)timeRange方法。

 AVAsset *videoAsset = <#AVAsset with at least one video track#>; AVAssetTrack *videoAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; AVMutableComposition *mutableComposition = [AVMutableComposition composition]; AVMutableCompositionTrack *compatibleCompositionTrack = [mutableComposition mutableTrackCompatibleWithTrack:videoAssetTrack]; if (compatibleCompositionTrack) { // Implementation continues. [compatibleCompositionTrack removeTimeRange: yourTimeRange]; //Export Now your media file using exportSession AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:compatibleCompositionTrack presetName:AVAssetExportPresetHighestQuality]; exportSession.outputFileType = AVFileTypeMPEG4; _assetExport.outputURL = outputFileUrl; [_assetExport exportAsynchronouslyWithCompletionHandler: ^(void ) { switch ([exportSession status]) { case AVAssetExportSessionStatusFailed: NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]); break; case AVAssetExportSessionStatusCancelled: NSLog(@"Export canceled"); break; case AVAssetExportSessionStatusCompleted: [self convertVideoToLowQuailtyWithInputURL:saveURL outputURL:saveURL1]; break; default: break; } } ]; }