www.4bai.cn 网页朗读机器人:服务器条件与完整方案
一、核心结论(一眼看懂)
- 方案 A(本地服务 + 浏览器插件):服务器需满足Ubuntu 22.04+、4 核 8GB+、50GB SSD,适合追求豆包级情感音质的离线体验
- 方案 B(纯前端浏览器 TTS):无服务器特殊要求,只需能托管静态 JS/CSS,适合快速部署、跨设备兼容
- 推荐组合:先用方案 B 快速上线,同时准备方案 A 的服务器,最终实现本地服务 + 前端集成的最佳体验
二、方案 A:服务器部署 ChatTTS(离线、豆包级情感音质)
1. 服务器硬件最低要求
| 配置项 | 最低要求 | 推荐配置 | 说明 |
|---|---|---|---|
| CPU | 4 核 Intel/AMD(支持 AVX2) | 8 核 E5-2699 V4(你已有) | 语音合成是 CPU 密集型任务,核数越多合成越快 |
| 内存 | 8GB | 16GB+ | 模型加载 + 推理需要,避免 OOM 崩溃 |
| 存储 | 50GB SSD | 100GB SSD | 系统 + 模型 + 缓存,SSD 保证加载速度 |
| GPU | 可选(无 GPU 用 CPU) | NVIDIA RTX 3060 6GB+ | 有 GPU 可提速 3-10 倍,情感合成更流畅 |
| 带宽 | 1Mbps | 5Mbps+ | 多用户同时请求时保证响应速度 |
2. 服务器软件必须条件
- 操作系统:Ubuntu 22.04 LTS(推荐)/ Debian 11+,不建议 CentOS(Python 生态适配性差)
- Python 环境:Python 3.10+(必须),配套 pip、venv 工具
- 依赖软件:git、ffmpeg、libssl-dev、libasound2-dev(音频处理与网络通信)
- 端口开放:7860 端口(ChatTTS 服务)、80/443 端口(网站访问),需在防火墙 / 安全组放行
3. 完整部署命令(不踩坑版)
sudo apt update && sudo apt upgrade -y
sudo apt install -y python3.10-venv git ffmpeg libssl-dev libasound2-dev
# 2. 创建虚拟环境(隔离系统Python)
python3 -m venv ~/chattts-env
source ~/chattts-env/bin/activate
# 3. 安装核心组件(指定gradio版本避免兼容问题)
pip install --upgrade pip wheel setuptools
pip install chattts gradio==4.28.0
# 4. 创建启动脚本(含情感参数)
cat > ~/chattts-start.sh << 'EOF'
#!/bin/bash
source ~/chattts-env/bin/activate
python - <<END
import ChatTTS
import gradio as gr
import torch
# 初始化ChatTTS(CPU模式,无GPU也能运行)
chat = ChatTTS.Chat()
chat.load(compile=False, device="cpu")
# 情感参数(接近豆包的温柔朗读腔)
speed = 1.05 # 语速:1.0=正常,1.1更快,0.9更慢
oral = 2 # 口语化:2=文章朗读(推荐),1=聊天模式
break_duration = 0.8 # 句间停顿,越大越舒缓
temperature = 0.35 # 音色稳定度,越小越稳
top_p = 0.7 # 采样多样性
# 固定音色(避免每次不同)
rand_spk = torch.load(ChatTTS.get_random_speaker(), map_location="cpu")
def speak(text):
params = {
"speed": speed,
"oral": oral,
"laugh": 0,
"break_duration": break_duration,
"temperature": temperature,
"top_p": top_p
}
wavs = chat.infer([text], params=params, speaker=rand_spk)
return (24000, wavs[0].cpu().numpy())
# 启动服务(公网可访问)
demo = gr.Interface(fn=speak, inputs="text", outputs="audio")
demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
END
EOF
# 5. 赋予执行权限并启动
chmod +x ~/chattts-start.sh
nohup ~/chattts-start.sh > ~/chattts.log 2>&1 &
# 6. 验证服务是否正常
ss -tulpn | grep 7860
# 1. 系统更新与依赖安装 sudo apt update && sudo apt upgrade -y sudo apt install -y python3.10-venv git ffmpeg libssl-dev libasound2-dev # 2. 创建虚拟环境(隔离系统Python) python3 -m venv ~/chattts-env source ~/chattts-env/bin/activate # 3. 安装核心组件(指定gradio版本避免兼容问题) pip install --upgrade pip wheel setuptools pip install chattts gradio==4.28.0 # 4. 创建启动脚本(含情感参数) cat > ~/chattts-start.sh << 'EOF' #!/bin/bash source ~/chattts-env/bin/activate python - <# 5. 赋予执行权限并启动 chmod +x ~/chattts-start.sh nohup ~/chattts-start.sh > ~/chattts.log 2>&1 & # 6. 验证服务是否正常 ss -tulpn | grep 7860
4. 网站集成步骤(手机 / 电脑都能用)
- 安装浏览器插件:Firefox/Chrome 安装Kokoro TTS扩展
-
配置插件:
- API 地址:http://你的服务器IP:7860/api/predict
- 格式:WAV
- 语速:1.05(与服务器一致)
- 开启:朗读选中内容、后台播放
- 测试:打开www.4bai.cn,选中文章段落,点击插件朗读按钮
三、方案 B:纯前端浏览器 TTS(零服务器压力,快速上线)
==【】=====================
1. 服务器条件(几乎无要求)
- 能正常托管静态网站(HTML/CSS/JS),你的西部数码虚拟主机完全满足
- 支持 HTTPS(浏览器本地 TTS 需要安全上下文),可通过 Let's Encrypt 免费申请 SSL 证书
- 无需额外 CPU / 内存 / 存储,所有 TTS 运算都在用户浏览器中完成
2. 网站集成代码(复制粘贴即用)
预览
==【<!-- 全局朗读按钮样式 -->
<style>
#read-aloud-btn {
position: fixed;
bottom: 30px;
right: 30px;
width: 60px;
height: 60px;
border-radius: 50%;
background: #2563eb;
color: white;
border: none;
font-size: 20px;
cursor: pointer;
z-index: 9999;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
#read-aloud-btn:hover {
background: #1d4ed8;
}
#read-aloud-status {
position: fixed;
bottom: 100px;
right: 30px;
background: rgba(0,0,0,0.7);
color: white;
padding: 8px 16px;
border-radius: 4px;
z-index: 9999;
display: none;
}
</style>
<!-- 朗读按钮HTML -->
<button id="read-aloud-btn"></button>
<div id="read-aloud-status">朗读中...</div>
<!-- 引入Kokoro TTS核心库(82MB,首次加载后缓存) -->
<script src="https://cdn.jsdelivr.net/npm/kokoro-js@latest/dist/kokoro.min.js"></script>
<!-- 朗读逻辑脚本 -->
<script>
document.addEventListener('DOMContentLoaded', async () => {
const btn = document.getElementById('read-aloud-btn');
const status = document.getElementById('read-aloud-status');
let tts, isPlaying = false, currentAudio = null;
// 初始化TTS引擎(中文支持)
try {
tts = await kokoro.load({
voice: "zh_cn", // 中文语音
dtype: "fp32", // 音质优先
device: "cpu" // 兼容所有设备
});
console.log("朗读引擎初始化成功");
} catch (e) {
console.error("初始化失败:", e);
btn.disabled = true;
btn.textContent = "❌";
return;
}
// 朗读函数
const readText = async (text) => {
if (!text) return;
isPlaying = true;
btn.textContent = "⏹";
status.style.display = "block";
try {
// 分段朗读(避免长文本卡顿)
const chunks = text.match(/.{1,200}[。!?;,]|.+$/g) || [text];
for (const chunk of chunks) {
if (!isPlaying) break;
const audioBlob = await tts.generate(chunk.trim(), { speed: 1.05 });
currentAudio = new Audio(URL.createObjectURL(audioBlob));
await new Promise(resolve => {
currentAudio.onended = resolve;
currentAudio.play();
});
}
} catch (e) {
console.error("朗读失败:", e);
} finally {
stopReading();
}
};
// 停止朗读
const stopReading = () => {
isPlaying = false;
if (currentAudio) {
currentAudio.pause();
currentAudio = null;
}
btn.textContent = "";
status.style.display = "none";
};
// 按钮点击事件
btn.addEventListener('click', () => {
if (isPlaying) {
stopReading();
} else {
// 获取当前页面主要内容(根据你的网站结构调整选择器)
const content = document.querySelector('article, .post-content, .entry-content')?.textContent ||
document.body.textContent;
readText(content);
}
});
});
</script>
<style> #read-aloud-btn { position: fixed; bottom: 30px; right: 30px; width: 60px; height: 60px; border-radius: 50%; background: #2563eb; color: white; border: none; font-size: 20px; cursor: pointer; z-index: 9999; box-shadow: 0 4px 8px rgba(0,0,0,0.2); } #read-aloud-btn:hover { background: #1d4ed8; } #read-aloud-status { position: fixed; bottom: 100px; right: 30px; background: rgba(0,0,0,0.7); color: white; padding: 8px 16px; border-radius: 4px; z-index: 9999; display: none; } <button id="read-aloud-btn"> <script src="https://cdn.jsdelivr.net/npm/kokoro-js@latest/dist/kokoro.min.js"> <script> document.addEventListener('DOMContentLoaded', async () => { const btn = document.getElementById('read-aloud-btn'); const status = document.getElementById('read-aloud-status'); let tts, isPlaying = false, currentAudio = null; // 初始化TTS引擎(中文支持) try { tts = await kokoro.load({ voice: "zh_cn", // 中文语音 dtype: "fp32", // 音质优先 device: "cpu" // 兼容所有设备 }); console.log("朗读引擎初始化成功"); } catch (e) { console.error("初始化失败:", e); btn.disabled = true; btn.textContent = "❌"; return; } // 朗读函数 const readText = async (text) => { if (!text) return; isPlaying = true; btn.textContent = "⏹"; status.style.display = "block"; try { // 分段朗读(避免长文本卡顿) const chunks = text.match(/.{1,200}[。!?;,]|.+$/g) || [text]; for (const chunk of chunks) { if (!isPlaying) break; const audioBlob = await tts.generate(chunk.trim(), { speed: 1.05 }); currentAudio = new Audio(URL.createObjectURL(audioBlob)); await new Promise(resolve => { currentAudio.onended = resolve; currentAudio.play(); }); } } catch (e) { console.error("朗读失败:", e); } finally { stopReading(); } }; // 停止朗读 const stopReading = () => { isPlaying = false; if (currentAudio) { currentAudio.pause(); currentAudio = null; } btn.textContent = ""; status.style.display = "none"; }; // 按钮点击事件 btn.addEventListener('click', () => { if (isPlaying) { stopReading(); } else { // 获取当前页面主要内容(根据你的网站结构调整选择器) const content = document.querySelector('article, .post-content, .entry-content')?.textContent || document.body.textContent; readText(content); } }); });