将AVAsset视频文件拆分为块

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将AVAsset视频文件拆分为块相关的知识,希望对你有一定的参考价值。

我想将AVAsset拆分成块 - AVAsset是一个视频文件。基本上我想在每个块上应用过滤器,标题和音频并保存最终视频。任何指导都将是一个很大的帮助。

答案

试试这个代码。阅读注释以了解我使用的变量

/**
* Here the object is a NSDictionary which has the asset URL, start time where you need to start the chunk, duration of the chunk and any other related details
* As the return value, you get split video path
*/
- (NSString *)chunkyGrab:(id)object
{
    NSLog(@"%s - %d", __PRETTY_FUNCTION__, __LINE__);

    AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
    AVMutableAudioMix *mutableAudioMix = [AVMutableAudioMix audioMix];
    NSMutableArray *audioParameters = [[NSMutableArray alloc] init];

    NSDictionary *options = nil;

    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[object objectForKey:@"url"] options:options]; // asset URL
    AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

    CMTime chunkStart = CMTimeMakeWithSeconds(CMTimeGetSeconds(kCMTimeZero) + [[object objectForKey:@"tss"] intValue], 1);  // Start time of the chunk
    CMTime chunkDuration = CMTimeMakeWithSeconds([[object objectForKey:@"duration"] intValue], 1);      // Duration of the chunk

    @try
    {
        NSError *errorOne;

        [videoTrack insertTimeRange:CMTimeRangeMake(chunkStart, chunkDuration)
                            ofTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
                             atTime:kCMTimeZero
                              error:&errorOne];

        if (errorOne)
        {
            NSLog(@"%s - %d # errorOne.description = %@", __PRETTY_FUNCTION__, __LINE__, errorOne.description);
        }
    }
    @catch (NSException *exception)
    {
        NSLog(@"%s - %d # exception.description = %@", __PRETTY_FUNCTION__, __LINE__, exception.description);
    }

    @try
    {
        if([[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] != nil)
        {
            [audioTrack insertTimeRange:CMTimeRangeMake(chunkStart, chunkDuration)
                                ofTrack:[[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]
                                 atTime:kCMTimeZero
                                  error:nil];
        }
        else
        {
            NSLog(@"%s - %d # No audio track", __PRETTY_FUNCTION__, __LINE__);
        }
    }
    @catch (NSException *exception)
    {
        NSLog(@"%s - %d # exception.description = %@", __PRETTY_FUNCTION__, __LINE__, exception.description);
    }

    AVMutableVideoComposition *MainCompositionInst = [AVMutableVideoComposition videoComposition];

    CGSize naturalSizeFirst;
    naturalSizeFirst = mixComposition.naturalSize;
    float renderWidth = 1280;
    float renderHeight = 720;

    mutableAudioMix.inputParameters = audioParameters;

    MainCompositionInst.frameDuration = CMTimeMake(1, 30);
    MainCompositionInst.renderSize = CGSizeMake(renderWidth, renderHeight);

    NSString *path = [self exportChunkAsset:MainCompositionInst :mixComposition :mutableAudioMix ];
    return path;
}


- (NSString *)exportChunkAsset:(AVMutableVideoComposition *)MainCompositionInst :(AVMutableComposition *)mixComposition :(AVMutableAudioMix *)mutableAudioMix
{
    NSLog(@"%s - %d", __PRETTY_FUNCTION__, __LINE__);

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    int r = rand() % 74;
    __block NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat:@"overlapVideo-%d.mov",r]];

    if([[NSFileManager defaultManager] fileExistsAtPath:myPathDocs])
    {
        [[NSFileManager defaultManager] removeItemAtPath:myPathDocs error:nil];
    }

    NSURL *url = [NSURL fileURLWithPath:myPathDocs];

// exporter is an instance of AVAssetExportSession
    _exporter = [AVCommon getAssetExportSession: mixComposition];
    _exporter.outputURL = url;
    _exporter.outputFileType = AVFileTypeQuickTimeMovie;
    _exporter.shouldOptimizeForNetworkUse = YES;
    _exporter.audioMix = mutableAudioMix;

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    [_exporter exportAsynchronouslyWithCompletionHandler:^
     {
         if(!_exporter.error)
         {
             exportError = NO;
             if( _exporter.status == AVAssetExportSessionStatusCancelled)
             {
                 if([[NSFileManager defaultManager] fileExistsAtPath:myPathDocs])
                 {
                     [[NSFileManager defaultManager] removeItemAtPath:myPathDocs error:nil];
                 }
             }
             dispatch_semaphore_signal(semaphore);
         }
         else
         {
             NSError *error = _exporter.error;
             NSLog(@"%s - %d # error.description = %@", __PRETTY_FUNCTION__, __LINE__, error.description);

             if([_exporter.error.domain isEqualToString:@"AVFoundationErrorDomain"])
             {
                 if([[NSFileManager defaultManager] fileExistsAtPath:myPathDocs])
                 {
                     [[NSFileManager defaultManager] removeItemAtPath:myPathDocs error:nil];
                 }
             }
             exportError = _exporter.error;

             dispatch_semaphore_signal(semaphore);
         }
     }];

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    if(exportError != nil)
    {
        return @"error";
    }

    [_exportProgressBarTimer invalidate];
    _exportProgressBarTimer = nil;

    return myPathDocs;
}

以上是关于将AVAsset视频文件拆分为块的主要内容,如果未能解决你的问题,请参考以下文章

带有流式 AVAsset -11800 错误的 AVExportSession

使用 AVAsset/AVCaptureSession 裁剪视频

AVAsset 的 NaturalSize 与视频文件不同

AVAsset 在 iOS 中使用图像叠加保存视频会破坏视频

将压缩的csv拆分为块的最有效方法

将数组拆分为块