2016-06-30 3 views
0

Я использую библиотеку «OWVideoProcessor» для резки фрагментов видеозаписи в реальном времени. Видео отлично работает на любых устройствах Apple, но когда я играю в браузере (Dropbox), у него есть несколько секунд, добавленных спереди, и звук также отсутствует в секундах, добавленных спереди. Здесь вы можете увидеть примеры этого видео: https://www.dropbox.com/s/2vyhqlfgfh6gzlk/file32167%281%29.mp4?dl=0 Если вы загружаете видео на устройство Apple, видеоролик имеет 20 секунд. если вы играете в браузере, у него есть 29 секунд.Создание видеофайла AVFileTypeMPEG4 с AVAssetExportSession и AVMutableComposition

Это код для сшивания видео:

- (void)stitchVideoWithDestinationPath:(NSString *)destinationPath completion:(void(^)(NSError *error))completion { 
    [self.exportSession cancelExport]; 

    NSLog(@"export started to path: %@", destinationPath); 

    AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init]; 
    AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
    AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 

    CMTime startTime = kCMTimeZero; 

    int lastIndex = self.segmentStart + self.segmentCount - 1; 
    NSLog(@"Stitching segments in interval: [%d - %d]", self.segmentStart, lastIndex); 

    for (int i = self.segmentCount - 5; i < lastIndex; i++) { 
     CMTimeShow(startTime); 
     NSURL *url = [OWUtilities urlForRecordingSegmentCount:i basePath:self.basePath]; 
     AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:@{AVURLAssetPreferPreciseDurationAndTimingKey: @(YES)}]; 
     NSAssert(asset, @"Invalid asset at: %@", url); 

     BOOL hasAllTracks = [[asset tracks] count] >= 2; 
     if (hasAllTracks) { 
      CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration); 

      AVAssetTrack *track = nil; 
      track = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
      [videoTrack insertTimeRange:timeRange ofTrack:track atTime:startTime error:nil]; 

      track = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 
      [audioTrack insertTimeRange:timeRange ofTrack:track atTime:startTime error:nil]; 

      startTime = CMTimeAdd(startTime, asset.duration); 
     } 
    } 
    NSTimeInterval segmentsDuration = CMTimeGetSeconds(startTime); 
    NSLog(@"Total segments duration: %.2f", segmentsDuration); 

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetPassthrough]; 

    if (![[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) { 
     NSArray *filePathsArray = [NSArray new]; 
     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
     NSString *documentsDirectory = [paths objectAtIndex:0]; 
     filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory error:nil]; 
     documentsDirectory = [documentsDirectory stringByAppendingString:@"/uploads/"]; 
     documentsDirectory = [documentsDirectory stringByAppendingString:[destinationPath lastPathComponent]]; 

     if([[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory]) { 
      destinationPath = documentsDirectory; 
     } 
    } 
    exporter.outputURL = [NSURL fileURLWithPath:destinationPath]; 
    exporter.outputFileType = AVFileTypeMPEG4; 
    BOOL trimRange = (segmentsDuration > self.outputSegmentDuration); 
    if (trimRange) { 
     CMTime duration = CMTimeMakeWithSeconds(self.outputSegmentDuration, startTime.timescale); 
     NSTimeInterval startInterval = segmentsDuration - self.outputSegmentDuration; 
     CMTime start = CMTimeMakeWithSeconds(startInterval, startTime.timescale); 
     exporter.timeRange = CMTimeRangeMake(start, duration); 

     NSLog(@"Exporting segment:"); 
     CMTimeRangeShow(exporter.timeRange); 
     NSTimeInterval segmentsDuration2 = CMTimeGetSeconds(duration); 
     NSLog(@"Total segments duration: %.2f", segmentsDuration2); 
    } 


    @weakify(self, exporter); 
    [exporter exportAsynchronouslyWithCompletionHandler:^{ 
     @strongify(self, exporter); 
     NSLog(@"error: %@", exporter.error); 
     if (completion && (exporter.status != AVAssetExportSessionStatusCancelled)) { 
      completion(exporter.error); 
     } else { 
      completion(nil); 
     } 


     if (self.exportSession == exporter) { 
      self.exportSession = nil; 
     } 
    }]; 

    self.exportSession = exporter; 
} 

ответ

1

Проблема была не в коде выше. Проблема была здесь:

NSDictionary *videoCompressionSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
               AVVideoCodecH264, AVVideoCodecKey, 
               [NSNumber numberWithInteger:width], AVVideoWidthKey, 
               [NSNumber numberWithInteger:height], AVVideoHeightKey, 
               [NSDictionary dictionaryWithObjectsAndKeys: 
               [NSNumber numberWithInteger: bps ], AVVideoAverageBitRateKey, 
               [NSNumber numberWithInteger:300], AVVideoMaxKeyFrameIntervalKey, 
               nil], AVVideoCompressionPropertiesKey, 
               nil]; 

Этот код используется для настройки параметров сжатия видео. AVVideoAverageBitRateKey установлен на низкий (например, 600 кбит/с), и AVVideoMaxKeyFrameIntervalKey был слишком большим. Таким образом, я изменил AVVideoMaxKeyFrameIntervalKey на 1, и я увеличил AVVideoAverageBitRateKey до 5000 кбит/с. Это решило мою проблему.

Этот код был написан для уменьшения размера видео. Вы можете изменить его в библиотеке OWVideoProcessor.