2014-10-17 117 views
0

我想修剪,然後壓縮視頻文件。AVAssetWriter破壞由AVAssetExportSession修剪的視頻

  1. 修剪我使用AVAssetExportSession
  2. 對於壓縮我使用AVAssetWriter

如果我單獨使用兩個代碼,每件事情都可以正常工作,但如果我修剪然後輸入壓縮輸出以進行壓縮,我得到了壓縮但損壞的視頻。

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

           } 
          } 
         } 

        } 
         ]; 
       } 
      } 
     } 
    } 
    ]; 
} 
+0

如果您的AVAssetWriter損壞,那麼它確定它給了你一些錯誤代碼是錯誤描述。我的問題是什麼是代碼或錯誤?由於您嘗試導出的文件格式不受支持,或者您的幀和聲音時間不同步,因此導出會話通常會損壞。 – Tirth 2014-10-17 10:52:07

+0

@Tirth沒有錯誤沒有崩潰,只是損壞的視頻文件。 – 2014-10-17 10:53:35

+0

你確定你經歷了AVMutableCompositionTrack類? – Tirth 2014-10-17 10:58:36

回答

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; 
     } 
    } 
    ]; 
} 
+0

這行有一些問題AVMutableCompositionTrack * compatibleCompositionTrack = [mutableComposition mutableTrackCompatibleWithTrack:videoAssetTrack]; – 2014-10-17 11:45:57

+0

哪個問題,請描述並提及您面臨的更好的錯誤。 – Tirth 2014-10-17 11:57:31

+0

xcode突出顯示mutableComposition並建議使用AVMutableComposition,但AVMutableComposition沒有mutableTrackCompatibleWithTrack。 – 2014-10-17 12:04:44