玩客云部署EasyVoice实战:HiNas、Docker、ARMv7、9001与固定地址访问(1)

玩客云部署EasyVoice实战:HiNas、Docker、ARMv7、9001与固定地址访问

前言

手里有大量小说、长文或视频旁白素材时,真正麻烦的往往不是"有没有TTS",而是在线工具的字数、时长和操作方式不适合长期使用。尤其是几十万字甚至更长的文本,如果每次都要拆段、上传、等待,再手动合并,做一本有声书会非常折腾。

这次我没有准备高配PC,而是直接用刷入HiNas的玩客云来跑EasyVoice。先通过HiNas自带脚本安装Docker和Portainer,再使用已经适配ARMv7的EasyVoice镜像,把9000映射到9001,并保留音频目录。

服务跑通以后,再实际测试文本转语音、超长文本流式生成、多角色配音,以及需要OpenAI兼容接口的AI角色解析。

最后再给9001增加外部访问入口,从随机公网地址切换到固定二级子域名。整篇重点不是把几十块的小盒子写成"本地大模型TTS服务器",而是把玩客云 → Docker → EasyVoice → TTS/多角色 → AI解析 → 远程访问这条链真正跑通。

这类方案真正有意思的地方,也不只是"低成本",而是把一台原本闲置的小盒子变成长期在线的语音入口。以后不管是小说、旁白还是多角色文本,都可以从同一个Web页面提交任务,而不必每次重新找在线网站。

更省事。

1 这套方案真正解决什么问题

EasyVoice更适合被理解成:

一套自托管的文本转语音Web界面和任务入口。

它适合这些场景:

  • 小说转有声书;
  • 长文转语音;
  • 视频旁白;
  • 多角色对白;
  • 需要字幕和音频同时生成;
  • 想把TTS入口部署到自己的NAS或小主机上。

本次使用的是基于上游项目二次开发的分支。

页面:

这套分支在现有功能基础上还加入了:

  • 多角色自定义配音UI;
  • 用户登录;
  • 三栏Web布局;
  • AMD64 / ARM64 / ARMv7适配。

2 为什么玩客云能跑这一版EasyVoice

玩客云这里最关键的不是算力,而是:

ARMv7架构适配。

上游项目在ARMv7上会碰到@node-rs/jieba原生模块缺少预编译二进制的问题。

本次分支做的处理是:

Jieba加载失败时,自动降级到简单分词器。

两者区别可以这样理解:

分词方式 特点
Jieba 基于词典和HMM,分词更细
简单分词器 主要按标点切分,兼容性更好

对这次TTS主流程来说,ARMv7降级以后仍然可以继续生成语音。

但长句的断句位置可能和Jieba版本略有差别。

这一点后面会从容器日志里直接看到。

3 先确认HiNas环境

这台玩客云已经刷入HiNas,并且能进入终端后台。

页面:

如果还没有HiNas环境,需要先把系统和终端登录准备好,再继续后面的Docker部署。

4 通过HiNas安装Docker和Portainer

先点击HiNas首页里的:

Docker面板

页面:

系统会提示安装Docker管理面板。

继续进入终端:

登录终端:

本次使用HiNas提供的安装脚本:

shell 复制代码
install-portainer.sh

执行过程:

安装完成:

这条脚本会把Docker和Portainer一起准备好。

5 初始化Portainer

回到HiNas首页刷新,再进入Docker面板。

页面:

第一次进入Portainer时,需要创建管理员账号。

密码至少12位。

完成以后进入仪表盘:

做到这里,Docker环境和图形化管理入口都已经具备。

6 ARMv7镜像和普通镜像要分开选

本次分支专门提供了ARMv7镜像。

相关说明页面:

玩客云使用的是ARMv7,所以执行:

shell 复制代码
docker run -d -p 9001:9000 --name easyvoice -v ./audio:/app/audio tannic666/easyvoice:v1.1-armv7

这里几个参数很关键:

  • 容器名:easyvoice
  • 外部端口:9001
  • 容器端口:9000
  • 音频目录:./audio:/app/audio
  • 镜像:tannic666/easyvoice:v1.1-armv7

如果是AMD64或ARM64,则使用:

shell 复制代码
docker run -d -p 9001:9000 --name easyvoice -v ./audio:/app/audio tannic666/easyvoice:v1.1

也就是说:

架构不同,镜像不要混用。

7 检查EasyVoice容器状态

部署结果:

继续执行:

shell 复制代码
docker ps

结果:

Portainer里也能看到对应容器:

这一步只能确认:

容器已经运行。

还需要继续看日志和Web页面。

8 从日志确认ARMv7降级逻辑

执行:

shell 复制代码
docker logs easyvoice | head -n 10

结果:

可以看到ARMv7环境里Jieba加载失败以后,服务自动切换到简单分词器。

这正是这个分支能继续在玩客云上运行的关键兼容处理之一。

9 9000和9001不要搞混

EasyVoice容器内部运行端口是:

9000

Docker映射到玩客云以后,外部访问端口是:

9001

所以浏览器访问:

shell 复制代码
http://192.168.50.179:9001

页面:

能够进入初始化页以后,可以确认:

浏览器 → 玩客云9001 → 容器9000 → EasyVoice

已经跑通。

10 创建管理员账号并登录

初始化页面完成账号设置以后:

进入EasyVoice主页。

到这里,本地Web服务才算真正可用。

11 先测试最基础的文本转语音

本次页面里提供了多种中文音色。

可以根据:

  • 旁白;
  • 男声;
  • 女声;
  • 年轻角色;
  • 地方特色;

来选择。

这次测试文本保持如下:

shell 复制代码
灾难爆发前,我像大多数学者一样,想用自己的学识造福人类。碳基生命是脆弱而短暂的,我想提升人类的寿命。如果有足够的时间积累世间所有的知识,如果可以用时间去弥补天赋的不足,那么每个人都有可能掌握所有的自然、生命、社会、人文等科学知识,让人们更全面地感受这个世界。设想一下,知识的边界一旦被打破,人们对意识、身体乃至整个世界的认知都将发生巨大的改变,人类将以无尽的生命探索整个宇宙化。

操作页面:

生成完成以后试听:
你的浏览器不支持 audio 标签。

这一层验证的是:

输入文本 → EasyVoice → 音频生成 → 浏览器播放

12 长文本更值得看"流式输出"

短文本能生成还不够。

本次继续用接近700万字的长篇文本进行测试:

运行过程:

页面显示在持续生成音频。

本次截图状态里,播放不到3分钟时,已经流式生成出约34分钟的音频时长。

这里更准确的理解是:

长文本任务不需要等整个文件全部生成完成以后才开始播放。

但整本长篇最终生成完成需要多久,仍然取决于文本长度、网络和上游语音服务状态。

13 "自建TTS"不等于语音模型完全离线运行

这套EasyVoice基于:

Edge TTS。

所以这里自己部署的是:

  • Web页面;
  • 任务入口;
  • 用户系统;
  • 音频管理;
  • 多角色逻辑。

并不是在玩客云本机上运行一个大型语音模型。

这个区别很重要。

玩客云能够承担这套服务,核心原因之一正是它不需要本机进行重型神经网络推理。

14 接下来测试多角色配音

进入多角色页面,先加载示例:

每个段落可以分别调整:

  • 音色;
  • 语速;
  • 音量;
  • 音调。

页面:

生成完成:

试听:
你的浏览器不支持 audio 标签。

这样一段文本里,不同角色就可以使用不同声音。

15 多角色真正有价值的是"段落可单独调整"

如果只是整篇文章用一个声音,普通TTS已经足够。

多角色模式更适合:

  • 小说对白;
  • 短剧;
  • 广播剧;
  • 剧本;
  • 多人对话。

因为每一个角色都可以单独分配声音。

这样后面发现某个角色不合适时,不必把整篇配置全部推翻。

16 AI解析角色属于另一条模型链

EasyVoice还提供:

AI解析多角色。

配置页面:

这部分不是Edge TTS自己完成的。

需要先填写:

  • API地址;
  • API Key。

并使用兼容OpenAI v1格式的接口。

所以这一层链路是:

文本 → AI模型解析角色 → EasyVoice生成段落 → TTS生成语音

如果没有配置AI接口,普通文本转语音和手动多角色仍然是另一套能力。

17 用三角色加旁白测试AI解析

测试内容:

tex 复制代码
清晨的山谷被薄雾覆盖,阳光像金色碎片洒在林间小路上。远处传来清脆的鸟鸣声。 
沈澜提着工具箱走在最前方,脚步轻快。 
沈澜:"今天一定能找到昨晚看到的光源位置。" 
顾行远抬头望着树梢,手里握着便携探测仪。 
顾行远:"如果真是反射物,那数据应该会有变化。" 
就在他们讨论时,林青岚从溪边快步走来,指尖夹着一片透明碎片。 
林青岚:"我在水边发现这个,边缘有烧蚀痕迹。" 
顾行远立刻接过碎片,探测仪发出轻微的提示音。
沈澜凑近观察,神色变得专注。 
沈澜:"痕迹并不像自然形成的。" 
三人沉默片刻,周围只有风声掠过草叶。 
雾逐渐散开,碎片在光下闪出微弱的蓝色光纹,像是隐藏着尚未被揭开的秘密。

填入以后点击开始解析:

解析完成:

本次自动生成了11个段落。

页面里已经把:

  • 旁白;
  • 沈澜;
  • 顾行远;
  • 林青岚;

分别拆开。

18 解析完成以后继续生成语音

点击生成:

试听:
你的浏览器不支持 audio 标签。

这一步真正证明的是:

AI角色解析 → 段落生成 → 多角色TTS

整条链已经跑通。

19 如果旁白被误判,可以给解析模型增加规则

本次还保留了一个提示词示例:

tex 复制代码
解析规则:除非文本中明确出现角色说话的引号或冒号,否则所有内容都视为旁白,不视为角色语音。 

这类规则的作用是:

约束AI模型怎么识别旁白和角色。

如果文本格式比较复杂,AI解析结果仍然需要人工检查。

不能把自动解析理解成每一篇小说都一定不会分错角色。

20 到这里,本地EasyVoice已经完整跑通

现在已经完成:

玩客云

↓

HiNas

↓

Docker / Portainer

↓

EasyVoice ARMv7

↓

9001 Web

↓

普通TTS

↓

长文本流式生成

↓

多角色配音

↓

AI角色解析

如果只在局域网里使用,到这里已经足够。

后面解决的是:

人在外面怎么继续进入EasyVoice。

21 公网访问之前先看账号和API Key

EasyVoice这套分支已经加入用户登录。

但如果又配置了AI解析,还可能涉及:

  • API Key;
  • 外部AI接口;
  • 生成音频;
  • 小说文本;
  • 多角色配置。

所以远程访问时,至少要同时关注:

  • 管理员密码;
  • 用户账号;
  • API Key是否暴露;
  • 固定公网地址传播范围;
  • audio目录备份。

cpolar负责网络入口。

EasyVoice自己的用户和凭据仍然要自己管理。

22 安装cpolar

介绍图:

在玩客云终端执行:

shell 复制代码
sudo curl https://get.cpolar.sh | sh

安装结果:

然后检查服务:

shell 复制代码
sudo systemctl status cpolar

结果:

状态正常以后再进入Web管理页面。

23 打开cpolar Web UI

访问:

shell 复制代码
# 请使用你的访问IP + 9200端口
http://192.168.50.179:9200/

页面:

登录以后进入后台:

24 给EasyVoice的9001创建公网入口

默认隧道页面:

编辑website隧道。

本次改成:

  • 名称:easyvoice-9001
  • 协议:HTTP
  • 本地地址:9001
  • 地区:China Top

页面:

这里真正映射的是:

玩客云对外提供EasyVoice的9001端口。

25 先用随机公网地址验证

进入在线隧道列表:

使用生成的HTTPS地址访问:

能够打开EasyVoice登录页以后,可以确认:

外部浏览器 → 公网地址 → 玩客云9001 → EasyVoice

已经跑通。

26 随机地址更适合先做网络验证

本次材料里随机域名按约24小时变化来描述。

这种方式更适合:

  • 临时测试;
  • 偶尔使用;
  • 先确认网络链路。

如果准备长期收藏,再继续配置固定二级子域名。

27 保留固定二级子域名

进入:

shell 复制代码
https://dashboard.cpolar.com/reserved

预留页面:

本次示例:

  • 地区:China Top
  • 二级域名:easyvoice01

实际名称以自己账号最终成功保留的结果为准。

28 编辑EasyVoice隧道

回到隧道列表:

把域名类型改成:

二级子域名

并填写前面保留的名称:

29 查看固定地址

在线隧道列表:

原来的随机地址已经切换成固定二级子域名形式。

30 最后从外部设备访问

使用固定HTTPS地址:

能够正常进入以后,长期远程入口完成。

整条链现在变成:

外部浏览器 → 固定公网地址 → 玩客云9001 → EasyVoice

31 固定地址解决的是"入口稳定"

固定二级子域名主要解决:

  • 手机长期收藏;
  • 电脑不用反复查新地址;
  • 外出时使用同一个入口;
  • 多设备访问更方便。

它解决的是:

访问入口不频繁变化。

并不代表:

  • EasyVoice变成完全离线TTS;
  • Edge TTS永远可用;
  • AI解析API不再需要网络;
  • API Key自动安全;
  • 任何超长文本都能瞬间生成完毕。

32 这台玩客云真正承担的是什么

这篇最容易被误解的地方,是把玩客云想成:

"在本机跑大型TTS模型。"

实际上它承担的是:

  • Docker;
  • EasyVoice Web服务;
  • 用户管理;
  • 音频目录;
  • 文本任务;
  • 多角色配置;
  • AI解析流程组织;
  • 对外访问入口。

这也是为什么几十块的ARMv7设备仍然能把这套服务跑起来。

33 这套方案更适合什么人

比较适合:

  • 手里已经有玩客云;
  • 已经刷入HiNas;
  • 想做长文本转语音;
  • 想用浏览器操作TTS;
  • 需要多角色配音;
  • 希望多设备访问;
  • 能接受Edge TTS和外部AI接口的网络依赖。

如果追求:

  • 完全离线;
  • 本地神经网络语音模型;
  • 高度自定义声音克隆;
  • 本机GPU推理;

那就属于另一类TTS方案。

34 最后把完整技术链重新看一遍

硬件:

玩客云 ARMv7

系统:

HiNas

容器:

Docker + Portainer

ARMv7镜像:

tannic666/easyvoice:v1.1-armv7

普通架构镜像:

tannic666/easyvoice:v1.1

端口:

9001:9000

数据:

./audio:/app/audio

本地功能:

文本TTS → 流式输出 → 多角色配音 → AI角色解析

随机远程:

公网随机地址 → 9001

固定远程:

固定二级子域名 → 9001

实际完成:

  • HiNas终端;
  • Docker / Portainer安装;
  • Portainer初始化;
  • ARMv7 EasyVoice镜像;
  • 9001端口;
  • 容器状态;
  • 日志验证;
  • 简单分词器降级;
  • 管理员初始化;
  • 文本转语音;
  • 长篇流式生成;
  • 多角色配音;
  • AI角色解析;
  • OpenAI兼容接口;
  • cpolar安装;
  • 随机公网访问;
  • 固定二级子域名;
  • 外部设备访问。

这样玩客云才真正从一台低功耗小盒子,变成一套可以长期提供EasyVoice Web入口、管理TTS任务并支持远程使用的轻量语音服务主机。

总结

这次真正跑通的是一条完整的玩客云 + EasyVoice链路:先在HiNas里通过脚本安装Docker和Portainer,再使用专门适配ARMv7的EasyVoice镜像,把容器9000映射到玩客云9001,并把音频目录挂载出来。

本地验证没有停在"容器显示Up"。后面继续检查日志,确认ARMv7环境下Jieba加载失败后已经自动降级到简单分词器,再实际完成普通文本转语音、长文本流式生成、多角色配音和AI角色解析。

需要特别区分的是,这是一套自托管的TTS入口和任务系统,并不等于在玩客云本机运行大型语音模型。EasyVoice基于Edge TTS,AI角色解析还需要额外的OpenAI兼容接口,所以"服务部署在本地"和"所有语音、AI能力完全离线"不是一回事。

远程部分是在局域网使用正常以后再增加的能力。随机公网地址先验证9001链路,固定二级子域名再解决长期入口变化的问题;如果里面配置了用户账号和AI API Key,长期公网访问时仍然要把账号、凭据和地址传播范围一起管理。

相关推荐
北风toto1 小时前
Linux 服务器通过 tgz 离线部署 Docker
linux·服务器·docker
fengkai45451 小时前
2、Kubernetes 介绍+安装+卸载
运维·容器·kubernetes
羑悻的小杀马特1 小时前
超越Bridge:全面掌握Docker网络隔离与通信的底层逻辑!
运维·网络·docker·容器
A-刘晨阳2 小时前
Windows硬盘里的媒体太乱?我用WSL+Plex把本地文件整理成一个统一媒体中心
运维·cpolar
Thomas.Sir2 小时前
第34课:微服务Docker容器化部署 & 生产环境上线
spring cloud·docker·微服务
小马同学-2 小时前
K8s 节点管理:查看、维护与集群删除操作
容器·kubernetes
对象存储与RustFS20 小时前
网盘限速逼你开会员?用 RustFS 自己搭一个不限速的“私人网盘
服务器·后端·docker
程序员老赵1 天前
Docker 部署 Filestash:轻松搭建浏览器文件管理平台
前端·docker·开源