【问题标题】:Transform not working in AVMutableVideoComposition while exporting导出时转换在 AVMutableVideoComposition 中不起作用
【发布时间】:2013-03-26 23:13:00
【问题描述】:

我的目标是组合一组从相机录制的剪辑,并以特定的首选尺寸导出它们。当然,导出前需要旋转视频方向。

我通过从一组视频剪辑中组合一个 AVMutableComposition 来做到这一点,这些视频剪辑存储在下面的 avAssets 中。我能够很好地组合它们,并将其导出。但是,我在 AVMutableVideoComposition 上设置的旋转变换没有得到遵守。如果我使用相同的变换并将其设置在视频轨道的 preferredTransform 属性上,那么它就可以工作。在这两种情况下,视频 renderSize 都没有得到尊重。就好像导出器完全忽略了 videoComposition 一样。有什么想法会发生什么吗?

我确实有一个 AVCaptureSession 正在运行,但我在导出之前将其关闭,这并没有任何区别。我对 iOS 编程相当陌生,所以我可能缺少一些基本的东西。 :)

我的代码:

-(void) finalRecord{
NSError *error = nil;

AVMutableComposition *composition = [AVMutableComposition composition];

AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
NSLog(@"Video track id is %d", [compositionVideoTrack trackID]);

AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

// avAssets hold the video clips to be composited
int pieces = [avAssets count];

CGAffineTransform transform = CGAffineTransformMakeRotation( M_PI_2);
//  [compositionVideoTrack setPreferredTransform:transform];

for (int i = 0; i<pieces; i++) {

    AVURLAsset *sourceAsset = [avAssets objectAtIndex:i];

    AVAssetTrack *sourceVideoTrack = [[sourceAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    AVAssetTrack *sourceAudioTrack = [[sourceAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

    [timeRanges addObject:[NSValue valueWithCMTimeRange:CMTimeRangeMake(kCMTimeZero, sourceAsset.duration)]];
    [videoTracks addObject:sourceVideoTrack];
    [audioTracks addObject:sourceAudioTrack];
}

[compositionVideoTrack insertTimeRanges:timeRanges ofTracks:videoTracks atTime:kCMTimeZero error:&error];
[compositionAudioTrack insertTimeRanges:timeRanges ofTracks:audioTracks atTime:kCMTimeZero error:&error];

AVMutableVideoCompositionInstruction *vtemp = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
vtemp.timeRange = CMTimeRangeMake(kCMTimeZero, [composition duration]);
NSLog(@"\nInstruction vtemp's time range is %f %f", CMTimeGetSeconds( vtemp.timeRange.start),
      CMTimeGetSeconds(vtemp.timeRange.duration));

// Also tried videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack    
AVMutableVideoCompositionLayerInstruction *vLayerInstruction = [AVMutableVideoCompositionLayerInstruction
                                                               videoCompositionLayerInstructionWithAssetTrack:composition.tracks[0]];
[vLayerInstruction setTransform:transform atTime:kCMTimeZero];
vtemp.layerInstructions = @[vLayerInstruction];

AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.renderSize = CGSizeMake(320.0, 240.0);
videoComposition.frameDuration = CMTimeMake(1,30);

videoComposition.instructions = @[vtemp];

AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:composition presetName:gVideoExportQuality];

NSParameterAssert(exporter != nil);
exporter.videoComposition = videoComposition;
exporter.outputFileType = AVFileTypeQuickTimeMovie;

NSString *rootName = [[self captureManager] tempFileRoot];

NSString *temp = [NSString stringWithFormat:@"%@%@.mov", NSTemporaryDirectory(), rootName];
exporter.outputURL = [NSURL fileURLWithPath:temp ];

[exporter exportAsynchronouslyWithCompletionHandler:^{
    switch ([exporter status]) {
        case AVAssetExportSessionStatusFailed:
            NSLog(@"Export failed: %@", [exporter error]);
            break;
        case AVAssetExportSessionStatusCancelled:
            NSLog(@"Export canceled");
            break;
        case AVAssetExportSessionStatusCompleted:
            NSLog(@"Export successfully");
            [self exportFile:exporter.outputURL];
            [self.delegate recordingEndedWithFile:exporter.outputURL];
            isExporting = FALSE;
            [[[self captureManager] session] startRunning];
            break;
        default:
            break;
    }
    if (exporter.status != AVAssetExportSessionStatusCompleted){
        NSLog(@"Retry export");
    }
}];

}

【问题讨论】:

    标签: iphone ios video avfoundation avmutablecomposition


    【解决方案1】:

    好吧,想通了,在这里发帖是为了帮助其他人不要浪费我所做的时间。

    问题在于,如果您在AVExportSession 上使用AVAssetExportPresetPassthrough,则导出器将忽略视频合成说明。我希望它在通过格式等时至少遵守视频合成说明,但显然这不是它的工作原理。在我填写完文档错误后,您可以在Technical Q&A 中找到它。

    【讨论】:

    • 那么解决方案是什么?
    • 要解决这个问题,只需使用对您的应用有意义的 AVAssetExportPresetPassthrough 以外的其他设置。
    • 我第一次在这里发帖时向 Apple 提交了一个错误 - 很高兴看到他们修改了他们的文档。
    • 此外,他们向控制台添加了消息:警告:使用 AVAssetExportPresetPassthrough 预设时,AVAssetExportSession 将忽略 videoComposition。
    【解决方案2】:

    如果你想使用AVAssetExportPresetPassthrough的解决方案:

    compositionVideoTrack.preferredTransform = transform
    

    更多信息在这里:https://developer.apple.com/library/archive/qa/qa1744/_index.html

    否则,如果您指定 AVAssetExportPresetPassthrough 导出选项以让所有轨道通过,但您仍想在合成上设置变换,请如上所述在合成轨道上设置 preferredTransform 属性。

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      相关资源
      最近更新 更多