记录一些和 Unicode 不断作斗争的日子

最开始给哔哩哔哩周刊写自动化脚本的时候,还不觉得生成图片能遇到什么坑。毕竟之前也用过 Pillow 库,算是比较熟悉了。而且遇到的都是些在普通不过的正常文本。

直到躲不开的 emoji 开始出现了。

一些普通的 Emoji

☀☁☂☃☄☎☑☔☕☘

刚开始遇到这类也还好,因为很显然,只是文本的字体没有这部分 emoji,Pillow 就全部给显示成了方框。简单框了个范围,用另一个字体来渲染就是了。

但后来就开始遇到各种标题里的花活,什么上下标字符花体字粗斜体全来了。比如

【𝟒𝐊 𝟔𝟎𝐅𝐏𝐒】这首《𝑭𝒂𝒍𝒍𝒊𝒏𝒈 𝑨𝒈𝒂𝒊𝒏》如今治愈了多少人!!! ℳ₯㎕-沉 沦

自此真正打响了与 Unicode 斗争的第一枪。

一些普通的 Unicode

上下标字符花体字粗斜体也能接受,人家看起来至少还是个正经字符。解决方法也是一样的简单粗暴:找一个定义了这部分字符的字体,单独匹配渲染。

于是脚本里的 UnicodeA_F 慢慢增加到了 UnicodeD_F。划一个新的正则范围,匹配上一个新的字体,如此查漏补缺的工作也还能接受,毕竟遇到特殊字符的场合相对还是非常有限的。

直到真正的重量级上场了。

Combining 字符

✥我҉͛̀̈̈̾̓̀͂̊͝的模҉̖̭̱͍̩͕͓̋̓͋̈̑͋̉͢͞ͅ样吓҈̎̍̅̒̎͂̈́̚͞.到你҈̛́̐̄́̃͗̓͒͒͊̿͛̒了?~❤✥

只能承认它杀死了比赛。但其实类似的标题并不是第一次见,在更早之前,我算是见过它的一位大前辈:

【初音ミク】宇宙大规模 11 次元构造体【ATOLS】

这位前辈更是重量级,即便在写这篇记录的时候,我也不得不佩服这种和视频契合的标题风格确实是非常到位。

能做到这种效果的原因是由于其中大量的 Combining 字符,比如日文的清浊音符号,部分小语种的音标和一些独特的组词方式。

但是 Pillow 罢工了呀,臣妾渲染不来,您还是另请高明吧。

思来想去不得法,最后想到,那既然网页前端能够正常展示,应该可以通过无头浏览器前端渲染然后截屏的方式,把这些特殊字符正确的显示出来。

简单糊了个页面,算是解决了这个问题。哔哩哔哩周刊与 Unicode 的斗争也算是告一段落了。

MAD 周刊,新的挑战

接手开始MAD 周刊的自动化后,很快又不得不面对 Unicode 带来的问题。然而实际上,应该说是 Unicode 和 Adobe 共同带来的问题。

为了保证原始 MAD 周刊工程文件的纯洁性,所有的文本都按照文本图层来进行修改。本来这也没有什么问题。

但是原工程使用的大量表达式,是基于旧版的 ExtendScript 引擎,毕竟工程本身是 2016 年的产物。但之前做哔哩哔哩周刊时一直用的是 JavaScript 引擎的表达式,这就产生了几个问题:

  1. 特殊的 Unicode 字符需要使用不同的字体才能正常显示
  2. ExtendScript 不能修改文本图层的部分字体样式属性
  3. 相比 ExtendScript,JavaScript 能够修改字体字号颜色等属性
  4. 为了使用 JavaScript 引擎就要把整个工程的其他表达式全部重写
  5. AfterEffects 对通过脚本修改字体的行为有奇怪的问题,不能保证正常显示

由于工作量太大,重写全部表达式显然不现实。基于此,我选择了另一种方式:让所有花活都变成正常的字符。

这就需要有一个表来记录这些特殊字符应该被替换为具体哪一个字符,于是诞生了 Antimemetics-Division 这样一个对抗项目。

期间则是枯燥的 Unicode 查表浏览过程,尽可能多的搜集这类特殊字符的标题来保证更广的覆盖面。

而后 Emoji 的问题也需要处理,这就要划分 Emoji 的 Unicode 字符范围。幸好这部分有据可查,在 Unicode 官方规范中有详细的记录各个 Emoji。

Combining 字符的问题也得到了解决,Unicode 官方规范中规定了 Mc Me Mn 三类 Mark 字符正好能够覆盖这个问题。

最终 Antimemetics-Division 不负使命,让 MAD 周刊中的标题都成为了“正经标题”,可喜可贺,可喜可贺。

虽然留下了反向利用此项目可以生成更加让人血压爆炸的标题的问题,暂且不提

本可以更优雅的解决方式

如是几期视频更新后,我逐渐意识到一种割裂感。

为什么哔哩哔哩周刊就应该渲染正常,MAD 周刊就要去掉这些字符呢?这种区别对待说白了,不过还是一种懒惰。

不同于我最初承认 ATOLS 玩的一手好标题,在 MAD 周刊上我反而以字符论标题优劣,不应是正确的解法。

于是决定同哔哩哔哩周刊一样通过前端截图来解决这个问题。同时考虑到排版影响,部分 MAD 标题常用全角符号,导致标题的起始像素位置其实并不顶格,便在脚本中加入了一个粗略的判断,进行一个 X 轴的移位使得视觉上显得更对齐一些。

但 Emoji 还是给我捣了乱,Emoji 因为都是全角宽度,无法判断像素位置是否顶格,这个问题只能留到之后再寻找合适的解法了。

Update 2022/10/03

成了,生成图片然后切左右透明像素就是了,问题解决

未尽之事

计划将哔哩哔哩周刊的图片生成也改为前端截图的方式。且不谈特殊字符的问题,前端这种方便可视化调整的形式,应该会对代码修改更友好一些,虽然想来是不会有什么改版和修改了。

而且通过 CSS,还能够实现一些 Pillow 做不到的文本样式效果,更好的还原 PSD 的设计样式。

曾经还想过写 Photoshop 脚本来做图,虽然还没试验过 Photoshop,考虑到前述 AfterEffects 文本图层的问题,以及前端截图确实更灵活,也就不再考虑了。

Built with Hugo
主题 StackJimmy 设计