基于 E-mote 模型的动态猫娘展示与部署教程

看门见山,先给一个展示地址看看效果:猫娘乐园角色E-mote图鉴

项目缘起

很久之前,在我切换到Linux系统后,发现我之前最喜欢的猫娘乐园动态壁纸没办法在Linux上使用,然后根据那个第三方壁纸的相关信息,刨根问底发现了FreeMote这个开源项目,并且看到了他的Web段实现了Demo,就萌生了这个项目的想法了。
但是碍于那时候技术能力和能分配的时间有限,于是这个想法就一直搁置了。最近不知道哪根经搭错了,突然就想把这个多年前的想法去实现,重新翻阅了相关的开源项目,借助AI,然后发现当时不能成功是疏漏了一些东西,于是打算再次去尝试实现。一开始的那几天天天碰壁,试了很多不同的方法都不行,但是,偶然的一次机会,我观察到提取的模型和解包的模型有相似之处,于是我就尝试从中间进行合成,没想到,真成功了!接下来的工作就顺风顺水了,但是就是很累人,要组织和转换每一个模型,八个猫娘,主要的六个猫娘还有好几套衣服,那个工作量是真的巨大啊!但是,如你所见,经过不懈努力,这个项目做出来了!
接下来,请让我为你介绍——NekoWebShow

开发技术路线

简单来说,这个项目最核心的部分就是FreeMote-SDK,没有这个开源的项目,本项目也无法实现。本项目是在弄清楚FreeMote这套框架逻辑后,将从UlyssesWu制作出来的的猫娘乐园角色动态壁纸解包出来的模型转换为可以让FreeMote-SDK的WebGL驱动的pure.psb格式,然后将各个模型和对应的声音组织好,写一个用于切换不同角色的前端框架,这就是我所做的事情。
前期的一部分开发工作记录,我已经写了一篇文章:试玩FreeMote,把二次元老婆搬上浏览器,感兴趣的可以去看看,这篇文章关注点是如何使用和部署。
因为前端需要实现的功能比较简单,所以我是直接面向LLM编程了,没有使用其他框架。本来想用MDUI的,但是后面想想还是算了。

在这里,要特别感谢嘉然小姐对本项目的支持,她帮助我解决了驱动库无法加载超过32MBpure.psb文件问题。没有她的支持,部分角色衣服的模型就没办法正常展示出来了。

项目分支说明

项目有两个分支,一个是php版本,另一个是html版本。之前是只打算做php版本的,毕竟可以代码复用,减少文件数量和代码量,但是后面考虑到如果是本地部署起来做动态壁纸,还要再跑一个php-fpm有点太地狱了,于是就搞了html的版本,纯静态实现,本地只需要部署一个web服务器即可。不过按理来说应该是可以直接打开本地文件而不需要服务器的,但是不知道为什么firefox打开就是报错,显示被阻止,所以也只好设置一个服务器了。
不过,后面我试了一下,使用KDE桌面的HTML Wallpaper插件,直接指定本地文件就像,不会有报错,也可以正常显示,估计只是firefox的限制(
所以,要是这样就非常好了,本地设置成壁纸web服务器都省了。

部署方法一:PHP环境部署

首先,确保你有一台服务器,部署上web服务器和php环境,我这里选择nginx和php,采用的操作系统为Alpine Linux 3.20。

apk add php php-fpm openssl nginx
rc-update add php-fpm83 default
rc-update add nginx default
service php-fpm82 start
service nginx start

这样一通操作下来,我们的基本环境就有了。接下来就是配置一下默认页面的规则,当然这是可选项,你可以直接一股脑用默认直接http部署,但是我并不推荐,我认为还是设置个域名配合SSL证书比较好。

设置默认匹配页面

我们先来生成一个默认的SSL自签名证书用于没有匹配到域名时错误提示页面使用。

mkdir -p /etc/nginx/ssl/
openssl genpkey -algorithm RSA -out /etc/nginx/ssl/selfsigned.key -pkeyopt rsa_keygen_bits:2048
openssl req -new -x509 -key /etc/nginx/ssl/selfsigned.key -out /etc/nginx/ssl/selfsigned.crt -days 365 -subj "/"

这样子就生成了自签名证书,证书和密钥位置分别在/etc/nginx/ssl/selfsigned.crt/etc/nginx/ssl/selfsigned.key
然后,删除/etc/nginx/http.d/default.conf,再重新创建:

rm /etc/nginx/http.d/default.conf
nano /etc/nginx/http.d/default.conf

内容替换为如下内容:

server {
    listen 80  default_server;
    #listen [::]:443 ssl default_server;

    server_name _;  # 这是一个通配符,表示任何未匹配的主机名

    #return 444;  # 关闭连接,不发送任何响应

    root /var/www/; # 静态文件的位置
    index index.html; # 默认主页

    location / {
        try_files $uri $uri/ =404; # 尝试提供请求的文件或目录,如果不存在则返回404
    }

    # 处理错误页面
    error_page 404 /404.html;
    location = /404.html {
        internal;
    }
}

server {
    listen 443 ssl default_server;
    #listen [::]:443 ssl default_server;

    server_name _;  # 这是一个通配符,表示任何未匹配的主机名

    ssl_certificate /etc/nginx/ssl/selfsigned.crt;
    ssl_certificate_key /etc/nginx/ssl/selfsigned.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384';

    root /var/www/; # 静态文件的位置
    index index.html; # 默认主页

    location / {
        try_files $uri $uri/ =404; # 尝试提供请求的文件或目录,如果不存在则返回404
    }

    # 处理错误页面
    error_page 404 /404.html;
    location = /404.html {
        internal;
    }
}

server {
    listen 80;
    server_name *.nekopara.uk;

    # 302 Redirect all traffic to the corresponding HTTPS URL
    location / {
        return 302 https://$host$request_uri;
    }
}

记得在/var/www/创建一个错误提示页面index.html:

nano /var/www/index.html

内容我(宝塔 x)已经帮你想好了:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>没有找到站点</title>
<style>
*{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
.content{background-color:#f3f7f9; height:300px;border:1px dashed #c6d9b6;padding:20px}
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
.t2{margin-bottom:8px; font-weight:bold}
ol{margin:0 0 20px 22px;padding:0;}
ol li{line-height:30px}
</style>
</head>

<body>
        <div class="main">
                <div class="title">没有找到站点</div>
                <div class="content">
                        <p class="t1">您的请求在Web服务器中没有找到对应的站点!</p>
                        <p class="t2">可能原因:</p>
                        <ol>
                                <li>您没有将此域名或IP绑定到对应站点!</li>
                                <li>配置文件未生效!</li>
                        </ol>
                        <p class="t2">如何解决:</p>
                        <ol>
                                <li>检查是否已经绑定到对应站点,若确认已绑定,请尝试重载Web服务;</li>
                                <li>检查端口是否正确;</li>
                                <li>若您使用了CDN产品,请尝试清除CDN缓存;</li>
                                <li>普通网站访客,请联系网站管理员;</li>
                        </ol>
                </div>
        </div>
</body>

默认页面设置好了,接下来就是设置对应的站点了。

部署NekoWebShow

我个人使用习惯是在根目录创建/data目录用于存放各种东西,先让我们克隆项目:

mkdir /data
cd /data/
git clone --depth 1 https://github.com/Chocola-X/NekoWebShow

然后就是申请证书并且解析域名到你的服务器,这里不再赘述,有acme.sh可以用,当然你也可以用我的网页在线生成证书:猫娘☆免费SSL证书申请
申请完成的证书,放到/data/certs/目录下。包括证书和私钥,例如_nekopara_uk.pem_nekopara_uk.key
然后是配置nginx服务器:

nano /etc/nginx/http.d/nekowebshow.conf

配置文件内容如下:

server {
    listen 443 ssl;
    server_name chocola.nekopara.uk vanilla.nekopara.uk azuki.nekopara.uk coconut.nekopara.uk fraise.nekopara.uk maple.nekopara.uk milk.nekopara.uk cinnamon.nekopara.uk show.nekopara.uk;

    # SSL certificate and key paths
    ssl_certificate /data/certs/_nekopara_uk.pem;
    ssl_certificate_key /data/certs/_nekopara_uk.key;

    # SSL settings (optional but recommended for security)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Root directory of the website
    root /data/nekowebshow;
    index index.html index.php;

    # Logging
    #access_log /var/log/nginx/nekopara.uk.access.log;
    #error_log /var/log/nginx/nekopara.uk.error.log;

    # Serve static files directly
    location / {
        try_files $uri $uri/ /index.html /index.php?$args;
    }

    # PHP processing
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Deny access to hidden files
    location ~ /\.ht {
        deny all;
    }
}

注意将域名替换为你实际的域名,以及你实际的证书路径,证书建议使用通配符证书。
因为我的域名nekopara.uk很符合主题,所以我给每一个角色都添加了子域名,例如chocola.nekopara.uk就很有趣了。对于其他域名,请根据需要自行选择。
这时候,打开对应的域名,应该是可以正常工作了,但是你会发现打开新的角色图鉴,就会跳转到我的网站。不要急不要哭,打开index.php让我们来改几个参数即可,这就是为什么我选择php构建的原因。
打开index.php找到开头这里:

$domain_chocola = 'https://chocola.nekopara.uk';
$domain_vanilla = 'https://vanilla.nekopara.uk';
$domain_azuki = 'https://azuki.nekopara.uk';
$domain_coconut = 'https://coconut.nekopara.uk';
$domain_maple = 'https://maple.nekopara.uk';
$domain_cinnamon = 'https://cinnamon.nekopara.uk';
$domain_milk = 'https://milk.nekopara.uk';
$domain_fraise = 'https://fraise.nekopara.uk';
$background_url = './img/bg.png';

替换为对应的域名即可,例如第一条替换为:$domain_chocola = 'https://chocola.example.com';
然后背景也是可以修改的,替换掉bg.png或者改为别的背景图URL即可,但是我个人还是认为游戏原本的背景比较搭配。。。
修改完成后,也就部署好了。
你可以之作为一个普通的角色图鉴使用,当然,我认为更好的做法是把这个做成动态壁纸,使用 KDE 的 HTML Wallpaper 设置对应的URL即可。因为本来我开发这个的初衷,就是想要一个好看的动态壁纸。
部署好后Be Like:
x_20250803_130606.png

部署方法二:静态HTML部署

相比于方法一,这个就不需要设置php环境了,能够减小系统性能开销。缺点就是,如果你想修改一些网页参数,会比较麻烦。更合适的做法是用在本地桌面背景,而不是展示了。

web服务器部署

当然,你愿意折腾的话,也不是不行,参照方法一配置nginx环境和证书即可,php就不需要安装了,配置方法这里就不再赘述,就是配置文件nekowebshow.conf要稍微改变一下:

server {
    listen 443 ssl;
    server_name chocola.nekopara.uk vanilla.nekopara.uk azuki.nekopara.uk coconut.nekopara.uk fraise.nekopara.uk maple.nekopara.uk milk.nekopara.uk cinnamon.nekopara.uk show.nekopara.uk;

    # SSL certificate and key paths
    ssl_certificate /data/certs/_nekopara_uk.pem;
    ssl_certificate_key /data/certs/_nekopara_uk.key;

    # SSL settings (optional but recommended for security)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Root directory of the website
    root /data/nekowebshow;
    index index.html index.php;

    # Logging
    #access_log /var/log/nginx/nekopara.uk.access.log;
    #error_log /var/log/nginx/nekopara.uk.error.log;


    location / {
        try_files $uri $uri/ =404; # 尝试提供请求的文件或目录,如果不存在则返回404
    }

    # 处理错误页面
    error_page 404 /404.html;
    location = /404.html {
        internal;
    }

}

要注意,克隆的时候,请克隆html_version分支:

git clone --depth 1 --branch html_version https://github.com/Chocola-X/NekoWebShow

当然,纯html的版本我已经在Github Pages部署了一份了,如果只是想要设置个动态壁纸不想部署的话,直接设置这个URL就好了。但是缺点是断网就寄。
直接用Github Pages链接部署成桌面背景Be Like:
x_20250803_130938.png

本地文件部署

如果你设置动态壁纸的软件支持直接读取本地文件且不报错的话,推荐采用这种方式。当然,本地打开html文件,firefox已经拦截跨文件夹请求了(
找一个你适合存放这个壁纸的文件夹,壁纸体积大概2.9G,然后和上面一样克隆项目:

git clone --depth 1 --branch html_version https://github.com/Chocola-X/NekoWebShow

然后在HTML Wallpaper设置壁纸路径即可享用。
x_20250803_131110.png
虽然但是有点吃性能就是了(