vox4ai 0.1.0__tar.gz

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.
@@ -0,0 +1,22 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ .venv/
5
+ venv/
6
+ ENV/
7
+ .idea/
8
+ .vscode/
9
+ build/
10
+ dist/
11
+ .mypy_cache/
12
+ .ruff_cache/
13
+ .pytest_cache/
14
+ *.log
15
+ .env
16
+ .env.local
17
+
18
+ # Generated
19
+ .coverage
20
+ GEMINI.md
21
+ *.bak
22
+ .mutmut-tmp.toml
vox4ai-0.1.0/LICENSE ADDED
@@ -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.
vox4ai-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: vox4ai
3
+ Version: 0.1.0
4
+ Summary: TTS 音声合成 CLI - vox / vox4ai コマンド
5
+ Project-URL: Homepage, https://github.com/vox4ai/vox4ai
6
+ Project-URL: Repository, https://github.com/vox4ai/vox4ai
7
+ Project-URL: Issues, https://github.com/vox4ai/vox4ai/issues
8
+ Author-email: utenadev <utena.cross+pypi@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: cli,edgetts,speech,synthesis,tts,tts-plugin-bridge,voice,vox4ai
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: End Users/Desktop
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
24
+ Classifier: Topic :: Utilities
25
+ Requires-Python: >=3.10
26
+ Requires-Dist: pydantic-settings>=2.14.1
27
+ Requires-Dist: pyyaml>=6.0
28
+ Requires-Dist: tts-plugin-bridge
29
+ Requires-Dist: tts-plugin-edgetts
30
+ Requires-Dist: vox4ai-skill-lib
31
+ Description-Content-Type: text/markdown
32
+
33
+ # vox4ai
34
+
35
+ <p align="center">
36
+ <img src="https://via.placeholder.com/1200x400/1a1a1a/ffffff?text=vox4ai" alt="vox4ai Banner" width="1200">
37
+ </p>
38
+
39
+ <p align="center">
40
+ <img src="https://img.shields.io/badge/pypi-latest-blue.svg" alt="PyPI version">
41
+ <img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License">
42
+ <img src="https://img.shields.io/badge/python-3.10%2B-yellow.svg" alt="Python Version">
43
+ <img src="https://img.shields.io/badge/maintained%3F-yes-brightgreen.svg" alt="Maintained">
44
+ </p>
45
+
46
+ <p align="center">
47
+ <a href="https://github.com/vox4ai/vox4ai">Website</a> •
48
+ <a href="https://github.com/vox4ai/vox4ai/issues">Report Bug</a> •
49
+ <a href="https://github.com/vox4ai/vox4ai/contributing">Contributing</a>
50
+ </p>
51
+
52
+ ---
53
+
54
+ ## 🚀 Overview
55
+
56
+ TTS 音声合成 CLI。`tts-plugin-bridge` のプラグインシステムに対応した TTS Engine を
57
+ 統一的に操作できます。`vox` と `vox4ai` 両方のコマンド名でインストールされます。
58
+
59
+ ## 📦 Installation
60
+
61
+ ```bash
62
+ uv add vox4ai
63
+ ```
64
+
65
+ インストールするだけで `tts-plugin-bridge` + `tts-plugin-edgetts`(クラウドデフォルト)が
66
+ 入り、追加のローカルサーバーなしで音声合成を試せます。
67
+
68
+ 他の TTS エンジンを追加する場合:
69
+
70
+ ```bash
71
+ uv add tts-plugin-aivisspeech # AivisSpeech Engine
72
+ uv add tts-plugin-piperplus # Piper Plus (HTTP server)
73
+ uv add tts-plugin-voisonatalk # VoiSona Talk
74
+ uv add tts-plugin-kokoro # Kokoro (local)
75
+ ```
76
+
77
+ ## 🛠 Usage
78
+
79
+ `vox` と `vox4ai` は同義。短い `vox` を推奨。
80
+
81
+ ```bash
82
+ # テキストを読み上げる(デフォルト: edgetts)
83
+ vox "こんにちは"
84
+
85
+ # 音声ファイルに保存
86
+ vox save "こんにちは" -o output.wav
87
+
88
+ # engine を明示指定
89
+ vox "こんにちは" -e aivisspeech --style-id 888753760
90
+
91
+ # 利用可能な TTS エンジン一覧
92
+ vox list
93
+
94
+ # 接続テスト
95
+ vox test -e aivisspeech --server-url http://localhost:10101
96
+
97
+ # 環境診断
98
+ vox --doctor
99
+
100
+ # 現在の設定
101
+ vox config
102
+
103
+ # サブコマンド一覧
104
+ vox --commands
105
+ ```
106
+
107
+ ## ⚙️ Configuration
108
+
109
+ `vox4ai say "こんにちは"` のように engine を省略しても、設定ファイルからデフォルト値を読み込みます。
110
+
111
+ **場所**: `~/.config/vox4ai/config.yaml`(XDG_CONFIG_HOME 準拠)
112
+
113
+ **設定例**:
114
+
115
+ ```yaml
116
+ # デフォルトの TTS Engine
117
+ engine: edgetts
118
+
119
+ # デフォルトの音声モデル
120
+ model: ja-JP-NanamiNeural
121
+
122
+ # TTS サーバーURL(aivisspeech などで必要)
123
+ server_url: http://localhost:10101
124
+
125
+ # デフォルトの話速(0.5 〜 2.0、デフォルト 1.0)
126
+ speed: 1.2
127
+
128
+ # 話者スタイル ID(aivisspeech など)
129
+ style_id: 888753760
130
+ ```
131
+
132
+ **優先順位**: `CLI 引数 > config.yaml > デフォルト値`
133
+
134
+ ## ⌨️ Subcommands
135
+
136
+ | Command | Description |
137
+ |---------|-------------|
138
+ | `say` | テキストを読み上げる(ffplay ストリーミング優先 → paplay/aplay) |
139
+ | `save` | テキストを音声ファイルに保存 |
140
+ | `list` | 利用可能なTTSプラグインを一覧表示 |
141
+ | `test` | TTSエンジンへの接続テスト |
142
+ | `config` | 現在の設定 (config.yaml) を表示 |
143
+
144
+ ## 📦 Dependencies
145
+
146
+ - `tts-plugin-bridge` — コアフレームワーク
147
+ - `tts-plugin-edgetts` — Microsoft Edge TTS(クラウド、デフォルト)
148
+ - `vox4ai-skill-lib` — 内部ライブラリ
149
+ - 任意の TTS プラグイン (`tts-plugin-aivisspeech`, `tts-plugin-piperplus` など)
150
+
151
+ ## 📜 License
152
+
153
+ MIT License
vox4ai-0.1.0/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # vox4ai
2
+
3
+ <p align="center">
4
+ <img src="https://via.placeholder.com/1200x400/1a1a1a/ffffff?text=vox4ai" alt="vox4ai Banner" width="1200">
5
+ </p>
6
+
7
+ <p align="center">
8
+ <img src="https://img.shields.io/badge/pypi-latest-blue.svg" alt="PyPI version">
9
+ <img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License">
10
+ <img src="https://img.shields.io/badge/python-3.10%2B-yellow.svg" alt="Python Version">
11
+ <img src="https://img.shields.io/badge/maintained%3F-yes-brightgreen.svg" alt="Maintained">
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://github.com/vox4ai/vox4ai">Website</a> •
16
+ <a href="https://github.com/vox4ai/vox4ai/issues">Report Bug</a> •
17
+ <a href="https://github.com/vox4ai/vox4ai/contributing">Contributing</a>
18
+ </p>
19
+
20
+ ---
21
+
22
+ ## 🚀 Overview
23
+
24
+ TTS 音声合成 CLI。`tts-plugin-bridge` のプラグインシステムに対応した TTS Engine を
25
+ 統一的に操作できます。`vox` と `vox4ai` 両方のコマンド名でインストールされます。
26
+
27
+ ## 📦 Installation
28
+
29
+ ```bash
30
+ uv add vox4ai
31
+ ```
32
+
33
+ インストールするだけで `tts-plugin-bridge` + `tts-plugin-edgetts`(クラウドデフォルト)が
34
+ 入り、追加のローカルサーバーなしで音声合成を試せます。
35
+
36
+ 他の TTS エンジンを追加する場合:
37
+
38
+ ```bash
39
+ uv add tts-plugin-aivisspeech # AivisSpeech Engine
40
+ uv add tts-plugin-piperplus # Piper Plus (HTTP server)
41
+ uv add tts-plugin-voisonatalk # VoiSona Talk
42
+ uv add tts-plugin-kokoro # Kokoro (local)
43
+ ```
44
+
45
+ ## 🛠 Usage
46
+
47
+ `vox` と `vox4ai` は同義。短い `vox` を推奨。
48
+
49
+ ```bash
50
+ # テキストを読み上げる(デフォルト: edgetts)
51
+ vox "こんにちは"
52
+
53
+ # 音声ファイルに保存
54
+ vox save "こんにちは" -o output.wav
55
+
56
+ # engine を明示指定
57
+ vox "こんにちは" -e aivisspeech --style-id 888753760
58
+
59
+ # 利用可能な TTS エンジン一覧
60
+ vox list
61
+
62
+ # 接続テスト
63
+ vox test -e aivisspeech --server-url http://localhost:10101
64
+
65
+ # 環境診断
66
+ vox --doctor
67
+
68
+ # 現在の設定
69
+ vox config
70
+
71
+ # サブコマンド一覧
72
+ vox --commands
73
+ ```
74
+
75
+ ## ⚙️ Configuration
76
+
77
+ `vox4ai say "こんにちは"` のように engine を省略しても、設定ファイルからデフォルト値を読み込みます。
78
+
79
+ **場所**: `~/.config/vox4ai/config.yaml`(XDG_CONFIG_HOME 準拠)
80
+
81
+ **設定例**:
82
+
83
+ ```yaml
84
+ # デフォルトの TTS Engine
85
+ engine: edgetts
86
+
87
+ # デフォルトの音声モデル
88
+ model: ja-JP-NanamiNeural
89
+
90
+ # TTS サーバーURL(aivisspeech などで必要)
91
+ server_url: http://localhost:10101
92
+
93
+ # デフォルトの話速(0.5 〜 2.0、デフォルト 1.0)
94
+ speed: 1.2
95
+
96
+ # 話者スタイル ID(aivisspeech など)
97
+ style_id: 888753760
98
+ ```
99
+
100
+ **優先順位**: `CLI 引数 > config.yaml > デフォルト値`
101
+
102
+ ## ⌨️ Subcommands
103
+
104
+ | Command | Description |
105
+ |---------|-------------|
106
+ | `say` | テキストを読み上げる(ffplay ストリーミング優先 → paplay/aplay) |
107
+ | `save` | テキストを音声ファイルに保存 |
108
+ | `list` | 利用可能なTTSプラグインを一覧表示 |
109
+ | `test` | TTSエンジンへの接続テスト |
110
+ | `config` | 現在の設定 (config.yaml) を表示 |
111
+
112
+ ## 📦 Dependencies
113
+
114
+ - `tts-plugin-bridge` — コアフレームワーク
115
+ - `tts-plugin-edgetts` — Microsoft Edge TTS(クラウド、デフォルト)
116
+ - `vox4ai-skill-lib` — 内部ライブラリ
117
+ - 任意の TTS プラグイン (`tts-plugin-aivisspeech`, `tts-plugin-piperplus` など)
118
+
119
+ ## 📜 License
120
+
121
+ MIT License
@@ -0,0 +1,75 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "vox4ai"
7
+ version = "0.1.0"
8
+ description = "TTS 音声合成 CLI - vox / vox4ai コマンド"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "utenadev", email = "utena.cross+pypi@gmail.com"},
14
+ ]
15
+ keywords = ["tts", "tts-plugin-bridge", "edgetts", "voice", "speech", "synthesis", "cli", "vox4ai"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Developers",
20
+ "Intended Audience :: End Users/Desktop",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Topic :: Multimedia :: Sound/Audio :: Speech",
29
+ "Topic :: Utilities",
30
+ ]
31
+ dependencies = [
32
+ "tts-plugin-bridge",
33
+ "tts-plugin-edgetts",
34
+ "vox4ai-skill-lib",
35
+ "pyyaml>=6.0",
36
+ "pydantic-settings>=2.14.1",
37
+ ]
38
+
39
+ [project.urls]
40
+ Homepage = "https://github.com/vox4ai/vox4ai"
41
+ Repository = "https://github.com/vox4ai/vox4ai"
42
+ Issues = "https://github.com/vox4ai/vox4ai/issues"
43
+
44
+ [project.scripts]
45
+ vox = "vox4ai.cli:main"
46
+ vox4ai = "vox4ai.cli:main"
47
+
48
+ [tool.uv.sources]
49
+ tts-plugin-bridge = { path = "../tts-plugin-bridge", editable = true }
50
+ tts-plugin-edgetts = { path = "../tts-plugin-edgetts", editable = true }
51
+ vox4ai-skill-lib = { path = "../vox4ai-skill-lib", editable = true }
52
+
53
+ [dependency-groups]
54
+ dev = [
55
+ "build>=1.5.0",
56
+ "pytest>=9.0.3",
57
+ "pytest-asyncio>=1.3.0",
58
+ "pytest-cov>=6.0.0",
59
+ "ruff>=0.15.12",
60
+ "twine>=6.2.0",
61
+ ]
62
+
63
+ [tool.coverage.run]
64
+ source = ["vox4ai"]
65
+ branch = true
66
+ omit = ["*/tests/*", "*/__pycache__/*"]
67
+
68
+ [tool.coverage.report]
69
+ show_missing = true
70
+ fail_under = 50
71
+
72
+ [tool.mutmut]
73
+ paths_to_mutate = ["src/vox4ai/config.py"]
74
+ tests_dir = ["tests/test_config.py"]
75
+ backup = false
File without changes
@@ -0,0 +1,229 @@
1
+ import argparse
2
+ import asyncio
3
+ import shutil
4
+
5
+ from tts_plugin_bridge import ConnectorFactory
6
+ from vox4ai_skill_lib.api import (
7
+ list_engines,
8
+ synthesize_text,
9
+ play_text,
10
+ test_connection,
11
+ )
12
+
13
+ from vox4ai.config import load as load_config, merge_cli, show as show_config
14
+
15
+ _EPILOG = """
16
+ 使用例:
17
+ vox4ai say "こんにちは" # テキストを読む(ストリーミング優先)
18
+ vox4ai say "Hello" -e edgetts # Edge TTS で読む
19
+ vox4ai save "こんにちは" -o output.wav # WAV ファイルに保存
20
+ vox4ai list # 利用可能エンジン一覧
21
+ vox4ai test -e aivisspeech # 接続テスト
22
+ vox4ai --commands # 使用可能なサブコマンド & エンジン一覧
23
+ vox4ai --doctor # 環境診断
24
+ """
25
+
26
+ _COMMANDS = {
27
+ "say": "テキストを読み上げる(ストリーミング優先、ffplay/paplay/aplay)",
28
+ "save": "テキストを音声ファイルに保存",
29
+ "list": "利用可能なTTSプラグインを一覧表示",
30
+ "test": "TTSエンジンへの接続をテスト",
31
+ "config": "現在の設定(config.yaml)を表示",
32
+ }
33
+
34
+
35
+ def main():
36
+ return asyncio.run(_async_main())
37
+
38
+
39
+ async def _async_main():
40
+ parser = argparse.ArgumentParser(
41
+ description="vox4ai - 音声合成 CLI",
42
+ formatter_class=argparse.RawDescriptionHelpFormatter,
43
+ epilog=_EPILOG,
44
+ add_help=False,
45
+ )
46
+ parser.add_argument(
47
+ "--commands",
48
+ action="store_true",
49
+ help="利用可能なサブコマンド & TTSエンジン一覧を表示",
50
+ )
51
+ parser.add_argument(
52
+ "--doctor",
53
+ action="store_true",
54
+ help="環境の動作確認",
55
+ )
56
+ parser.add_argument(
57
+ "-h",
58
+ "--help",
59
+ action="store_true",
60
+ help="このヘルプを表示",
61
+ )
62
+ parser.add_argument(
63
+ "--tts-plugin-list",
64
+ action="store_true",
65
+ help=argparse.SUPPRESS,
66
+ )
67
+
68
+ known, remaining = parser.parse_known_args()
69
+
70
+ if known.help:
71
+ parser.print_help()
72
+ return 0
73
+
74
+ if known.commands:
75
+ print("利用可能なサブコマンド:")
76
+ for name, desc in _COMMANDS.items():
77
+ print(f" {name:8s} {desc}")
78
+ print()
79
+ print("TTS エンジン:")
80
+ engines = ConnectorFactory.list_available()
81
+ if engines:
82
+ for eng in engines:
83
+ print(f" {eng}")
84
+ else:
85
+ print(" (none found)")
86
+ print()
87
+ print("詳細: vox4ai <コマンド> --help")
88
+ return 0
89
+
90
+ if known.doctor:
91
+ return await _doctor()
92
+
93
+ if known.tts_plugin_list:
94
+ return await list_engines()
95
+
96
+ sub = parser.add_subparsers(dest="command", help="利用可能なコマンド")
97
+ sub.add_parser("list", help="利用可能なTTSプラグインを一覧表示")
98
+ sub.add_parser("config", help="現在の設定表示")
99
+
100
+ say_parser = sub.add_parser(
101
+ "say", help="テキストを読み上げる(ストリーミング優先)"
102
+ )
103
+ say_parser.add_argument("text", help="読み上げるテキスト")
104
+ say_parser.add_argument("--engine", "-e", help="TTSエンジン名")
105
+ say_parser.add_argument("--speed", "-s", type=float, default=1.0, help="話速")
106
+ say_parser.add_argument("--volume", "-v", type=float, help="音量")
107
+ say_parser.add_argument("--pitch", "-p", type=float, help="ピッチ補正")
108
+ say_parser.add_argument("--server-url", help="TTSサーバーURL")
109
+ say_parser.add_argument("--style-id", type=int, help="話者スタイルID")
110
+ say_parser.add_argument("--model", help="音声モデル名")
111
+
112
+ save_parser = sub.add_parser("save", help="テキストを音声ファイルに保存")
113
+ save_parser.add_argument("text", help="合成するテキスト")
114
+ save_parser.add_argument("--engine", "-e", help="TTSエンジン名")
115
+ save_parser.add_argument("--speed", "-s", type=float, default=1.0, help="話速")
116
+ save_parser.add_argument("--volume", "-v", type=float, help="音量")
117
+ save_parser.add_argument("--pitch", "-p", type=float, help="ピッチ補正")
118
+ save_parser.add_argument("--server-url", help="TTSサーバーURL")
119
+ save_parser.add_argument("--style-id", type=int, help="話者スタイルID")
120
+ save_parser.add_argument(
121
+ "--output", "-o", help="出力ファイルパス(省略時はBase64表示)"
122
+ )
123
+ save_parser.add_argument("--play", action="store_true", help="保存後に再生")
124
+
125
+ test_parser = sub.add_parser("test", help="TTS接続をテスト")
126
+ test_parser.add_argument("--engine", "-e", help="TTSエンジン名")
127
+ test_parser.add_argument("--server-url", help="TTSサーバーURL")
128
+ test_parser.add_argument("--style-id", type=int, help="話者スタイルID")
129
+
130
+ args = parser.parse_args(remaining)
131
+
132
+ if not args.command:
133
+ parser.print_help()
134
+ return 1
135
+
136
+ if args.command == "config":
137
+ print(show_config())
138
+ return 0
139
+
140
+ cfg = load_config()
141
+ if args.command in ("say", "save", "test"):
142
+ merged = merge_cli(cfg, args)
143
+ else:
144
+ merged = {}
145
+
146
+ engine_kwargs = {}
147
+ if merged.get("server_url"):
148
+ engine_kwargs["server_url"] = merged["server_url"]
149
+
150
+ engine = merged.get("engine") or None
151
+ model = merged.get("model") or None
152
+ speed = merged.get("speed", 1.0)
153
+ volume = merged.get("volume")
154
+ pitch = merged.get("pitch")
155
+ style_id = merged.get("style_id")
156
+
157
+ if args.command == "list":
158
+ return await list_engines()
159
+ elif args.command == "say":
160
+ return await play_text(
161
+ args.text,
162
+ engine,
163
+ speed,
164
+ volume,
165
+ pitch,
166
+ style_id,
167
+ model,
168
+ engine_kwargs,
169
+ )
170
+ elif args.command == "save":
171
+ return await synthesize_text(
172
+ args.text,
173
+ engine,
174
+ speed,
175
+ volume,
176
+ pitch,
177
+ style_id,
178
+ getattr(args, "output", None),
179
+ engine_kwargs,
180
+ False,
181
+ getattr(args, "play", False),
182
+ )
183
+ elif args.command == "test":
184
+ return await test_connection(
185
+ engine,
186
+ style_id,
187
+ engine_kwargs,
188
+ )
189
+ else:
190
+ parser.print_help()
191
+ return 1
192
+
193
+
194
+ async def _doctor():
195
+ print("vox4ai 環境診断")
196
+ print("=" * 40)
197
+
198
+ print("\n[再生コマンド]")
199
+ for cmd in ("ffplay", "paplay", "aplay"):
200
+ found = shutil.which(cmd) is not None
201
+ print(f" {cmd:12s} {'found' if found else 'not found'}")
202
+
203
+ print("\n[TTS プラグイン]")
204
+ try:
205
+ engines = ConnectorFactory.list_available()
206
+ if engines:
207
+ for eng in engines:
208
+ print(f" {eng:15s} registered")
209
+ else:
210
+ print(" (none found)")
211
+ except Exception as e:
212
+ print(f" error: {e}")
213
+
214
+ print("\n[Python パッケージ]")
215
+ for pkg in ("tts-plugin-bridge", "edge-tts", "aiohttp", "pydantic"):
216
+ try:
217
+ __import__(pkg.replace("-", "_"))
218
+ print(f" {pkg:20s} installed")
219
+ except ImportError:
220
+ print(f" {pkg:20s} not installed")
221
+
222
+ print()
223
+ return 0
224
+
225
+
226
+ if __name__ == "__main__":
227
+ import sys
228
+
229
+ sys.exit(main())
@@ -0,0 +1,75 @@
1
+ import argparse
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ import yaml
7
+
8
+
9
+ def _config_dir() -> Path:
10
+ xdg = os.environ.get("XDG_CONFIG_HOME")
11
+ if xdg:
12
+ return Path(xdg) / "vox4ai"
13
+ return Path.home() / ".config" / "vox4ai"
14
+
15
+
16
+ def _config_path() -> Path:
17
+ return _config_dir() / "config.yaml"
18
+
19
+
20
+ _DEFAULTS: dict[str, Any] = {
21
+ "engine": "",
22
+ "model": "",
23
+ "server_url": "",
24
+ "style_id": None,
25
+ "speed": 1.0,
26
+ "volume": None,
27
+ "pitch": None,
28
+ }
29
+
30
+
31
+ def defaults() -> dict[str, Any]:
32
+ return dict(_DEFAULTS)
33
+
34
+
35
+ def load() -> dict[str, Any]:
36
+ """Load ~/.config/vox4ai/config.yaml, falling back to defaults."""
37
+ cfg = defaults()
38
+ path = _config_path()
39
+ if not path.exists():
40
+ return cfg
41
+ try:
42
+ raw = yaml.safe_load(path.read_text())
43
+ if isinstance(raw, dict):
44
+ for k in cfg:
45
+ if k in raw:
46
+ cfg[k] = raw[k]
47
+ except Exception:
48
+ pass
49
+ return cfg
50
+
51
+
52
+ def show() -> str:
53
+ path = _config_path()
54
+ if not path.exists():
55
+ return "(no config file)"
56
+ return path.read_text().strip() or "(empty)"
57
+
58
+
59
+ def merge_cli(cfg: dict[str, Any], args: argparse.Namespace) -> dict[str, Any]:
60
+ """CLI args override config values. Returns merged copy."""
61
+ merged = dict(cfg)
62
+ cli_map = {
63
+ "engine": "engine",
64
+ "model": "model",
65
+ "server_url": "server_url",
66
+ "style_id": "style_id",
67
+ "speed": "speed",
68
+ "volume": "volume",
69
+ "pitch": "pitch",
70
+ }
71
+ for cli_attr, cfg_key in cli_map.items():
72
+ val = getattr(args, cli_attr, None)
73
+ if val is not None and val != "":
74
+ merged[cfg_key] = val
75
+ return merged