3

私のアプリでは、小さなビデオを録画してNSMutableArrayasに追加し、AVAssetキャプチャした内容を記録しています。ユーザーがボタンを押してそれらをマージすると、最終結果は最初に撮影されたビデオのみになります (たとえば、3 つの短いビデオが撮影された場合、マージ後の最終結果は最初のビデオのみになり、他のビデオは表示されません)。NSMutableArray で繰り返し、ビデオをつなぎ合わせる私のコードは次のとおりです。

if (self.capturedVideos.count != 0) {        
    //Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack.
    AVMutableComposition* mixComposition = [[AVMutableComposition alloc] init];

    for (AVAsset *asset in self.capturedVideos) {
        //check if the video is the first one captures so that it  is placed at time 0.
        if ([self.capturedVideos indexOfObject:asset] == 0) {
            AVMutableCompositionTrack *firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
            [firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];
            previousAsset = asset;
        } else{
            AVMutableCompositionTrack *track = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
            [track insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:previousAsset.duration error:nil];
            previousAsset = asset;
        }
    }

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:
    [NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]];
    NSURL *url = [NSURL fileURLWithPath:myPathDocs];
    // 5 - Create exporter
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
    exporter.outputURL=url;
    exporter.outputFileType = AVFileTypeQuickTimeMovie;
    exporter.shouldOptimizeForNetworkUse = YES;
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self exportDidFinish:exporter];
        });
    }];
}

for ループの後にあるのは、ビデオをエクスポートしてカメラ ロールに保存するためです。私の間違いはどこですか?期間は正しいです(したがって、重複はありません)。しかし、私は何かを疑っています。@implementation の後に追加されたインスタンス変数があります。これは、追加された前のアセットを追跡する previousAsset であり、次のアセットをどこに配置するかを知っています。クラスAVAssetなので、初期化しようとするとエラーが表示されるため、初期化しませんでした。

previousAsset = [[AVAsset alloc] init];

4

4 に答える 4

3

これはうまくいきます

      AVMutableComposition *mainComposition = [[AVMutableComposition alloc] init];
      AVMutableCompositionTrack *compositionVideoTrack = [mainComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];


      AVMutableCompositionTrack *soundtrackTrack = [mainComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
      CMTime insertTime = kCMTimeZero;

      for (AVAsset *videoAsset in assets) {

          [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:insertTime error:nil];

          [soundtrackTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:insertTime error:nil];

          // Updating the insertTime for the next insert
          insertTime = CMTimeAdd(insertTime, videoAsset.duration);
      }

      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      NSString *documentsDirectory = [paths objectAtIndex:0];

      // Creating a full path and URL to the exported video
      NSString *outputVideoPath =  [documentsDirectory stringByAppendingPathComponent:
                              [NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]];

      // NSString *documentsDirectory = [paths objectAtIndex:0];
      NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:
                         current_name];
      NSURL *outptVideoUrl = [NSURL fileURLWithPath:myPathDocs];
      AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mainComposition presetName:AVAssetExportPreset640x480];

      // Setting attributes of the exporter
      exporter.outputURL=outptVideoUrl;
      exporter.outputFileType =AVFileTypeMPEG4;   //AVFileTypeQuickTimeMovie;
      exporter.shouldOptimizeForNetworkUse = YES;
      [exporter exportAsynchronouslyWithCompletionHandler:^{
          dispatch_async(dispatch_get_main_queue(), ^{
              //completion(exporter);
              [self exportDidFinish:exporter];
              // [self exportDidFinish:exporter:assets];
          });
      }];

これはうまくいきます..

于 2014-02-10T10:58:48.553 に答える
1

アプリ内でより再利用可能な方法でこれを行う方法の出発点として、Git Hub に優れたサンプル プロジェクトがあります。

https://github.com/khoavd-dev/MergeVideos/blob/master/MergeVideos/VideoManager/KVVideoManager.swift

于 2020-01-03T16:25:59.567 に答える