-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0f14402
Showing
19 changed files
with
790 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
name: Release Bob Plugin | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
paths: | ||
- 'bob-plugin/**' | ||
|
||
jobs: | ||
release: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 | ||
sparse-checkout: | | ||
.github | ||
bob-plugin | ||
release.py | ||
appcast.json | ||
sparse-checkout-cone-mode: false | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: '3.x' | ||
|
||
- name: Get latest tag | ||
id: get_latest_tag | ||
run: | | ||
git fetch --tags | ||
latest_tag=$(git tag | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1) | ||
if [ -z "$latest_tag" ]; then | ||
echo "version=v0.0.1" >> $GITHUB_OUTPUT | ||
else | ||
current_version=${latest_tag#v} | ||
IFS='.' read -r major minor patch <<< "$current_version" | ||
new_version="v$major.$minor.$((patch + 1))" | ||
echo "version=$new_version" >> $GITHUB_OUTPUT | ||
fi | ||
- name: Create Release Package | ||
run: | | ||
version="${{ steps.get_latest_tag.outputs.version }}" | ||
version_number=${version#v} | ||
python release.py $version_number | ||
- name: Create Release | ||
uses: softprops/action-gh-release@v1 | ||
with: | ||
tag_name: ${{ steps.get_latest_tag.outputs.version }} | ||
name: Release ${{ steps.get_latest_tag.outputs.version }} | ||
files: | | ||
voi-*.bobplugin | ||
appcast.json | ||
generate_release_notes: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.venv | ||
.DS_Store | ||
*.bobplugin | ||
*.onnx | ||
voices.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Bob Kokoro TTS Plugin | ||
|
||
一个基于 [Bob](https://bobtranslate.com/) 的文本转语音插件,使用 Kokoro 本地部署模型作为语音合成服务。 | ||
|
||
## 项目结构 | ||
|
||
本项目包含两个主要部分: | ||
|
||
1. **Bob 插件** (`bob-plugin/`): Bob 的文本转语音插件 | ||
2. **TTS 服务器** (`server/`): Kokoro TTS 本地服务器 | ||
|
||
## 快速开始 | ||
|
||
### 1. 部署 TTS 服务器 | ||
|
||
首先下载必需的模型文件: | ||
|
||
```bash | ||
cd server | ||
# 下载 ONNX 模型文件 | ||
wget https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files/kokoro-v0_19.onnx | ||
# 下载声音配置文件 | ||
wget https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files/voices.json | ||
``` | ||
|
||
然后选择以下任一方式部署服务器: | ||
|
||
```bash | ||
# 方式一:直接运行 | ||
pip install -r requirements.txt | ||
python server.py | ||
|
||
# 方式二:Docker(推荐) | ||
docker build -f Dockerfile.conda -t kokoro-tts-conda . | ||
docker run -p 8000:8000 kokoro-tts-conda | ||
``` | ||
|
||
详细说明请参考 [服务器文档](server/README.md) | ||
|
||
### 2. 安装 Bob 插件 | ||
|
||
1. 下载最新版本的插件([Releases](https://github.com/xnmeet/voi/releases/latest)) | ||
2. 安装 `.bobplugin` 文件到 Bob 中 | ||
3. 在 Bob 的偏好设置中配置服务器地址(例如:`http://localhost:8000/text-to-speech`) | ||
|
||
详细说明请参考 [插件文档](bob-plugin/README.md) | ||
|
||
## 问题反馈 | ||
|
||
如果您在使用过程中遇到任何问题,请通过以下方式反馈: | ||
|
||
1. 在 GitHub 上提交 Issue | ||
2. 发送邮件至 [email protected] | ||
|
||
## 许可证 | ||
|
||
[MIT License](LICENSE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"identifier": "com.meet.bob-plugin-voi", | ||
"versions": [ | ||
{ | ||
"version": "0.0.1", | ||
"desc": "auto", | ||
"sha256": "19b53f798e02d37adf685ed5470813f88bfa270dcfdb0855c0d6002deb7ecab9", | ||
"url": "https://raw.githubusercontent.com/xnmeet/voi/releases/download/v0.0.2/voi-0.0.2.bobplugin", | ||
"minBobVersion": "0.5.0" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# Bob Kokoro TTS Plugin | ||
|
||
Bob 的文本转语音插件,使用 Kokoro 本地部署模型作为语音合成服务。 | ||
|
||
## 功能特点 | ||
|
||
- 支持多种声音选项 | ||
- 可自定义服务器接口地址 | ||
- 支持 Base64 格式的音频输出 | ||
- 与 Bob 无缝集成 | ||
|
||
## 安装要求 | ||
|
||
- Bob 版本 ≥ 1.6.0 | ||
- 需要有运行中的 Kokoro TTS 服务器 | ||
|
||
## 插件配置 | ||
|
||
### 必需配置 | ||
|
||
- **服务器地址**: 设置 Kokoro TTS 服务器的完整地址(例如:`http://localhost:8000/synthesize`) | ||
|
||
### 可选配置 | ||
|
||
- **声音选择**: 可选择不同的声音模型 | ||
- af: 默认声音 | ||
- af_bella: Bella 声音 | ||
- af_nicole: Nicole 声音 | ||
- af_sarah: Sarah 声音 | ||
- af_sky: Sky 声音 | ||
- am_adam: Adam 声音 | ||
- am_michael: Michael 声音 | ||
- bf_emma: Emma 声音 | ||
- bf_isabella: Isabella 声音 | ||
- bm_george: George 声音 | ||
- bm_lewis: Lewis 声音 | ||
|
||
## 使用方法 | ||
|
||
1. 在 Bob 中选择文本 | ||
2. 选择 Kokoro TTS 作为语音合成服务 | ||
3. 点击播放按钮即可听到合成的语音 | ||
|
||
## 开发说明 | ||
|
||
本插件使用 GitHub Actions 进行自动化发布。当插件代码有更新时,会自动: | ||
|
||
1. 创建新的版本号 | ||
2. 生成插件包 | ||
3. 更新 `appcast.json` | ||
4. 发布新版本 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const supportedLanguages = [['en', 'en']]; | ||
|
||
exports.supportedLanguages = supportedLanguages; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"identifier": "com.meet.bob-plugin-voi", | ||
"version": "0.0.1", | ||
"category": "tts", | ||
"name": "Kokoro 语音", | ||
"summary": "使用 Kokoro 本地部署模型作为语音合成服务", | ||
"icon": "icon.png", | ||
"author": "xnmeet <[email protected]>", | ||
"homepage": "https://github.com/xnmeet/voi", | ||
"appcast": "https://raw.githubusercontent.com/xnmeet/voi/main/appcast.json", | ||
"minBobVersion": "1.6.0", | ||
"options": [ | ||
{ | ||
"identifier": "baseUrl", | ||
"type": "text", | ||
"title": "自定义接口完整地址" | ||
}, | ||
{ | ||
"identifier": "voice", | ||
"type": "menu", | ||
"title": "声色", | ||
"defaultValue": "af", | ||
"menuValues": [ | ||
{ "title": "af", "value": "af" }, | ||
{ "title": "af_bella", "value": "af_bella" }, | ||
{ "title": "af_nicole", "value": "af_nicole" }, | ||
{ "title": "af_sarah", "value": "af_sarah" }, | ||
{ "title": "af_sky", "value": "af_sky" }, | ||
{ "title": "am_adam", "value": "am_adam" }, | ||
{ "title": "am_michael", "value": "am_michael" }, | ||
{ "title": "bf_emma", "value": "bf_emma" }, | ||
{ "title": "bf_isabella", "value": "bf_isabella" }, | ||
{ "title": "bm_george", "value": "bm_george" }, | ||
{ "title": "bm_lewis", "value": "bm_lewis" } | ||
] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
var config = require('./config.js'); | ||
var utils = require('./utils.js'); | ||
|
||
function supportLanguages() { | ||
return config.supportedLanguages.map(([standardLang]) => standardLang); | ||
} | ||
|
||
function tts(query, completion) { | ||
const targetLanguage = utils.langMap.get(query.lang); | ||
if (!targetLanguage) { | ||
const err = new Error(`不支持 ${query.lang} 语种`); | ||
throw err; | ||
} | ||
const originText = query.text; | ||
|
||
try { | ||
$http.request({ | ||
method: 'POST', | ||
url: $option.baseUrl, | ||
header: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: { | ||
text: originText, | ||
voice: $option.voice, | ||
speed: 1, | ||
stream: false, | ||
format: 'base64' | ||
}, | ||
handler: function (resp) { | ||
var rawData = resp.data.audio_data; | ||
completion({ | ||
result: { | ||
type: 'base64', | ||
value: rawData, | ||
raw: rawData | ||
} | ||
}); | ||
} | ||
}); | ||
} catch (e) { | ||
$log.error(e); | ||
} | ||
} | ||
|
||
exports.supportLanguages = supportLanguages; | ||
exports.tts = tts; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
var config = require('./config.js'); | ||
|
||
const langMap = new Map(config.supportedLanguages); | ||
const langMapReverse = new Map(config.supportedLanguages.map(([standardLang, lang]) => [lang, standardLang])); | ||
|
||
exports.langMap = langMap; | ||
exports.langMapReverse = langMapReverse; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#!/usr/bin/env python3 | ||
import os | ||
import json | ||
import hashlib | ||
import shutil | ||
from pathlib import Path | ||
import argparse | ||
from datetime import datetime | ||
|
||
def calculate_sha256(filename): | ||
sha256_hash = hashlib.sha256() | ||
with open(filename, "rb") as f: | ||
for byte_block in iter(lambda: f.read(4096), b""): | ||
sha256_hash.update(byte_block) | ||
return sha256_hash.hexdigest() | ||
|
||
def create_plugin_package(version): | ||
# Create zip file from src directory | ||
src_dir = "bob-plugin" | ||
output_name = f"voi-{version}" | ||
|
||
# Create zip archive | ||
shutil.make_archive(output_name, 'zip', src_dir) | ||
|
||
# Rename to .bobplugin | ||
plugin_file = f"{output_name}.bobplugin" | ||
os.rename(f"{output_name}.zip", plugin_file) | ||
|
||
return plugin_file | ||
|
||
def update_appcast(version, plugin_file): | ||
appcast_file = "appcast.json" | ||
|
||
# Calculate SHA256 | ||
sha256 = calculate_sha256(plugin_file) | ||
|
||
# Read existing appcast.json | ||
if os.path.exists(appcast_file): | ||
with open(appcast_file, 'r') as f: | ||
appcast = json.load(f) | ||
else: | ||
appcast = { | ||
"identifier": "com.meet.bob-plugin-voi", | ||
"versions": [] | ||
} | ||
|
||
# Create new version entry | ||
new_version = { | ||
"version": version, | ||
"desc": "auto", | ||
"sha256": sha256, | ||
"url": f"https://raw.githubusercontent.com/xnmeet/voi/releases/download/v{version}/{plugin_file}", | ||
"minBobVersion": "0.5.0" | ||
} | ||
|
||
# Add or update version | ||
versions = appcast["versions"] | ||
for i, v in enumerate(versions): | ||
if v["version"] == version: | ||
versions[i] = new_version | ||
break | ||
else: | ||
versions.insert(0, new_version) | ||
|
||
# Write updated appcast.json | ||
with open(appcast_file, 'w') as f: | ||
json.dump(appcast, f, indent=2) | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description='Create Bob plugin package and update appcast.json') | ||
parser.add_argument('version', help='Version number (e.g., 0.0.1)') | ||
args = parser.parse_args() | ||
|
||
plugin_file = create_plugin_package(args.version) | ||
update_appcast(args.version, plugin_file) | ||
print(f"Created plugin package: {plugin_file}") | ||
print("Updated appcast.json") | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
__pycache__ | ||
*.pyc | ||
*.pyo | ||
*.pyd | ||
.Python | ||
env | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
.tox | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
*.log | ||
.pytest_cache | ||
.env | ||
.venv | ||
.DS_Store |
Oops, something went wrong.