浅尝开源项目:FreeMote

这是一个比较冷门的开源项目,可以看作是E-Mote的开源实现。之前我还是用Windows做主力机使用的Nekopara动态壁纸就是这个项目实现的,而现在我已经切换到Linux作为主力系统使用一坤年了,是时候想想办法把我的巧克力弄到我的桌面上了。
Linux想搞动态壁纸,主要就是两种:视频和网页。而FreeMote-SDK就有网页的WebGL实现。
很早之前我就尝试过一次,但是那时候技术力不足,而且没学会查看文档,失败了。这次,既然我都能写文章发出来了,那肯定是取得了阶段性的进展了。
相比于Live2D,E-Mote的应用就比较少了,主要是几个Galgame在用,其中就包括NEKOPARA。而绝大部分网站的动态二次元看板娘都是Live2D实现的,E-mote几乎看不见。所以文档少,案例少,基本上是摸著石头过河。
我主要是研究网页端的FreeMote,下面,就开始探索吧。

Demo分析

这是项目Project-AZUSA给的网页Demo project-azusa.github.io 基本上可以在网页实现E-mote的功能。不过看了一下FreeMote-SDK,文档约等于没有,只能自己根据网页Demo进行推断了。
看描述,说是需要Pure(unencrypted) PSB文件,当然,此PSB不是Photoshop的文件,而是这一套工具的文件格式。为了得到这个文件,则需要FreeMote的这些工具进行转换。
接下来就是那个Demo网页用到的文件,我已经爬取下来了:

.
├── data
│   └── emote_test2.pure.emtbytes
├── driver
│   ├── emoteplayer.js
│   └── FreeMoteDriver.js
├── img
│   └── bg.jpg
├── index.html
└── main.js

4 directories, 6 files

从文件命名就可以看出,emote_test2.pure.emtbytes是模型文件。但是其格式却不是psb?但是也有可能只是换了一下后缀名。
搞清楚了大概的情况,关键点就在于模型文件的获取,以及尝试去替换另一个模型。虽然FreeMote-SDK没有什么文档,但是FreeMote项目的文档还是相对比较完善的,对于生成特定的模型文件具有比较高的参考价值。

Demo模型转换测试

开始之前,只需要下载FreeMote的工具集即可,在Release里面就有下载了。
首先是先要分析现有的文件,按照文档的说法,我决定先尝试解包实例Demo的模型文件:

[chocola@chocola-sa5212m4 data]$ wine ../../Ulysses-FreeMoteToolkit-v4.0.3/PsbDecompile.exe ./emote_test2.pure.emtbytes 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Decompiler
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Decompiling: emote_test2.pure
Done.
[chocola@chocola-sa5212m4 data]$ ls
emote_test2.pure  emote_test2.pure.emtbytes  emote_test2.pure.json  emote_test2.pure.resx.json
[chocola@chocola-sa5212m4 data]$ tree
.
├── emote_test2.pure
│   └── tex-texture.png
├── emote_test2.pure.emtbytes
├── emote_test2.pure.json
└── emote_test2.pure.resx.json

2 directories, 4 files
[chocola@chocola-sa5212m4 data]$ 

可以看到解包后有tex-texture.png纹理图片和emote_test2.pure.json设置文件,其中纹理图片和Live2D的纹理图片看起来很像。
然后,再尝试合成回psb文件:

[chocola@chocola-sa5212m4 data]$ wine ../../Ulysses-FreeMoteToolkit-v4.0.3/PsBuild.exe ./emote_test2.pure.json 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Compiler
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Compiling emote_test2.pure ...
Compile emote_test2.pure done.
Done.
[chocola@chocola-sa5212m4 data]$ ls
emote_test2.pure  emote_test2.pure.emtbytes  emote_test2.pure.json  emote_test2.pure.pure.psb  emote_test2.pure.resx.json

可以看到,得到了emote_test2.pure.pure.psb文件,尝试去替换掉原本的emote_test2.pure.emtbytes文件,看看能不能正常工作。
这里需要修改main.js文件,找到文件加载路径,将emote_test2.pure.emtbytes替换为emote_test2.pure.pure.psb就可以了:

    // load data then, register mouse event
    player.promiseLoadDataFromURL("./data/emote_test2.pure.pure.psb")

然后我测试了一下,一切正常,说明整个工具链是可以用的,WebGL端确实是可以使用工具生成的pure.psb文件。

尝试替换模型

因为项目文档里面说有psb测试文件可以供使用,存放的仓库是FreeMote.Samples,于是我就去下了一个模型:[FlattenArray][PSBv4][win]dx_ふかみ_駅員服.psb,来进行尝试。
因为这个模型文件名太长了不方便,我直接重命名为test.psb了,下面就是操作:

[chocola@chocola-sa5212m4 Ext_Asset]$ wine ../Ulysses-FreeMoteToolkit-v4.0.3/PsbDecompile.exe test.psb 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Decompiler
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Decompiling: test
Done.
[chocola@chocola-sa5212m4 Ext_Asset]$ tree
.
├── test
│   └── tex-texture.png
├── test.json
├── test.psb
└── test.resx.json

2 directories, 4 files
[chocola@chocola-sa5212m4 Ext_Asset]$ wine ../Ulysses-FreeMoteToolkit-v4.0.3/PsBuild.exe test.json 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Compiler
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Compiling test ...
Compile test done.
Done.
[chocola@chocola-sa5212m4 Ext_Asset]$ wine ../Ulysses-FreeMoteToolkit-v4.0.3/EmtConvert.exe test.pure.psb.lz4 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Converter
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Shell type: LZ4
Done.
[chocola@chocola-sa5212m4 Ext_Asset]$ wine ../Ulysses-FreeMoteToolkit-v4.0.3/FreeMoteViewer.exe test.pure.psb.decompressed.psb 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote Viewer
by Ulysses, wdwxy12345@gmail.com

最后一个命令,是查看生成的模型test.pure.psb.decompressed.psb是否正常,界面大概长这样:
x_20250718_135733.png
确定无误后,我满怀信心的将模型替换到WebGL端,结果。。。
x_20250718_140851.png
居然报错了?不过细看红色框出来的地方:motion file 'template' has not adaptive spec [win] of motion file. export psb again.
似乎是因为模型属性不兼容,针对win这个关键字,我检索了两个模型的json文件。
x_20250718_141308.png
好兄弟,看出来区别了吗?正常运行的那个模型specPlatform对应的值是ems而不能运行的对应的是win,所以。。。改一下?把win全换成ems
然后再重新转换一下:

[chocola@chocola-sa5212m4 Ext_Asset]$ wine ../Ulysses-FreeMoteToolkit-v4.0.3/PsBuild.exe test.json 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Compiler
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Compiling test ...
Compile test done.
Done.
[chocola@chocola-sa5212m4 Ext_Asset]$ wine ../Ulysses-FreeMoteToolkit-v4.0.3/EmtConvert.exe test.pure.psb.lz4 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Converter
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Shell type: LZ4
Done.

x_20250718_141848.png
不过,似乎改完之后颜色变奇怪了?然后发现原来的那个模型文件颜色也是奇怪的,那没事了,直接开始尝试!
x_20250718_142357.png
虽然动作有点奇怪,但是至少成功了!

获取猫娘模型

我先不打算解包NEKOPARA,怕东西太多了,打算先拿这个项目的作者自己搞得猫娘动态壁纸开刀。对,就是我之前提到的在Windows上面用的动态壁纸。
看了一下那个动态壁纸的文件,应该是Unity3D做的,那只需要解包工具就好了,使用AssetStudio就可以完美解包了。资源的文件在NekoWallpaper_Data/data.unity3d
AssetStudioGUI打开这个文件,在Asset List选项卡中,点一下Container标题,就可以按照存放的目录排序了,这样子比较好找模型。
x_20250718_143913.png
我们就拿牛奶来开刀吧,需要的文件是milk-wintermilk-winter-b_tex000.png,把这两个文件提取出来。
其中没有后缀名称这个,个人推断是psb文件。
然后对没有后缀名的文件进行转换:

[chocola@chocola-sa5212m4 winter]$ wine ../../../Ulysses-FreeMoteToolkit-v4.0.3/PsbDecompile.exe milk-winter
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Decompiler
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Decompiling: milk-winter
Done.
[chocola@chocola-sa5212m4 winter]$ tree
.
├── milk-winter
├── milk-winter-b_tex000.png
├── milk-winter.json
├── milk-winter-resources
│   └── tex-texture.png
└── milk-winter.resx.json

2 directories, 5 files

可以看到多了一个纹理图片,但是我查看过后发现实际上是空图片,所以,我将提取出来的图片替换掉了解包出来的空图片。
然后,合成psb:

[chocola@chocola-sa5212m4 winter]$ wine ../../../Ulysses-FreeMoteToolkit-v4.0.3/PsBuild.exe milk-winter.json 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Compiler
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Compiling milk-winter ...
Compile milk-winter done.
Done.

但是,有一部分的模型,解包出来是没有纹理的:

[chocola@chocola-sa5212m4 pajama]$ tree
.
├── vanilla-pajama
├── vanilla-pajama.json
└── vanilla-pajama.resx.json

1 directory, 3 files

这时候就需要自己添加纹理了,先将提取出来的纹理放到同一个目录下:

[chocola@chocola-sa5212m4 pajama]$ tree
.
├── vanilla-pajama
├── vanilla-pajama-a-ex2-type2_tex000.png
├── vanilla-pajama.json
└── vanilla-pajama.resx.json

1 directory, 4 files

在生成psb文件后关联纹理:

[chocola@chocola-sa5212m4 pajama]$ wine ../../../Ulysses-FreeMoteToolkit-v4.0.3/PsBuild.exe vanilla-pajama.json 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Compiler
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Compiling vanilla-pajama ...
Compile vanilla-pajama done.
Done.
[chocola@chocola-sa5212m4 pajama]$ wine ../../../Ulysses-FreeMoteToolkit-v4.0.3/PsBuild.exe link vanilla-pajama.pure.psb vanilla-pajama-a-ex2-type2_tex000.png 
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:mscoree:parse_supported_runtime sku=L".NETFramework,Version=v4.8" not implemented
0024:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
FreeMote PSB Compiler
by Ulysses, wdwxy12345@gmail.com
18 Plugins Loaded.

Link vanilla-pajama.pure done.
Done.
[chocola@chocola-sa5212m4 pajama]$ tree
.
├── vanilla-pajama
├── vanilla-pajama-a-ex2-type2_tex000.png
├── vanilla-pajama.json
├── vanilla-pajama.pure.linked.psb
├── vanilla-pajama.pure.psb
└── vanilla-pajama.resx.json

1 directory, 6 files

其中,vanilla-pajama.pure.linked.psb就是最终文件了。
处理完成后,可以看到,效果非常好:
x_20250718_145309.png
接下来,如前所述,改一下属性值,尝试放到网页上。
x_20250718_145947.png
真不错,下一步工作就是继续完善了,这个阶段性成果我已经很满意了!