一、背景
在iOS平台下,使用FFmpeg tools(命令行)开发添加文字水印功能需要添加libfreetype、libfontconfig、libfribidi库.
为什么需要这3个库?因为在ffmpeg官方说明文档中:
11.60 drawtext
Draw a text string or text from a specified file on top of a video, using the libfreetype library.To enable compilation of this filter, you need to configure FFmpeg with --enable-libfreetype. To enable default font fallback and the font option you need to configure FFmpeg with --enable-libfontconfig. To enable the text_shaping option, you need to configure FFmpeg with --enable-libfribidi.
翻译过来意思是:
使用libfreetype库在视频指定文件中绘制文本字符串或文本。要启用此过滤器的编译,您需要使用--enable-libfreetype配置FFmpeg。要启用默认字体后备和字体选项,您需要使用--enable-libfontconfig配置FFmpeg。要启用text_shaping选项,您需要使用--enable-libfribidi配置FFmpeg。
所以,这里我们需要自行编译libfreetype、libfontconfig、libfribidi库。
二、编译第三方库
在ffmpeg中,加入第三方库需要下载源码并将它编译。使用brew install libfreetype安装是没用的,因为这样安装出来的freetype只有x86架构,并没有其它架构。必须要像网上x264教程一样,需要下载它的源码,使用xcode编译出它的静态库出来,再在FFmpeg编译中添加参数--enable-libfreetype、--enable-libfontfig、--enable-libfribidi.这样FFmpeg才会将这三个库加进去一起编译。
我使用的脚本是mobile-ffmpeg,在这个脚本中包含了编译脚本与源码:
1.源码
freetype库源码位于mobile-ffmpeg/src/freetype
fontconfig库源码位于mobile-ffmpeg/src/fontconfig
fribidi库源码位于mobile-ffmpeg/src/fribidi
所有ffmpeg使用到的第三方库都放到了mobile-ffmpeg/src目录下,如有新版本或想更换源码可以替换该路径。
2.编译脚本
freetype编译脚本位于mobile-ffmpeg/build/ios-freetype.h
fontconfig编译脚本位于mobile-ffmpeg/build/ios-fontconfig.h
fribidi编译脚本位于mobile-ffmpeg/build/ios-fontconfig.h
所有ffmpeg使用到的第三方库的编译脚本都在mobile-ffmpeg/build中。
3.编译环境准备
编译环境需要Xcode 8和Command Line Tools for Xcode8。(可见上一篇 iOS集成FFmpeg开发)
4.编译命令
cd mobile-ffmpeg
./ios.sh --disable-arm64e --disable-armv7s --enable-fontconfig --enable-freetype --enable-fribidi
编译完成后会在当前目录生成一个prebuilt目录,里面包含arm64、armv7、i386、x86_64架构下已经编译的第三方库与ffmpeg库。静态库合并之后放在ios-universal中
第三方库我们取expat、fontconfig、freetype、fribidi、libpng、libuuid中的静态库,需要将他们加入到工程的链接库中。
三、测试
1.新建Xcode工程
按照 iOS集成FFmpeg开发 的方法,直接替换ffmpeg库和新增第三方库,我们编写以下命令作为测试代码:
ffmpeg -i test.mp4 -vf drawtext=fontfile=Songti.ttc:text='测试水印':x=10:y=10:fontsize=24:fontcolor=white test_output.mp4
运行后打开test_output.mp4成功看到文字水印。
编译不再报错:No such filter: 'drawtext' ,报没有drawtext滤镜的错误。
2.文字水印含有符号的情况
1).在文字水印中含有冒号:时,ffmpeg运行会报错:
[Parsed_drawtext_0 @ 0x7f8d21702000] Cannot find a valid font for the family Sans
[AVFilterGraph @ 0x7f8d1e50e640] Error initializing filter 'drawtext' with args 'fontfile=/Library/Fonts/Songti.ttc:text=测试水印:90%:x=10:y=10:fontsize=24:fontcolor=white'
Error reinitializing filters!
Failed to inject frame into filter network: No such file or directory
Error while processing the decoded data for stream #0:0
原因是文字水印中的冒号:是ffmpeg中的分隔符,需要将它转义.
2). 在文字水印中含有百分号%,ffmpeg运行会报错:
[Parsed_drawtext_0 @ 0x7ffa57d0ecc0] Stray % near ''
Last message repeated 1 times
原因是百分号%之后需要它要找大括号,因为%{...}格式是函数扩展模式,可见ffmpeg命令官网介绍
所以我们这里的解决方案就是增加命令expansion=none,指定扩展模式为逐个字符打印
ffmpeg -i test.mp4 -vf drawtext=fontfile=Songti.ttc:text='测试水印\\:90%':x=10:y=10:fontsize=24:fontcolor=white:expansion=none test_output.mp4
四、分析编译脚本
回过头来,我们简单分析一下mobile-ffmpeg脚本
第三方库和ffmpeg源码放在mobile-ffmpeg/src/* 中,编译脚本放在mobile-ffmpeg/build/*中,
如果我们对ffmpeg编译配置需要修改,可以打开mobile-ffmpeg/build/ios-ffmpeg.sh进行添加或修改。
最外层使用脚本位于mobile-ffmpeg/ios.sh,打开该脚本阅读可以看到它的逻辑。可对脚本进行修改以满足需求。
五、结束
文中Demo:
参考资料:https://github.com/tanersener/mobile-ffmpeg