12

私の目標は、カメラから記録された一連のクリップを作成し、それらを特定の適切なサイズでエクスポートすることです。もちろん、エクスポートする前にビデオの向きを回転させる必要があります。

これを行うには、以下のavAssetsに保存されているビデオクリップの配列からAVMutableCompositionを作成します。私はそれらをうまく構成し、それをエクスポートすることができます。ただし、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");
    }
}];

}
4

2 に答える 2

13

Okはそれを理解し、他の人が私がした時間を無駄にしないようにここに投稿しました。

問題は、で使用する場合AVAssetExportPresetPassthroughAVExportSessionエクスポーターがビデオ作成の指示を無視することです。フォーマットなどを通過する際に、少なくともビデオ作曲の指示を尊重することを期待していましたが、どうやらそれはそれがどのように機能するかではありません。ドキュメントのバグを埋めた後、テクニカルQ&Aで見つけることができます。

于 2013-03-27T18:33:34.330 に答える
0

使用したい場合の解決策AVAssetExportPresetPassthrough

compositionVideoTrack.preferredTransform = transform

詳細はこちら:https ://developer.apple.com/library/archive/qa/qa1744/_index.html

それ以外の場合、AVAssetExportPresetPassthroughエクスポートオプションを指定してすべてのトラックを通過させても、コンポジションに変換を設定する場合は、上記のようにコンポジショントラックにpreferredTransformプロパティを設定します。

于 2020-08-27T06:11:05.287 に答える