IOS在视频上添加字幕效果的基本思路是:

  1. 使用自定义的CATextLayer文字图层或者CAShapeLayer文字图层,添加到视频的Layer上创建用户自定义的字幕效果。这两者的区别是:CATextLayer支持设置简单的文字效果,包括文字的内容、字体、字号大小、对其方式、文字颜色、背景颜色等基本的属性;CAShapeLayer功能更强大,提供了CATextLayer没有的边框大小、边框颜色等设置,如果需要更高级的文字内容展示,需要使用CATextLayer配合UIBezierPath来定制自定义的文字内容。

  2. 通过设置Layer图层的动画来控制字幕的时间点和时间长度,这里有一个坑如果单独设置CATextLayer或者CAShapeLayer的动画不能控制开始的时间,需要额外添加一个CALayer图层,把文字图层CATextLayer或者CAShapeLayer添加到父CALayer图层中,在文字图层CATextLayer或者CAShapeLayer上设置开始的动画

    NSTimeInterval animatedInStartTime = startTime + initAnimationDuration;CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];fadeInAnimation.fromValue = @0.0f;fadeInAnimation.toValue = @1.0f;fadeInAnimation.additive = NO;fadeInAnimation.removedOnCompletion = NO;fadeInAnimation.beginTime = animatedInStartTime;fadeInAnimation.duration = animationDuration;fadeInAnimation.autoreverses = NO;fadeInAnimation.fillMode = kCAFillModeBoth;[textLayer addAnimation:fadeInAnimation forKey:@"opacity"];
复制代码

在父CALayer图层上设置结束的动画,这样设置才能实现用户自定义的时间点和时间长度

NSTimeInterval animatedOutStartTime = startTime + duration - animationDuration;CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];fadeOutAnimation.fromValue = @1.0f;fadeOutAnimation.toValue = @0.0f;fadeOutAnimation.additive = NO;fadeOutAnimation.removedOnCompletion = NO;fadeOutAnimation.beginTime = animatedOutStartTime;fadeOutAnimation.duration = animationDuration;fadeOutAnimation.autoreverses = NO;fadeOutAnimation.fillMode = kCAFillModeBoth;[animatedTitleLayer addAnimation:fadeOutAnimation forKey:@"opacity"];
复制代码

完整的代码

- (CALayer *)buildLayerbuildTxt:(NSString*)texttextSize:(CGFloat)textSizetextColor:(UIColor*)textColorstrokeColor:(UIColor*)strokeColoropacity:(CGFloat)opacitytextRect:(CGRect)textRectfontPath:(NSString*)fontPathviewBounds:(CGSize)viewBoundsstartTime:(NSTimeInterval)startTimeduration:(NSTimeInterval)duration
{if (!text || [text isEqualToString:@""]){return nil;}// Create a layer for the overall title animation.CALayer *animatedTitleLayer = [CALayer layer];// 1. Create a layer for the text of the title.CATextLayer *titleLayer = [CATextLayer layer];titleLayer.string = text;titleLayer.font = (__bridge CFTypeRef)(@"Helvetica");titleLayer.fontSize = textSize;titleLayer.alignmentMode = kCAAlignmentCenter;titleLayer.bounds = CGRectMake(0, 0, textRect.size.width, textRect.size.height);titleLayer.foregroundColor = textColor.CGColor;titleLayer.backgroundColor = [UIColor clearColor].CGColor;// [animatedTitleLayer addSublayer:titleLayer];// 添加文字以及边框效果UIFont *font = nil;if ((fontPath != nil) && (fontPath.length > 0)) {font = [[FLVideoEditFontManager sharedFLVideoEditFontManager] fontWithPath:fontPath size:textSize];titleLayer.font = CGFontCreateWithFontName((__bridge CFStringRef)font.fontName);}if (font == nil) {titleLayer.font = (__bridge CFTypeRef)(@"Helvetica");}UIBezierPath *path = nil;if (font) {path = [FLLayerBuilderTool createPathForText:text fontHeight:textSize fontName:(__bridge CFStringRef)(font.fontName)];}else{path = [FLLayerBuilderTool createPathForText:text fontHeight:textSize fontName:CFSTR("Helvetica")];}CGRect rectPath = CGPathGetBoundingBox(path.CGPath);CAShapeLayer *textLayer = [CAShapeLayer layer];textLayer.path = path.CGPath;textLayer.lineWidth = 1;if (strokeColor != nil) {textLayer.strokeColor = strokeColor.CGColor;}if (textColor != nil) {textLayer.fillColor = textColor.CGColor;}textLayer.lineJoin = kCALineJoinRound;textLayer.lineCap = kCALineCapRound;textLayer.geometryFlipped = NO;textLayer.opacity = opacity;textLayer.bounds = CGRectMake(0, 0, rectPath.size.width, textSize+10);[animatedTitleLayer addSublayer:textLayer];// 动画图层位置animatedTitleLayer.position = CGPointMake(textRect.origin.x+textRect.size.width/2, viewBounds.height - textRect.size.height/2 - textRect.origin.y);NSTimeInterval initAnimationDuration = 0.1f;NSTimeInterval animationDuration = 0.1f;// 3.显示动画NSTimeInterval animatedInStartTime = startTime + initAnimationDuration;CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];fadeInAnimation.fromValue = @0.0f;fadeInAnimation.toValue = @1.0f;fadeInAnimation.additive = NO;fadeInAnimation.removedOnCompletion = NO;fadeInAnimation.beginTime = animatedInStartTime;fadeInAnimation.duration = animationDuration;fadeInAnimation.autoreverses = NO;fadeInAnimation.fillMode = kCAFillModeBoth;[textLayer addAnimation:fadeInAnimation forKey:@"opacity"];NSTimeInterval animatedOutStartTime = startTime + duration - animationDuration;CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];fadeOutAnimation.fromValue = @1.0f;fadeOutAnimation.toValue = @0.0f;fadeOutAnimation.additive = NO;fadeOutAnimation.removedOnCompletion = NO;fadeOutAnimation.beginTime = animatedOutStartTime;fadeOutAnimation.duration = animationDuration;fadeOutAnimation.autoreverses = NO;fadeOutAnimation.fillMode = kCAFillModeBoth;[animatedTitleLayer addAnimation:fadeOutAnimation forKey:@"opacity"];return animatedTitleLayer;
}
复制代码

依赖的工具类FLLayerBuilderTool.m文件:

#import "FLLayerBuilderTool.h"
#import <CoreText/CoreText.h>@implementation FLLayerBuilderTool+ (UIBezierPath*) createPathForText:(NSString*)string fontHeight:(CGFloat)height fontName:(CFStringRef)fontName
{if ([string length] < 1)return nil;UIBezierPath *combinedGlyphsPath = nil;CGMutablePathRef letters = CGPathCreateMutable();CTFontRef font = CTFontCreateWithName(fontName, height, NULL);if (font == nil) {font = (__bridge CFTypeRef)(@"Helvetica");}NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)font, kCTFontAttributeName,nil];NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:stringattributes:attrs];CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attrString);CFArrayRef runArray = CTLineGetGlyphRuns(line);// for each RUNfor (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runArray); runIndex++){// Get FONT for this runCTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex);CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);// for each GLYPH in runfor (CFIndex runGlyphIndex = 0; runGlyphIndex < CTRunGetGlyphCount(run); runGlyphIndex++){// get Glyph & Glyph-dataCFRange thisGlyphRange = CFRangeMake(runGlyphIndex, 1);CGGlyph glyph;CGPoint position;CTRunGetGlyphs(run, thisGlyphRange, &glyph);CTRunGetPositions(run, thisGlyphRange, &position);// Get PATH of outline{CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, NULL);CGAffineTransform t = CGAffineTransformMakeTranslation(position.x, position.y);CGPathAddPath(letters, &t, letter);CGPathRelease(letter);}}}CFRelease(line);combinedGlyphsPath = [UIBezierPath bezierPath];[combinedGlyphsPath moveToPoint:CGPointZero];[combinedGlyphsPath appendPath:[UIBezierPath bezierPathWithCGPath:letters]];CGPathRelease(letters);CFRelease(font);if (attrString){attrString = nil;}return combinedGlyphsPath;
}@end
复制代码

参考资料:
视频特效制作:如何给视频添加边框、水印、动画以及3D效果
视频特效制作2
AVFoundation Tutorial: Adding Overlays and Animations to Videos

转载于:https://juejin.im/post/5ca5d489f265da30c4045f6e

iOS使用AVFoundation在视频上添加字幕以及控制字幕时间相关推荐

  1. 免费将中文视频转换为英文视频并添加中英双语字幕

    免费将中文视频转换为英文视频并添加中英双语字幕 背景 女朋友需要找关于<不要随意喂养动物园的动物>的英语视频,因为限定是英语类的视频,所以在国内的视频平台基本无法找到.虽然我是个程序员,但 ...

  2. camtasia怎么在视频上添加图片

    最终需要实现的目的就是在视频上添加一个图片,大概如下: [1]"媒体"界面的左下角有一个"+"号的标志,点击,导入媒体,然后选择你想要的图片,就会导入到媒体箱 ...

  3. ios 使用AVFoundation从视频中提取音频

    ios 使用AVFoundation从视频中提取音频 在导出音频文件时候,使用 m4a格式或者wav格式,总会遇到某些视频无法正常导出,使用caf(core audio format)则可以正常导出. ...

  4. 如何在视频上添加字幕?试试这几个方法吧

    我有一个朋友,他是一名游戏爱好者.前几天,他制作了一个新的游戏教程,并想要将其上传到网络上.这时,他突然看到有一些观众留言说:"视频做的不错,但是能不能加个字幕方便理解".为了满足 ...

  5. php显示动态的文字,动态文字制作软件,视频上制作动感文字/动态字幕条

    在视频中,文字除了可以介绍或说明视频内容之外,更能适时增添视频的趣味性.在以下我们将介绍的动态文字制作软件中,带有多种预设的标题文字动画,大家可以轻松的直接套用,也能自定义文字动画,让视频影片更具专业 ...

  6. 如何用html制作一个动态烟花,视频加烟花特效 视频如何制作烟花效果|视频上添加动态的焰火效果...

    有句mmp不知当讲不当讲,今天竟然是孔子的诞辰,这样一算孔子很有可能是处女座呢!!当看到这条消息时我的内心是拒绝的,在我看来孔子的中庸思想表示的"平庸.折中.调和"明明是我们天秤座 ...

  7. 视频剪辑方法,在视频上添加图片或者视频

    最近有很多朋友在问,该如何快速剪辑视频,比如在视频画面中添加图片.或者视频中添加视频呢?其实这样的效果不难实现,下面一起来学习一下. 材料准备: 一台Win系统的电脑 安装一个媒体梦工厂 视频素材 步 ...

  8. 使用html5制作烟花的视频,视频加烟花特效 视频如何制作烟花效果|视频上添加动态的焰火效果...

    有句mmp不知当讲不当讲,今天竟然是孔子的诞辰,这样一算孔子很有可能是处女座呢!!当看到这条消息时我的内心是拒绝的,在我看来孔子的中庸思想表示的"平庸.折中.调和"明明是我们天秤座 ...

  9. python保存logo_如何用python 在视频上添加自己的logo

    先准备好自己的logo 最好是透明图片,这样添加上去后才不显得突兀.比如下面例子中的logo_sc.png就是一个透明图片. 参照如下代码处理 #!/usr/bin/python3 # -*- cod ...

最新文章

  1. Cs Tip08: 文件存储
  2. 向linux内核增加新的系统调用,为linux内核添加新的系统调用
  3. java 双向链表_23张图!万字详解「链表」,从小白到大佬
  4. 816 - Abbott's Revenge
  5. 为什么优秀和听话总是难两全?
  6. HappyAA服务器部署笔记1(nginx+tomcat的安装与配置)
  7. 支付宝回应手机黑产;微软将允许员工永久在家办公;Flutter 1.22 正式发布|极客头条
  8. CSS-Box模型--理解与整理
  9. Lesson_6 作业_1 ---- 封装学生类
  10. 小白_Unity引擎_Console控制台
  11. 计算机一级excel建立数据透视表,excel中插入数据透视表的方法
  12. 玲珑杯#3 G 1043 - G. Quailty and Square Counter【线段树-卡常数】
  13. 淘宝CRM是如何通过数据分析进行解决问题的
  14. VOB视频格式转换器怎么把vob转换为mp3
  15. 5G C-V2X技术介绍
  16. “追梦五年”主题征文『51CTO五周年庆』
  17. Python爬取新闻联播(文字版)
  18. JQuery Mobile试试水
  19. 证券基金经营机构信息技术管理办法
  20. part-18 压摆率SR

热门文章

  1. 科学解析2021年AI领域的10个大胆预测
  2. 2021年码农应该了解的所有机器学习算法
  3. 深度|人工智能赋能“新基建”产业的四方面及建议
  4. Appian宣布将Google AI 集成到RPA中
  5. 黄海广博士的机器学习个人笔记及深度学习笔记
  6. 深度丨人工智能和大数据的关系及中国在AI领域如何赶超世界
  7. Tensorflow—tensorboard网络结构
  8. (深入理解)matplotlib绘图原理(figure,axes,axis,canvas的区别)
  9. 文章推荐 | 城市规划中城市信息学的研究进展
  10. Cell颠覆性发现:中脑神经元的新作用