某简单易懂的LibASS使用说明
前言
最近在写Foobar的弹幕支持插件(见 Foobar字幕(弹幕)支持插件开发日志),在ASS格式支持部分需要用到LibASS,这里就把使用的情况记录一下吧~
简介
ASS / SSA格式,全称Advanced Substation Alpha / Substation Alpha,是一种功能极为强大的字幕格式,其实跟ASS WE CAN是米有关系的~ASS本质是文本文档,编辑非常方便.关于ASS格式的使用不是本文的讨论范围,这里不予叙述~
LibASS则是一个轻量级的对ASS / SSA格式字幕进行渲染的函数库.该库使用C编写,效率较高.据官方说明,LibASS和VSFilter兼容性最好~
*LibASS依赖的第三方库: FreeType, iConv(可选), FontConfig(可选)
FreeType是LibASS使用的通用字体渲染库,也是很强大的库,作用是把系统的字库(ClearType神马的)渲染成单张Bitmap(位图)~
使用流程
以下就以LibASS自带的Test.c为例,说明一下LibASS的工作方式.下列函数顺序调用,即可最简使用LibASS.
-
初始化LibASS / init()
这个函数用于初始化LibASS的,只有两个参数:输出位图的长和宽.
1.ass_library_init()函数:
作用:初始化LibASS的字幕库(ASS_Library)
参数:无
返回值:字幕库的指针/ ASS_Library*
2.ass_renderer_init()函数:
作用:初始化LibAss的渲染器(ASS_Renderer)
参数:字幕库的指针 / ASS_Library*
返回值:渲染器的指针 / ASS_Renderer*
3.ass_set_frame_size()函数:
作用:指定输出位图大小
参数1:渲染器的指针 / ASS_Render*
参数2:输出位图的宽 / int
参数3:输出位图的长 / int
返回值:无
4.ass_set_fonts()函数:
作用:指定使用的字体库,如果没有使用FontConfig库的话,必须指定字体,否则渲染失败.
参数1:渲染器的指针 / ASS_Renderer*
参数2:字库完整文件路径 / const char*
参数3:字体类型 / const char*
参数4:是否使用FontConfig / int
参数5:FontConfig路径 / const char*
参数6:是否更新FontConfig的缓冲 / int
返回值:无
ASS_Library结构体:
字体信息库.
ASS_Renderer结构体:
字幕渲染器,包含该帧的渲染信息. -
读取字幕
初始化完成了就可以开始读取ASS格式字幕了,LibASS很方便地把读取文件写在一个函数里面了,基本不用考虑文件编码问题,因为这个函数已经为我们做好转换的工作了.
1.ass_read_file()函数:
作用:读取ASS格式字幕到音轨库(ASS_Track)
参数1:字幕库的指针 / ASS_Library*
参数2:ASS字幕文件完整路径 / char*
参数3:代码页 / char* (如果ASS文件不是Unicode编码的话,需要手动检测ANSI的代码页)
返回值:音轨库的指针 / ASS_Track*
ASS_Track结构体:
与其叫音轨库,我觉得叫字幕事件库更合适,包含一个曲目的字幕事件. -
渲染字幕
万事具备,在上面函数调用完后,LibASS有足够的信息去渲染字幕了.
1.ass_render_frame()函数:
作用:生成某帧的字符位图库(ASS_Image).
参数1:渲染器的指针 / ASS_Renderer*
参数2:音轨库的指针 / ASS_Track*
参数3:需要渲染帧的时间(单位:毫秒) / long long
参数4:检测前后两帧是否相同的标识 / int*
返回值:当前帧的字符位图库的指针 / ASS_Image*
*注意这个函数,每次调用会把上一次生成的ASS_Image释放
2.gen_image()函数:
这个函数其实不是LibASS的函数,是test.c的函数例子.
作用:生成一张自定义大小的空自定义位图(image_t),且为其分配内存空间.
参数1:输出位图的宽 / int
参数2:输出位图的长 / int
返回值:自定义位图的指针 / image_t*
3.blend()函数:
这个函数也不是LibASS的函数,且循环调用blend_single()函数.
作用:把参数2中字符位图库的位图混合到参数1的自定义位图中.
参数1:自定义位图的指针 / image_t*
参数2:字符位图库的指针 / ASS_Image*
返回值:无 -
清理工作
至此,已经完成对1帧字幕的渲染,得到了一幅自定义格式的位图了.如果不需要再渲染其他帧,则需要对LibASS进行清理.
1.ass_free_track()函数:
参数:音轨库的指针 / ASS_Track*
2.ass_renderer_done()函数:
参数:渲染器的指针 / ASS_Renderer*
3.ass_library_done()函数:
参数:字幕库的指针 / ASS_Library*
至此完成对LibASS的使用,生成的位图(Bitmap)可以按照自己需要再加工成别的图片格式,详情可以查看其他开源图片格式的开发文档,这里不再叙述.
需要特别注意的是,如果要获得可以直接让视频接口支持的位图,还需要自行了解接口的SDK说明~
Remark
这里说明一下使用LibASS要注意的地方.
-
关于ASS_Image的数据结构
结构体定义:
w:字符位图的宽 / int
h:字符位图的长 / int
stride:字符位图的块大小 / int
bitmap:字符位图的数据 / unsigned char*
color:字符位图的颜色 / unsigned
dst_x:字符位图在自定义位图的x坐标 / int
dst_y:字符位图在自定义位图的y坐标 / int
next:下一张字符位图的指针 / ASS_Image*
说明:
Stride是一幅位图的块大小,在很多情况都需要用到,计算公式如下:
Stride = 每像素字节数 * 位图宽度
ASS_Image定义的是单色位图,故每像素字节数为1,则这里Stride = 位图宽度.可得Bitmap的总Buffer Size:
Size = Stride * 位图高度,代入上式:
Size = 位图宽度 * 位图高度 (单位:Byte)
在这里,Bitmap的数据用于表示每像素的灰度(或Alpha值). -
关于image_t的数据结构
结构体定义
width:输出位图的长 / int
height:输出位图的宽 / int
stride:位图块大小 / int
buffer:位图数据 / unsigned char*
说明:
这个结构体并不是LibASS的数据结构,是test.c的自定义位图格式.
这里的Stride依照需求,取值会不同,公式仍然和上一样.如果要获得标准RGB(24Bit / 3Byte)位图,则这里的位图块大小:
Stride = 3 * 位图宽度
如果想要获得ARGB(32Bit / 4Byte)的位图的话,则位图块大小:
Stride = 4 * 位图宽度
总位图Buffer Size计算方式同上. -
关于位图数据(Bitmap Buffer)的数据结构
按照标准Windows Bitmap定义,(24bit / 32bit)位图每像素信息储存方式:
0xBBGGRR(AA)
如果是2Bit – 16Bit的位图,储存将按照颜色表(Color Pattern)方式存储,这里不在讨论.
后记
LibASS一直作为视频播放器内部使用的开源库,以其轻便高效的特点,完全没有压力地占领了大部分视频播放器对ASS / SSA的支持方式.
虽然官方没有给出完成的SDK文档,但是我觉得源代码 / 头文件给出的注释已经很给力了,我写这篇东西貌似有点多此一举?!
挺有用的,感谢。
菜鸡不太熟 C。
最近要用 Electron.js 做一个类似 Aegisub (功能) 的编辑器。
所以在网上查相关文章