Android上使用FFmpeg添加文字水印和字幕 - 闭坑指南

现在我们都玩抖音这些短视频APP,我们看到它里面的视频有些是有字幕或者文字水印的,那这是怎么做到的呢?我们今天就来认识一下FFmpeg中强大的drawtextsubtitles滤镜。

在音视频行业,大多人都知道FFmpeg,因为基本大多数的视频播放器或者音视频处理都用到了它,但你可能不知道是FFmpeg中还有2大处理文字的利器:drawtextsubtitles

默认情况下,FFmpeg是不支持drawtextsubtitles,因为这个需要借助第三方库才能开启,如下就是开启的第三方库:

第三方库 版本 下载地址 添加版本 说明
fribidi 1.0.10 github.com/fribidi/fri... 1.3.2 双向文本处理,drawtext filter依赖
freetype 2.10.2 mirror.yongbok.net/nongnu/free... 1.3.2 支持多种字体格式,drawtext filter依赖
fontconfig 2.13.92 www.freedesktop.org/software/fo... 1.3.2 字体配置和渲染,drawtext filter依赖
ass 0.14.0 github.com/libass/liba... 1.3.2 字幕渲染库,可向视频添加字幕

我们在编译FFmpeg的时候需要将上述第三方库一起编译,然后再在配置中启用如下命令:

bash 复制代码
./configure \
... # 此处省略其他
# 启用fribidi
--enable-libfribidi \
# 启用fontconfig
--enable-libfontconfig \
# 启用ass
--enable-libass \
# 启用drawtext和subtitles滤镜以及相关的编解码和封装、解封装
--enable-filter=subtitles
--enable-filter=drawtext \
--enable-libfreetype \
--enable-muxer=ass \
--enable-demuxer=ass \
--enable-muxer=srt \
--enable-demuxer=srt \
--enable-muxer=webvtt \
--enable-demuxer=webvtt \
--enable-encoder=ass \
--enable-decoder=ass \
--enable-encoder=srt \
--enable-decoder=srt \
--enable-encoder=webvtt \
--enable-decoder=webvtt \

这样编译出来的FFmpeg才支持drawtextsubtitles

绘制文本-drawtext

其实drawtext就是在视频上绘制文字,那举个简单的例子:

就像上面一样,我在视频上加了一串自己的文案,原理很简单,就是对视频每一帧都给写上✍🏻文字。我们主要看看FFmpeg中使用drawtext的规则:

bash 复制代码
ffmpeg -y -i input -vf "drawtext=fontfile=${字体路径}/Pingfang.ttf:text=FFmpegCommand:x=(w-text_w)/2:y=(h-text_h)/2:fontsize=100:fontcolor=white" -c:v libx264 output
  • -vf 就是启用滤镜,那后面的内容就是滤镜的具体内容
  • drawtext 就表示我们要使用drawtext这个滤镜
  • fontfile 就表示我们的字体路径,如果没有配置fontconfig,那这个就必须传
  • text 就是我们要写的文案了
  • x、y 表示显示的位置,我这里是显示到屏幕正中间
  • fontsize 字体大小,默认16
  • fontcolor 字体颜色,颜色是定义在ffmpeg-utils里面的,可参考文档 ffmpeg.org/ffmpeg-util...

那还有其他比较重要的参数:

  • box :启用给字体绘制一个背景盒子,默认是0不绘制,1就是绘制box。还可以对盒子添加边框boxborderw=10(不让box太靠近文案),boxcolor就是绘制box的填充颜色(颜色是定义在ffmpeg-utils里面的,可参考文档 ffmpeg.org/ffmpeg-util...
lua 复制代码
ffmpeg -y -i input -vf "drawtext=fontfile=${字体路径}/Pingfang.ttf:box=1:boxcolor=black:boxborderw=10:text=FFmpegCommand:x=(w-text_w)/2:y=(h-text_h)/2:fontsize=100:fontcolor=white" -c:v libx264 output
  • borderw :给文字添加描边,borderw=3就表示添加3个像素的描边,默认为0。通过bordercolor去设置颜色,颜色也是使用 ffmpeg.org/ffmpeg-util... 此处的颜色,看结果
lua 复制代码
ffmpeg -y -i input -vf "drawtext=fontfile=${字体路径}/Pingfang.ttf:borderw=3:bordercolor=black:text=FFmpegCommand:x=(w-text_w)/2:y=(h-text_h)/2:fontsize=100:fontcolor=white" -c:v libx264 output
  • shadowx、shadowy :给文字添加投影,shadowcoror可以设置投影的颜色
lua 复制代码
ffmpeg -y -i input -vf "drawtext=fontfile=${字体路径}/Pingfang.ttf:shadowx=5:shadowy=5:shadowcolor=DimGray:text=FFmpegCommand:x=(w-text_w)/2:y=(h-text_h)/2:fontsize=100:fontcolor=white" -c:v libx264 output

还有很多其他的参数,大家可以去这里 ffmpeg.org/ffmpeg-filt... 查阅

字幕-subtitles

开发过音视频的小伙伴知道,视频的字幕分两种:

  • 软字幕:视频里包含了视频轨道、音频轨道、字幕轨道,将字幕放入了字幕轨道里,播放时从中读取,可将字幕进行分离。
  • 硬字幕:视频中不含字幕轨道,字幕是刻录在视频画面中的,无法分离字幕。

那字幕的格式一般常使用的就2种格式:

  • SRT:提供字幕内容和显示时间
  • ASS:提供字幕内容、显示时间以及字体颜色、特效等

SRT

这里我们这里只介绍SRT,对ASS感兴趣的小伙伴可以自行查阅,如下就是SRT字幕内容的格式:

lua 复制代码
1
00:00:00,120 --> 00:00:01,380
不知道明天会怎样

2
00:00:01,800 --> 00:00:03,360
又或是风雨会来临

就是如此简单,那如果我想设置字幕的颜色和字体大小该怎么办?我这里给大家提供了一份设置字体大小以及特效的文档

ini 复制代码
01.Name             风格(Style)的名称,区分大小写,不能包含逗号。例如 Default
02.Fontname         使用的字体名称,区分大小写。例如 Arial
03.Fontsize         字体的字号,一般16号就可以
04.PrimaryColour    设置主要颜色, 为蓝-绿-红三色的十六进制代码相排列, BBGGRR. 为字幕填充颜色,例如 &Hffffff
05.SecondaryColour  设置次要颜色, 为蓝-绿-红三色的十六进制代码相排列, BBGGRR. 在卡拉OK效果中由次要颜色变为主要颜色.
06.OutlineColour    设置轮廓颜色, 为蓝-绿-红三色的十六进制代码相排列, BBGGRR.
07.BackColour       设置阴影颜色, 为蓝-绿-红三色的十六进制代码相排列, BBGGRR. ASS的这些字段还包含了alpha通道信息. (AABBGGRR), 注ASS的颜色代码要在前面加上&H
08.Bold             -1为粗体, 0为常规
09.Italic           -1为斜体, 0为常规
10.Underline       [-1 或者 0] 下划线
11.Strikeout       [-1 或者 0] 中划线/删除线
12.ScaleX          修改文字的宽度,为百分数,例如 100
13.ScaleY          修改文字的高度,为百分数
14.Spacing         文字间的额外间隙. 为像素数
15.Angle           按Z轴进行旋转的度数, 原点由alignment进行了定义. 可以为小数
16.BorderStyle     1=边框+阴影, 3=纯色背景. 当值为3时, 文字下方为轮廓颜色的背景, 最下方为阴影颜色背景.
17.Outline         当BorderStyle为1时, 该值定义文字轮廓宽度, 为像素数, 常见有0, 1, 2, 3, 4.
18.Shadow          当BorderStyle为1时, 该值定义阴影的深度, 为像素数, 常见有0, 1, 2, 3, 4.
19.Alignment       定义字幕的位置. 字幕在下方时, 1=左对齐, 2=居中, 3=右对齐. 1, 2, 3加上4后字幕出现在屏幕上方. 1, 2, 3加上8后字幕出现在屏幕中间. 例: 11=屏幕中间右对齐. Alignment对于ASS字幕而言, 字幕的位置与小键盘数字对应的位置相同.
20.MarginL         字幕可出现区域与左边缘的距离, 为像素数
21.MarginR         字幕可出现区域与右边缘的距离, 为像素数
22.MarginV         垂直距离

怎么设置字幕特效,大家一目了然,但是有2个点要注意:

  • 凡是设置颜色的地方都采用的是BGR格式,而非我们常用的RGB(就是要反正写😏)。
  • Alignment字幕位置,
    • 字幕出现在屏幕下方:1=左对齐, 2=居中, 3=右对齐。
    • 字幕出现在屏幕上方:1, 2, 3加上4后. 也就是5=左上,6=顶部居中,7=右上
    • 字幕出现在屏幕中间:1, 2, 3加上8后. 也就是9=左侧居中,10=正中,11=右侧居中
css 复制代码
ffmpeg -y -i input -vf "subtitles=${字体文件位置}:force_style='fontname=苹方 常规,fontsize=40,PrimaryColour=&H000000,OutlineColour=&HF0F0F0,Italic=0,BorderStyle=1,Alignment=2'" -c:v libx264 output

如上就是我设置的字幕显示,每隔一段时间就显示一句(间隔时间请看上面SRT例子中的时间),不会一直固定在这里。在命令中有2个点特别重要:

  • force_style之后的内容都是使用单引号("'")引起来的,不加会报错。
  • fontname设置字体时需要进行fontconfig的配置,而且一定要使用字体名而非文件名,类似下图,字体文件名为PingFang Regular.ttf,但字体名为苹方 常规

配置fontconfig

那如何配置fontconfig呢?在一般的linux、windows、macOS系统上,它会自动查找查找并获取字体字幕。在Android上不配置就会报错。 其实解决的关键点就是向FontConfig设置环境变量:

c 复制代码
extern "C"
JNIEXPORT void JNICALL
Java_com_coder_ffmpeg_jni_FFmpegConfig_00024Companion_setFontConfigPath(JNIEnv *env, jobject thiz,jstring env_value) {
    const char *value = env->GetStringUTFChars(env_value,JNI_FALSE);
    setenv("FONTCONFIG_PATH", value, 1);
    env->ReleaseStringUTFChars(env_value,value);
}

但是请注意,这里设置FontConfigPath不是字体文件目录哦,而是一个类似于下面这个格式的配置文件:

xml 复制代码
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <!-- 设置字体目录 -->
    <dir>/path/to/your/fonts</dir>

    <!-- 添加字体文件匹配规则 -->
    <match target="pattern">
        <test name="family" qual="any">
            <string>YourFontFamilyName</string>
        </test>
        <edit name="family" mode="prepend" binding="strong">
            <string>YourPreferredFontFamily</string>
        </edit>
    </match>
</fontconfig>

所以我们在处理的时候,需要自行构建一个这样的文件,然后通过上方setFontConfigPath将这个配置文件设置到环境变量中。

使用开源库

是不是感觉比较复杂的样子,大家其实也完全不必要自己去写这一部分代码,很多FFmpeg开源库都自己加了相关内容,你只需要简单接入就行了。 我本身也开源了相关的内容,大家感兴趣也可以去看看【FFmpegCommand】

以上关于在Android上使用FFmpeg的水印文字和字幕的全部内容,咱们评论区见😄

相关推荐
落落落sss6 分钟前
sharding-jdbc分库分表
android·java·开发语言·数据库·servlet·oracle
消失的旧时光-19432 小时前
kotlin的密封类
android·开发语言·kotlin
服装学院的IT男3 小时前
【Android 13源码分析】WindowContainer窗口层级-4-Layer树
android
「QT(C++)开发工程师」4 小时前
【FFmpeg应用场景概述】
ffmpeg
cuijiecheng20184 小时前
音视频入门基础:AAC专题(6)——FFmpeg源码中解码ADTS格式的AAC的Header的实现
ffmpeg·音视频·aac
yunhuibin4 小时前
ffmpeg面向对象——参数配置秘密探索及其设计模式
学习·设计模式·ffmpeg
CCTV果冻爽5 小时前
Android 源码集成可卸载 APP
android
码农明明5 小时前
Android源码分析:从源头分析View事件的传递
android·操作系统·源码阅读
秋月霜风6 小时前
mariadb主从配置步骤
android·adb·mariadb
Python私教6 小时前
Python ORM 框架 SQLModel 快速入门教程
android·java·python