tts-plugin-edgetts 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tts_plugin_edgetts/__init__.py +3 -0
- tts_plugin_edgetts/connector.py +86 -0
- tts_plugin_edgetts-0.1.0.dist-info/METADATA +157 -0
- tts_plugin_edgetts-0.1.0.dist-info/RECORD +7 -0
- tts_plugin_edgetts-0.1.0.dist-info/WHEEL +4 -0
- tts_plugin_edgetts-0.1.0.dist-info/entry_points.txt +2 -0
- tts_plugin_edgetts-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from typing import AsyncGenerator, Optional
|
|
2
|
+
|
|
3
|
+
import edge_tts
|
|
4
|
+
from tts_plugin_bridge.protocol import TTSConnector, TTSRequest, TTSResponse
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class EdgeTTSConnector(TTSConnector):
|
|
8
|
+
ENGINE_NAME = "edgetts"
|
|
9
|
+
SUPPORTED_PARAMS = ["voice", "rate", "pitch", "proxy"]
|
|
10
|
+
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
voice: str = "ja-JP-NanamiNeural",
|
|
14
|
+
rate: str = "+0%",
|
|
15
|
+
pitch: str = "+0Hz",
|
|
16
|
+
proxy: Optional[str] = None,
|
|
17
|
+
):
|
|
18
|
+
self.voice = voice
|
|
19
|
+
self.rate = rate
|
|
20
|
+
self.pitch = pitch
|
|
21
|
+
self.proxy = proxy
|
|
22
|
+
|
|
23
|
+
@staticmethod
|
|
24
|
+
def _speed_to_rate(speed: float) -> str:
|
|
25
|
+
percent = round((speed - 1.0) * 100)
|
|
26
|
+
return f"{percent:+d}%"
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def _volume_to_percent(volume: float) -> str:
|
|
30
|
+
percent = round((volume - 1.0) * 100)
|
|
31
|
+
return f"{percent:+d}%"
|
|
32
|
+
|
|
33
|
+
def _build_params(self, req: TTSRequest) -> dict:
|
|
34
|
+
voice = req.extra.get("voice") or req.model or self.voice
|
|
35
|
+
rate = req.extra.get("rate") or self._speed_to_rate(req.speed)
|
|
36
|
+
pitch = req.extra.get("pitch") or self.pitch
|
|
37
|
+
volume = self._volume_to_percent(req.volume) if req.volume else "+0%"
|
|
38
|
+
proxy = req.extra.get("proxy") or self.proxy
|
|
39
|
+
return {
|
|
40
|
+
"voice": voice,
|
|
41
|
+
"rate": rate,
|
|
42
|
+
"pitch": pitch,
|
|
43
|
+
"volume": volume,
|
|
44
|
+
"proxy": proxy,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async def synthesize(self, req: TTSRequest) -> TTSResponse:
|
|
48
|
+
try:
|
|
49
|
+
params = self._build_params(req)
|
|
50
|
+
communicate = edge_tts.Communicate(req.text, **params)
|
|
51
|
+
|
|
52
|
+
audio_chunks: list[bytes] = []
|
|
53
|
+
async for chunk in communicate.stream():
|
|
54
|
+
if chunk["type"] == "audio":
|
|
55
|
+
audio_chunks.append(chunk["data"])
|
|
56
|
+
|
|
57
|
+
if not audio_chunks:
|
|
58
|
+
return TTSResponse.fail("No audio data received from edge-tts")
|
|
59
|
+
|
|
60
|
+
audio_data = b"".join(audio_chunks)
|
|
61
|
+
return TTSResponse.ok(audio_data=audio_data, metadata={"format": "mp3"})
|
|
62
|
+
except Exception as e:
|
|
63
|
+
return TTSResponse.fail(f"{type(e).__name__}: {e}")
|
|
64
|
+
|
|
65
|
+
async def synthesize_stream(self, req: TTSRequest) -> AsyncGenerator[bytes, None]:
|
|
66
|
+
params = self._build_params(req)
|
|
67
|
+
communicate = edge_tts.Communicate(req.text, **params)
|
|
68
|
+
async for chunk in communicate.stream():
|
|
69
|
+
if chunk["type"] == "audio":
|
|
70
|
+
yield chunk["data"]
|
|
71
|
+
|
|
72
|
+
async def is_available(self) -> bool:
|
|
73
|
+
try:
|
|
74
|
+
await edge_tts.list_voices()
|
|
75
|
+
return True
|
|
76
|
+
except Exception:
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
async def close(self):
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
async def __aenter__(self):
|
|
83
|
+
return self
|
|
84
|
+
|
|
85
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
86
|
+
await self.close()
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tts-plugin-edgetts
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Microsoft Edge TTS 向け TTS Plugin (edge-tts backend)
|
|
5
|
+
Project-URL: Homepage, https://github.com/vox4ai/tts-plugin-edgetts
|
|
6
|
+
Project-URL: Repository, https://github.com/vox4ai/tts-plugin-edgetts
|
|
7
|
+
Project-URL: Issues, https://github.com/vox4ai/tts-plugin-edgetts/issues
|
|
8
|
+
Author-email: utenadev <utena.cross+pypi@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: edge,edgetts,microsoft,speech,synthesis,tts,tts-plugin,voice
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: edge-tts>=7.0
|
|
26
|
+
Requires-Dist: tts-plugin-bridge
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# tts-plugin-edgetts
|
|
30
|
+
|
|
31
|
+
<p align="center">
|
|
32
|
+
<img src="https://via.placeholder.com/1200x400/1a1a1a/ffffff?text=tts-plugin-edgetts" alt="tts-plugin-edgetts Banner" width="1200">
|
|
33
|
+
</p>
|
|
34
|
+
|
|
35
|
+
<p align="center">
|
|
36
|
+
<img src="https://img.shields.io/badge/pypi-latest-blue.svg" alt="PyPI version">
|
|
37
|
+
<img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License">
|
|
38
|
+
<img src="https://img.shields.io/badge/python-3.10%2B-yellow.svg" alt="Python Version">
|
|
39
|
+
<img src="https://img.shields.io/badge/maintained%3F-yes-brightgreen.svg" alt="Maintained">
|
|
40
|
+
</p>
|
|
41
|
+
|
|
42
|
+
<p align="center">
|
|
43
|
+
<a href="https://github.com/vox4ai/tts-plugin-edgetts">Website</a> •
|
|
44
|
+
<a href="https://github.com/vox4ai/tts-plugin-edgetts/issues">Report Bug</a> •
|
|
45
|
+
<a href="https://github.com/vox4ai/tts-plugin-edgetts/contributing">Contributing</a>
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 🚀 Overview
|
|
51
|
+
|
|
52
|
+
[edge-tts](https://github.com/rany2/edge-tts) (Microsoft Edge TTS) を `tts-plugin-bridge` で利用するためのプラグインです。
|
|
53
|
+
APIキー不要で多言語対応のTTSが利用できます。
|
|
54
|
+
|
|
55
|
+
## 📦 インストール
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
uv add tts-plugin-bridge tts-plugin-edgetts
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## ⚙️ 前提条件
|
|
62
|
+
|
|
63
|
+
- インターネット接続 (Microsoft Edge TTSサービスにアクセス)
|
|
64
|
+
- ローカルサーバー不要
|
|
65
|
+
- 再生には [ffplay](https://ffmpeg.org/ffplay.html) または `paplay` / `aplay` がPATHに存在すること
|
|
66
|
+
- ffplay がある場合: ストリーミング再生(受信しながら即時再生)
|
|
67
|
+
- ffplay がない場合: 全取得後に paplay / aplay で再生
|
|
68
|
+
|
|
69
|
+
## 🛠 Usage
|
|
70
|
+
|
|
71
|
+
### 🧩 Python API
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from tts_plugin_bridge import TTSSkill
|
|
75
|
+
|
|
76
|
+
async with TTSSkill(default_engine="edgetts") as skill:
|
|
77
|
+
# save / synthesize — ファイル保存やBase64取得用
|
|
78
|
+
res = await skill.save(
|
|
79
|
+
text="こんにちは、エッジティーティーエスのテストです。",
|
|
80
|
+
speed=1.2,
|
|
81
|
+
model="ja-JP-KeitaNeural",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# say / play — 直接再生(ffplayストリーミング → paplay/aplay)
|
|
85
|
+
res = await skill.say(
|
|
86
|
+
text="ストリーミングで即時再生します。",
|
|
87
|
+
speed=1.0,
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 🎤 CLI(vox4ai 推奨)
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# 直接再生(自動ストリーミング)
|
|
95
|
+
vox4ai say "こんにちは" -e edgetts
|
|
96
|
+
|
|
97
|
+
# 男性声で再生
|
|
98
|
+
vox4ai say "こんにちは" -e edgetts --model ja-JP-KeitaNeural
|
|
99
|
+
|
|
100
|
+
# ファイル保存(MP3)
|
|
101
|
+
vox4ai save "こんにちは" -e edgetts -o output.mp3
|
|
102
|
+
|
|
103
|
+
# 環境診断
|
|
104
|
+
vox4ai --doctor
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### ⌨️ CLI(tts-plugin-bridge 後方互換)
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
tts-plugin-bridge synthesize "こんにちは" -e edgetts -o output.mp3
|
|
111
|
+
tts-plugin-bridge play "こんにちは" -e edgetts
|
|
112
|
+
tts-plugin-bridge play "こんにちは" -e edgetts --model ja-JP-KeitaNeural
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 🔧 サポートパラメータ
|
|
116
|
+
|
|
117
|
+
| パラメータ | 型 | 説明 |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| `speed` | float | 話速 (1.0=標準, >1.0=速い) → edge-tts `rate` に自動変換 |
|
|
120
|
+
| `volume` | float | 音量倍率 → edge-tts `volume` に自動変換 |
|
|
121
|
+
| `model` | str | 音声名 (例: `ja-JP-KeitaNeural`) → edge-tts `voice` にマッピング |
|
|
122
|
+
| `extra.pitch` | str | ピッチ (例: `+5Hz`, `-10Hz`) |
|
|
123
|
+
| `extra.rate` | str | 話速の直接指定 (例: `+50%`, `-20%`)。speed変換より優先 |
|
|
124
|
+
| `extra.volume` | str | 音量の直接指定 (例: `+100%`)。volume変換より優先 |
|
|
125
|
+
| `extra.voice` | str | 音声名の直接指定。modelより優先 |
|
|
126
|
+
| `extra.proxy` | str | プロキシURL |
|
|
127
|
+
|
|
128
|
+
### 🗣️ 主な音声一覧
|
|
129
|
+
|
|
130
|
+
| 音声名 | 性別 | 言語 |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| `ja-JP-NanamiNeural` | 女性 | 日本語 (デフォルト) |
|
|
133
|
+
| `ja-JP-KeitaNeural` | 男性 | 日本語 |
|
|
134
|
+
| `en-US-EmmaMultilingualNeural` | 女性 | 英語 (多言語対応) |
|
|
135
|
+
| `en-US-AndrewNeural` | 男性 | 英語 |
|
|
136
|
+
|
|
137
|
+
全音声一覧: `uv run edge-tts --list-voices`
|
|
138
|
+
|
|
139
|
+
### 📁 出力フォーマット
|
|
140
|
+
|
|
141
|
+
MP3 (24kHz, 48kbps, mono)
|
|
142
|
+
|
|
143
|
+
## 🔍 検証環境
|
|
144
|
+
|
|
145
|
+
- **OS**: Windows 11 + WSL2 (Ubuntu)
|
|
146
|
+
- **確認日**: 2026-05-09
|
|
147
|
+
- **依存**: edge-tts v7.2.8, bridge / vox4ai CLI
|
|
148
|
+
- **確認内容**:
|
|
149
|
+
- `vox4ai say` によるストリーミング再生(ffplay 経由)
|
|
150
|
+
- `vox4ai save` による MP3 ファイル保存
|
|
151
|
+
- `vox4ai --doctor` 環境診断
|
|
152
|
+
- `tts-plugin-bridge` CLI 後方互換維持
|
|
153
|
+
- 全ユニットテスト 22件 パス
|
|
154
|
+
|
|
155
|
+
## 📜 ライセンス
|
|
156
|
+
|
|
157
|
+
MIT License
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
tts_plugin_edgetts/__init__.py,sha256=4OIoBm__Vwd-Y3kudEJwMXAUZJozZrO6PixiUgjwTJY,72
|
|
2
|
+
tts_plugin_edgetts/connector.py,sha256=80xPL-nMltFJ13mwsNRE_W0qqXHoHW5VKN-J4kgTNb4,2778
|
|
3
|
+
tts_plugin_edgetts-0.1.0.dist-info/METADATA,sha256=t8UHPah_MbhADWEFY_aNVJBb1fvDMOBwn1b0s9_BSFQ,5532
|
|
4
|
+
tts_plugin_edgetts-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
5
|
+
tts_plugin_edgetts-0.1.0.dist-info/entry_points.txt,sha256=_3VdHQZNdyipE_ZRdZYRYXlMWPIqSJtwd7lBIuI6lx0,80
|
|
6
|
+
tts_plugin_edgetts-0.1.0.dist-info/licenses/LICENSE,sha256=RnwZkqBFkeDYZDf3AlIh-qwLMPsJJajhB2YwaRRDWMU,1062
|
|
7
|
+
tts_plugin_edgetts-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vox4ai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|