11import os
22import sys
33
4- import dotenv
5- from ghoshell_common .contracts import LocalWorkspaceProvider
6-
7- from ghoshell_moss .speech import make_baseline_tts_speech
4+ from ghoshell_moss .speech import make_baseline_tts_speech , Speech
85from ghoshell_moss .speech .player .pyaudio_player import PyAudioStreamPlayer
96from ghoshell_moss .speech .volcengine_tts import VolcengineTTS , VolcengineTTSConf
107from ghoshell_moss_contrib .agent import ModelConf , SimpleAgent
118
12- current_dir = os .path .dirname (os .path .abspath (__file__ ))
13- sys .path .append (current_dir )
14-
159import asyncio
1610from os .path import dirname , join
1711
2721from miku_channels .head import head_chan
2822from miku_channels .leg import left_leg_chan , right_leg_chan
2923from miku_channels .necktie import necktie_chan
30-
3124from ghoshell_moss .core .shell import new_shell
25+ from ghoshell_moss_contrib .example_ws import workspace_container , get_example_speech
26+ import pathlib
27+
28+ # 加载当前路径.
29+ current_dir = os .path .dirname (os .path .abspath (__file__ ))
30+ sys .path .append (current_dir )
3231
3332# 全局状态
3433model : live2d .LAppModel | None = None
35- container = Container ()
3634WIDTH = 600
3735HEIGHT = 800
3836
39- WORKSPACE_DIR = ".workspace"
40- dotenv .load_dotenv (f"{ WORKSPACE_DIR } /.env" )
41-
4237
4338# 初始化Pygame和Live2D
4439def init_pygame ():
@@ -50,7 +45,7 @@ def init_pygame():
5045
5146
5247# 初始化Live2D模型
53- def init_live2d (model_path : str ):
48+ def init_live2d (model_path : str , container : Container ):
5449 global model
5550 live2d .init ()
5651 live2d .glInit ()
@@ -101,11 +96,9 @@ def stop_speak(*args):
10196 speaking_event .clear ()
10297
10398
104- async def run_agent ():
99+ async def run_agent (container : Container , speech : Speech | None = None ):
105100 loop = asyncio .get_running_loop ()
106101
107- container .register (LocalWorkspaceProvider (".workspace" ))
108-
109102 # 创建 Shell
110103 shell = new_shell (container = container )
111104
@@ -142,12 +135,15 @@ async def speaking():
142135 player = PyAudioStreamPlayer ()
143136 player .on_play (start_speak )
144137 player .on_play_done (stop_speak )
145- tts = VolcengineTTS (conf = VolcengineTTSConf (default_speaker = "saturn_zh_female_keainvsheng_tob" ))
138+ speech = speech or container .get (Speech )
139+ if speech is None :
140+ tts = VolcengineTTS (conf = VolcengineTTSConf (default_speaker = "saturn_zh_female_keainvsheng_tob" ))
141+ speech = make_baseline_tts_speech (player = player , tts = tts )
146142
147143 agent = SimpleAgent (
148144 instruction = "你是miku, 拥有 live2d 数字人躯体. 你是可爱和热情的数字人. " ,
149145 shell = shell ,
150- speech = make_baseline_tts_speech ( player = player , tts = tts ) ,
146+ speech = speech ,
151147 model = ModelConf (
152148 kwargs = {
153149 "thinking" : {
@@ -162,22 +158,22 @@ async def speaking():
162158 await speaking_task
163159
164160
165- async def run_agent_and_render ():
161+ async def run_agent_and_render (container : Container , speech : Speech | None = None ):
166162 # 初始化 Pygame 和 Live2D
167163 screen , display = init_pygame ()
168164 model_path = join (dirname (__file__ ), "model/miku.model3.json" )
169- init_live2d (model_path )
165+ init_live2d (model_path , container )
170166
171167 # 保持窗口打开,直到用户关闭
172168 running = True
173169 clock = pygame .time .Clock ()
174170 font = pygame .font .SysFont (None , 24 )
175171
176172 # 创建一个任务来运行 agent
177- agent_task = asyncio .create_task (run_agent ())
173+ agent_task = asyncio .create_task (run_agent (container , speech ))
178174
179175 try :
180- while running :
176+ while running and not agent_task . done () :
181177 # 处理pygame事件
182178 for event in pygame .event .get ():
183179 if event .type == pygame .QUIT :
@@ -201,20 +197,26 @@ async def run_agent_and_render():
201197 pass
202198 finally :
203199 # 取消agent任务
204- agent_task .cancel ()
205- try :
206- await agent_task
207- except asyncio .CancelledError :
208- pass
200+ if not agent_task .done ():
201+ agent_task .cancel ()
202+ try :
203+ await agent_task
204+ except asyncio .CancelledError :
205+ pass
209206
210207 # 清理资源
211208 live2d .dispose ()
212209 pygame .quit ()
213210
214211
212+ WORKSPACE_DIR = pathlib .Path (__file__ ).parent .parent .joinpath ('.workspace' )
213+
214+
215215def main ():
216216 # 运行异步主函数
217- asyncio .run (run_agent_and_render ())
217+ with workspace_container (WORKSPACE_DIR ) as container :
218+ speech = get_example_speech (container )
219+ asyncio .run (run_agent_and_render (container , speech ))
218220
219221
220222# 运行主函数
0 commit comments