xcode 将带有 AVMutableVideoComposition 的文本叠加添加到特定时间范围

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21684549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 04:38:49  来源:igfitidea点击:

Add a text overlay with AVMutableVideoComposition to a specific timerange

iosxcodeavfoundationavmutablecomposition

提问by ScottF

I have found a few examples that show how to add a text overlay on a video.

我找到了一些示例,展示了如何在视频上添加文本叠加层。

Ray's Tutorial - http://www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos

Ray 的教程 - http://www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos

This SO answer - How can I add a watermark in a captured video on iOS

这个 SO 答案 -如何在 iOS 上捕获的视频中添加水印

There were a few others that I referenced as well. My code looks almost identical to that answer and I've been trying to tweak it to get the text overlay to only show up for a second or two at the beginning of the video. Any help on how I could accomplish that?

还有其他一些我也参考了。我的代码看起来与那个答案几乎相同,我一直在尝试调整它以使文本覆盖仅在视频开头显示一两秒钟。关于我如何做到这一点的任何帮助?

Here is my code. This works as is to export the video with the overlay being shown for the entire duration.

这是我的代码。这可以导出视频,并在整个持续时间内显示覆盖。

if(vA) {
    videoCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    [videoCompositionTrack insertTimeRange:videoTimerange ofTrack:[[vA tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:&error];
    [videoCompositionTrack setPreferredTransform:[[[vA tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] preferredTransform]];
    if(error)
        NSLog(@"%@", error);
}

if(aA) {
    audioCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [audioCompositionTrack insertTimeRange:audioTimerange ofTrack:[[aA tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:&error];
    if(error)
        NSLog(@"%@", error);
}

CGSize videoSize = [videoCompositionTrack naturalSize];

UIImage *myImage = [UIImage imageNamed:@"cover.png"];
CALayer *aLayer = [CALayer layer];
aLayer.contents = (id)myImage.CGImage;
aLayer.frame = CGRectMake(5, 25, 100, 56);
aLayer.opacity = 0.7;

CATextLayer *titleLayer = [CATextLayer layer];
titleLayer.string = titleText;
titleLayer.fontSize = 18;
titleLayer.foregroundColor = titleColor.CGColor;
titleLayer.alignmentMode = kCAAlignmentCenter;
titleLayer.frame = CGRectMake(20, 10, videoSize.width - 40, 20);
[titleLayer displayIfNeeded];

CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
[parentLayer addSublayer:videoLayer];
[parentLayer addSublayer:aLayer];
if(titleText && [titleText length] > 0) {
    [parentLayer addSublayer:titleLayer];
}

AVMutableVideoComposition *videoComp = [AVMutableVideoComposition videoComposition];
videoComp.renderSize = videoSize;
videoComp.frameDuration = CMTimeMake(1, 30);
videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

AVAssetTrack *videoTrack = [[mixComposition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
[instruction setTimeRange:CMTimeRangeMake(kCMTimeZero, [mixComposition duration])];
instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
videoComp.instructions = [NSArray arrayWithObject:instruction];

AVAssetExportSession *_assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];
_assetExport.videoComposition = videoComp;
_assetExport.outputFileType = AVFileTypeMPEG4;
_assetExport.outputURL = outputFileUrl;

[_assetExport exportAsynchronouslyWithCompletionHandler:^{
    AVAssetExportSessionStatus status = [_assetExport status];
    switch (status) {
        case AVAssetExportSessionStatusFailed:
            NSLog(@"Export Failed");
            NSLog(@"Export Error: %@", [_assetExport.error localizedDescription]);
            NSLog(@"Export Error Reason: %@", [_assetExport.error localizedFailureReason]);
            break;
        case AVAssetExportSessionStatusCompleted:
            NSLog(@"Export Completed");
            [self performSelectorOnMainThread:@selector(updateProgressIndicator:) withObject:[NSNumber numberWithFloat:2] waitUntilDone:YES];
            break;
        case AVAssetExportSessionStatusUnknown:
            NSLog(@"Export Unknown");
            break;
        case AVAssetExportSessionStatusExporting:
            NSLog(@"Export Exporting");
            break;
        case AVAssetExportSessionStatusWaiting:
            NSLog(@"Export Waiting");
            break;
    }
}];

回答by ScottF

I figured out what I needed to do. It wasn't anything special really. It just required a better understanding of what was all possible.

我想出了我需要做什么。真的没什么特别的。它只需要更好地理解一切皆有可能。

Basically all I had to do was add a basic opacity animation to the layer with text in it.

基本上我所要做的就是向带有文本的图层添加一个基本的不透明动画。

// My original code for creating the text layer
CATextLayer *titleLayer = [CATextLayer layer];
.
.
.
[titleLayer displayIfNeeded];

// the code for the opacity animation which then removes the text
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
[animation setDuration:0];
[animation setFromValue:[NSNumber numberWithFloat:1.0]];
[animation setToValue:[NSNumber numberWithFloat:0.0]];
[animation setBeginTime:1];
[animation setRemovedOnCompletion:NO];
[animation setFillMode:kCAFillModeForwards];
[titleLayer addAnimation:animation forKey:@"animateOpacity"];

回答by Jatin Kathrotiya

We should add two opacity animations for Video overlay at particular time rang. First animation for show overlay at start duration and second animation for hide overlay at end duration. We should take care to set fill mode of animation.

Sample code of Video overlay for particular time Rang.

我们应该在特定时间范围内为视频叠加添加两个不透明动画。第一个动画用于在开始持续时间显示覆盖,第二个动画用于在结束持续时间隐藏覆盖。我们应该注意设置动画的填充模式。

特定时间范围的视频叠加示例代码。

            let textLayer = CATextLayer()
            textLayer.opacity = 0.0
            .
            .
            textLayer.frame = CGRect(x: 0.0, y: 0.0, width: 150.0, height:100.0)
            textLayer.string = "Overlay Text"

            let startVisible = CABasicAnimation.init(keyPath:"opacity")
            startVisible.duration = 0.1    // for fade in duration
            startVisible.repeatCount = 1
            startVisible.fromValue = 0.0  
            startVisible.toValue = 1.0
            startVisible.beginTime = overlay.startTime.seconds // overlay time range start duration
            startVisible.isRemovedOnCompletion = false 
            startVisible.fillMode = kCAFillModeForwards 
            textLayer.add(startVisible, forKey: "startAnimation")

            let endVisible = CABasicAnimation.init(keyPath:"opacity")
            endVisible.duration = 0.1
            endVisible.repeatCount = 1
            endVisible.fromValue = 1.0
            endVisible.toValue = 0.0
            endVisible.beginTime = overlay.endTime.seconds
            endVisible.fillMode = kCAFillModeForwards
            endVisible.isRemovedOnCompletion = false
            textLayer.add(endVisible, forKey: "endAnimation")