PrimeBot 启元 Q1 & T1 技能整活工作台
PYTHON SKILL SOURCE · 78行纯离线保底王

《社交能量补给站》极简源码精讲

零网络依赖、零外部音频、最适合活动现场首轮上机锁死 40 分基础分的稳健剧本

😜 调皮课代表大白话划重点(30 秒读懂核心)
短小精悍就是它的代名词!全篇一共才 78 行代码,没有任何花里胡哨的网络请求或外部文件读取。上台先问候一声,接着依次送上「勇气充电」、「灵感充电」、「快乐充电」三格好心情,每说一句配一个安全白名单动作(Q1 用 3001/3008/3007,T1 用双形态通吃的 26/43/26),稳得一批!

🔍 核心机关与修改指南

⚡ 30秒极速改台词 STEPS 元组

第 14~18 行的 STEPS 元组里放着三句充电台词,直接把文字改成你的段子、谜语或祝福词就能立刻打包!

🤖 双机型安全动作表 MOTIONS 字典

第 20~23 行定义了 Q1(3001/3008/3007,保持 7 秒)和 T1(26/43/26,保持 18 秒),choreography() 会自动校验 T1 形态。

🗣️ 工业级防吞字轮询 speak() 函数

第 35~55 行实现了带 4 秒起声监控与 0.7 秒防抖滤波的 speak(),彻底告别长句换气被截断的尴尬。

💻 完整源码与配置内容(共 78 行 · 支持行号定位与一键复制)

📄 共 78 行
1"""社交能量补给站:基于官方示例的 TTS 轮询与动作编排,纯标准库。"""
2
3import time
4
5ROBOT_MODEL = "q1"
6POLL_SECONDS = 0.1
7IDLE_SECONDS = 0.7
8STEPS = (
9 "第一格,勇气充电。今天你已经迈出了第一步,给自己加个油!",
10 "第二格,灵感充电。先让一个小点子跑起来,再慢慢把它变精彩!",
11 "第三格,快乐充电。请收下这份机械式认真,和百分之百的祝福!",
12)
13# 等待时长为保守初值,现场按动作权威表、任务日志与实际观感调整。
14MOTIONS = {
15 "q1": ((3001, 7.0), (3008, 7.0), (3007, 7.0)),
16 "t1": ((26, 18.0), (43, 18.0), (26, 18.0)),
17}
18
19
20def audio_state() -> int:
21 snapshot = robot.get_audio_play_state()
22 if isinstance(snapshot, dict):
23 state = snapshot.get("state")
24 if isinstance(state, dict) and state.get("value") in (1, 2):
25 return state["value"]
26 raise RuntimeError("AUDIO_STATE_INVALID")
27
28
29def speak(text: str) -> None:
30 """必须观测到起声及稳定空闲;超时终止,避免下一句截断当前音频。"""
31 print("SPEAK " + text, flush=True)
32 robot.play_tts(text)
33 start_deadline = time.monotonic() + 4.0
34 while audio_state() != 1:
35 if time.monotonic() >= start_deadline:
36 raise RuntimeError("TTS_NOT_STARTED")
37 time.sleep(POLL_SECONDS)
38
39 finish_deadline = time.monotonic() + max(len(text) * 0.45, 4.0) + 8.0
40 idle_since = None
41 while time.monotonic() < finish_deadline:
42 if audio_state() == 1:
43 idle_since = None
44 elif idle_since is None:
45 idle_since = time.monotonic()
46 elif time.monotonic() - idle_since >= IDLE_SECONDS:
47 return
48 time.sleep(POLL_SECONDS)
49 raise RuntimeError("TTS_NOT_FINISHED")
50
51
52def choreography() -> tuple:
53 if ROBOT_MODEL == "t1":
54 form = robot.get_t1_robot_form()
55 if form not in ("biped", "quadruped"):
56 raise RuntimeError("T1_FORM_UNKNOWN")
57 # 两种形态均使用 26/43,属于手册所列的四足允许集合。
58 print("T1_FORM " + form, flush=True)
59 return MOTIONS[ROBOT_MODEL]
60
61
62def main() -> None:
63 motions = choreography()
64 print("ENERGY_STATION_START model=" + ROBOT_MODEL, flush=True)
65 speak("欢迎来到社交能量补给站!不用扫码,送你三格好心情。")
66 for index, (text, (animation_id, hold)) in enumerate(zip(STEPS, motions), 1):
67 speak(text)
68 accepted = robot.play_animation(animation_id, interrupt=False)
69 print("ANIMATION step=%d id=%d accepted=%s" % (index, animation_id, accepted), flush=True)
70 if not accepted:
71 raise RuntimeError("ANIMATION_REJECTED id=%d" % animation_id)
72 time.sleep(hold)
73 speak("充电完成!愿你带着自己的点子出发。掌声送给每一个敢动手的人!")
74 print("ENERGY_STATION_DONE steps=%d" % len(STEPS), flush=True)
75
76
77# 与官方示例一样,在运行时 exec 注入 robot 后直接执行。
78main()