【问题标题】:Mute Video + Transform Video Using single export operation of AVAssetExportSession使用 AVAssetExportSession 的单一导出操作静音视频 + 转换视频
【发布时间】:2018-04-11 07:25:09
【问题描述】:

我有以下代码来修复视频转换

    - (AVVideoComposition *)squareVideoCompositionFor:(AVAsset *)asset {

    AVAssetTrack *track = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;

    CGFloat length = MAX(track.naturalSize.width, track.naturalSize.height);

    CGSize size = track.naturalSize;

    CGFloat scale = 0;

    CGAffineTransform transform = track.preferredTransform;

    if (transform.a == 0 && transform.b == 1 && transform.c == -1 && transform.d == 0) {
        scale = -1;
    }
    else if (transform.a == 0 && transform.b == -1 && transform.c == 1 && transform.d == 0) {
        scale = -1;
    }
    else if (transform.a == 1 && transform.b == 0 && transform.c == 0 && transform.d == 1) {
        scale = 1;
    }
    else if (transform.a == -1 && transform.b == 0 && transform.c == 0 && transform.d == -1) {
        scale = -1;
    }

    transform = CGAffineTransformTranslate(transform, scale * -(size.width - length) / 2, scale * -(size.height - length) / 2);




    AVMutableVideoCompositionLayerInstruction *transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:track];
    [transformer setTransform:transform atTime:kCMTimeZero];

//    CGAffineTransform finalTransform = t2;
//    [transformer setTransform:finalTransform atTime:kCMTimeZero];

    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, kCMTimePositiveInfinity);
    instruction.layerInstructions = @[transformer];


    AVMutableVideoComposition *composition = [AVMutableVideoComposition videoComposition];
    composition.frameDuration = CMTimeMake(1, 30);
    composition.renderSize =  CGSizeMake(length, length);
    composition.instructions = @[instruction];
    composition.renderScale = 1.0;


    return composition;
    }

以及静音音频的以下代码

- (AVMutableComposition *) removeAudioFromVideoFileFor:(AVAsset *)asset  {
    AVMutableComposition *composition_Mix = [AVMutableComposition composition];
    AVMutableCompositionTrack *compositionVideoTrack = [composition_Mix addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

    BOOL ok = NO;

    AVAssetTrack * sourceVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

    CMTimeRange x = CMTimeRangeMake(kCMTimeZero, [asset duration]);
    NSError *error;
    ok = [compositionVideoTrack insertTimeRange:x ofTrack:sourceVideoTrack atTime:kCMTimeZero error:&error];

    return composition_Mix;
}

这里我如何调用函数

    AVAsset *asset = [AVAsset assetWithURL:inputURL];

    AVMutableComposition *composition = [self  removeAudioFromVideoFileFor:asset];

    AVAssetExportSession *session = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
    session.videoComposition = [self squareVideoCompositionFor:asset];
    session.outputURL = outputURL;
    session.outputFileType = AVFileTypeMPEG4;
    session.shouldOptimizeForNetworkUse = true;
    session.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);

但如果我同时使用composition 和[self squareVideoCompositionFor:asset] 则会显示错误

Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo={NSLocalizedDescription=Operation Stopped, NSLocalizedFailureReason=无法合成视频。}

如果我省略了一个,那么它工作正常意味着一个 AVAssetExportSession 可以将视频或 squareVideo 中的音频静音

有没有一种方法可以同时使用 AVAssetExportSession 的单个导出进度来实现?

【问题讨论】:

    标签: ios objective-c avfoundation avcomposition


    【解决方案1】:

    您的代码看起来不错,但我已对您的代码进行了更改以使其正常工作。

    inputURL 和 outputURL 应该以 file:// 或 https:// 为前缀(因为它是 url,在你的情况下它应该以 file:// 开头)

    如果您的无效,那么您将无法获得所需的输出。

    //FOR OUTPUT URL
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    path = [path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    
    //the output video will be written to file final.mp4
    NSURL *outputURL = [NSURL fileURLWithPath:path];
    outputURL = [outputURL URLByAppendingPathComponent:@"final.mp4"];
    NSLog(@"outputURL = %@", outputURL);
    
    
    //FOR INPUT URL
    //This is the path of the bundle resource that is going to be used
    NSURL *inputURL = [[NSBundle mainBundle] URLForResource:@"video" withExtension:@"mp4"];
    NSLog(@"inputURL = %@", inputURL);
    

    导出作文

    //this will export the composition with the specified configuration
    [session exportAsynchronouslyWithCompletionHandler:^{
        NSLog(@"Success");
    }];
    

    当您在控制台中看到“成功”日志时,请检查您的应用程序的文档目录。视频将写在outptURL。

    注意:使用 CMD + SHIFT + G 并粘贴 outputURL。您将被重定向到应用程序的文档文件夹(仅适用于模拟器)。对于设备,您需要下载应用容器并查看包内容。

    完整代码

    removeAudioFromVideoFileFor: 和 squareVideoCompositionFor: 方法看起来不错。只需要更改以下内容。

    这里的“video”是app bundle中资源文件的名称。

    - (void)viewDidLoad {
    [super viewDidLoad];
    
    
       NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
       path = [path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
      NSURL *outputURL = [NSURL fileURLWithPath:path];
    outputURL = [outputURL URLByAppendingPathComponent:@"final.mp4"];
      NSLog(@"outputURL = %@", outputURL);
    
    
      NSURL *inputURL = [[NSBundle mainBundle] URLForResource:@"video" withExtension:@"mp4"];
      NSLog(@"inputURL = %@", inputURL);
    
      AVAsset *asset = [AVAsset assetWithURL:inputURL];
    
      AVMutableComposition *composition = [self removeAudioFromVideoFileFor: asset];
    
      AVAssetExportSession *session = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
      session.videoComposition = [self squareVideoCompositionFor:asset];
      session.outputURL = outputURL;
      session.outputFileType = AVFileTypeMPEG4;
      session.shouldOptimizeForNetworkUse = true;
      session.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
    
      [session exportAsynchronouslyWithCompletionHandler:^{
         NSLog(@"Success:");
      }];
    }
    

    希望对你有帮助

    【讨论】:

    • 感谢您的回答,我会看看这个,如果有任何疑问,请告诉您。
    猜你喜欢
    • 1970-01-01
    • 2012-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 2016-06-13
    相关资源
    最近更新 更多