从单元测试运行时,CATextLayer没有出现在AVMutableComposition(CATe

2019-09-16 16:52发布

编辑:奇怪的事情:看来,从运行一个完整的应用程序一切正常,这个代码的时候,但我总是从我的单元测试运行电影的创作,只有那里没有工作。 想弄清楚这是为什么?

我试图用AVMutableComposition视频+音频+文本结合并将其导出到一个新的视频。

我的代码是基于AVEditDemo从WWDC '10

我添加了一个紫色的背景,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 ...
}];

Answer 1:

我遇到同样的问题在不同的上下文。 就我而言,我搬到准备AVMutableComposition到一个后台线程。 移动准备的一部分返回到主队列/线程做CATextLayer叠加再次正常工作。

这可能并不完全适用于您的单元测试的情况下,但我的猜测是,CATextLayer / AVFoundation取决于UIKit的/ AppKit的是运行/可用的某些部分(绘制上下文?当前屏幕?),因为线程上下文,这可能解释故障,我们都看到的。



Answer 2:

我有几乎一切与CALayer的和内容设置为CGImage有功,还包括图像的问题。 除CGTextLayer文字,如果我设置背景颜色CGTextLayer,一个BEGINTIME和持续时间是完美呈现过 - 只是实际的文本不希望出现。 这一切都在模拟器上,然后我在手机上运行它:它是完美的。

结论:该模拟器呈现漂亮的视频......直到你使用CATextLayer。



Answer 3:

进一步的调查是必要的,但AFAICT现在CATextLayer内的AVMutableVideoComposition根本不从逻辑单元测试目标内工作,而这个功能必须从一个普通目标进行测试。



Answer 4:

我的问题是,我需要设置contentsGravity = kCAGravityBottomLeft - 否则我的文字是关闭屏幕。



文章来源: CATextLayer doesn't appear in an AVMutableComposition when running from a unit test