AVAssetWriter破坏AVAssetExportSession修剪的视频

时间:2014-10-17 10:43:11

标签: ios objective-c avassetwriter avassetexportsession

我正在尝试修剪然后压缩视频文件。

  1. 我正在使用AVAssetExportSession
  2. 进行修剪
  3. 对于压缩,我使用的是AVAssetWriter
  4. 如果我单独使用两个代码,那么每件事情都可以正常工作但是如果我修剪然后输入修剪输出以进行压缩,那么我会得到压缩但损坏的视频。

    - (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");
                                         }];
    
                                     }
                                 }
                             }
    
                         }
                          ];
                     }
                 }
             }
         }
         ];
    }
    

1 个答案:

答案 0 :(得分:1)

您必须使用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;
       }
     }
     ];
}