12

編集: 最も奇妙なこと: 完全なアプリからこのコードを実行するとすべてが機能するように見えますが、私は常に単体テストからムービーの作成を実行していましたが、そこでのみ機能しませんでした。その理由を調べてみると…

AVMutableComposition を使用してビデオ + オーディオ + テキストを結合し、新しいビデオにエクスポートしようとしています。

私のコードは WWDC '10 の AVEditDemo に基づいています

CATextLayer に紫色の背景を追加したので、ムービーにエクスポートされたという事実を知ることができますが、テキストは表示されません... さまざまなフォント、位置、色の定義で遊んでみましたが、何も役に立たなかったので、ここにコードを投稿して、誰かが似たようなものに出くわしたかどうかを確認し、何が欠けているか教えてください.

コードは次のとおりです (self.audio と self.video は AVURLAssets です)。

CMTime exportDuration = self.audio.duration;

AVMutableComposition *composition = [[AVMutableComposition alloc] init];

AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVAssetTrack *videoTrack = [[self.video tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

// add the video in loop until the audio ends
CMTime currStartTime = kCMTimeZero;
while (CMTimeCompare(currStartTime, exportDuration) < 0) {
    CMTime timeRemaining = CMTimeSubtract(exportDuration, currStartTime);
    CMTime currLoopDuration = self.video.duration;

    if (CMTimeCompare(currLoopDuration, timeRemaining) > 0) {
        currLoopDuration = timeRemaining;
    }
    CMTimeRange currLoopTimeRange = CMTimeRangeMake(kCMTimeZero, currLoopDuration);

    [compositionVideoTrack insertTimeRange:currLoopTimeRange ofTrack:videoTrack
                                    atTime:currStartTime error:nil];

    currStartTime = CMTimeAdd(currStartTime, currLoopDuration);
}

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

AVAssetTrack *audioTrack = [self.audio.tracks objectAtIndex:0];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, self.audio.duration) ofTrack:audioTrack atTime:kCMTimeZero error:nil];

AVMutableVideoComposition *videoComposition;

// the text layer part - THIS IS THE PART THAT DOESN'T WORK WELL
CALayer *animatedTitleLayer = [CALayer layer];
CATextLayer *titleLayer = [[CATextLayer alloc] init];
titleLayer.string = @"asdfasdf";
titleLayer.alignmentMode = kCAAlignmentCenter;
titleLayer.bounds = CGRectMake(0, 0, self.video.naturalSize.width / 2, self.video.naturalSize.height / 2);
titleLayer.opacity = 1.0;
titleLayer.backgroundColor = [UIColor purpleColor].CGColor;

[animatedTitleLayer addSublayer:titleLayer];
animatedTitleLayer.position = CGPointMake(self.video.naturalSize.width / 2.0, self.video.naturalSize.height / 2.0);

// build a Core Animation tree that contains both the animated title and the video.
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, self.video.naturalSize.width, self.video.naturalSize.height);
videoLayer.frame = CGRectMake(0, 0, self.video.naturalSize.width, self.video.naturalSize.height);
[parentLayer addSublayer:videoLayer];
[parentLayer addSublayer:animatedTitleLayer];

videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
passThroughInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, exportDuration);
AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];

passThroughInstruction.layerInstructions = [NSArray arrayWithObject:passThroughLayer];
videoComposition.instructions = [NSArray arrayWithObject:passThroughInstruction];

videoComposition.frameDuration = CMTimeMake(1, 30);
videoComposition.renderSize = self.video.naturalSize;

AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];

exportSession.videoComposition = videoComposition;
exportSession.outputURL = [NSURL fileURLWithPath:self.outputFilePath];
exportSession.outputFileType = AVFileTypeQuickTimeMovie;

[exportSession exportAsynchronouslyWithCompletionHandler:^() {
    // save the video ...
}];
4

4 に答える 4

2

別のコンテキストで同じ問題に遭遇しました。私の場合、AVMutableComposition の準備をバックグラウンド スレッドに移動しました。準備のその部分をメイン キュー/スレッドに戻すと、CATextLayer オーバーレイが再び適切に機能するようになりました。

これは単体テストのコンテキストに正確には当てはまらない可能性がありますが、私の推測では、CATextLayer/AVFoundation は、そのスレッド コンテキストで実行中/利用可能な UIKit/AppKit の一部 (描画コンテキスト? 現在の画面?) に依存している可能性があります。私たち二人が見ている失敗を説明してください。

于 2016-01-11T23:26:11.870 に答える
1

ほとんどすべてがうまくレンダリングされ、CALayer を使用した画像と CGImage に設定されたコンテンツが表示されるという問題がありました。CGTextLayer テキストを除いて、背景色を CGTextLayer に設定した場合、beginTime と期間も完全にレンダリングされました。実際のテキストは表示されませんでした。それはすべてシミュレーターで行い、それを電話で実行しました。完璧でした。

結論: シミュレーターは素晴らしいビデオをレンダリングします... CATextLayer を使用するまでは。

于 2016-11-15T19:18:48.597 に答える
0

さらなる調査が必要ですが、AFAICT の現在、AVMutableVideoComposition 内の CATextLayer は、ロジック ユニット テスト ターゲット内からは機能せず、この機能は通常のターゲットからテストする必要があります。

于 2012-05-01T21:13:26.977 に答える