xiaozhi-sdk 0.0.7__py3-none-any.whl → 0.0.9__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.

Potentially problematic release.


This version of xiaozhi-sdk might be problematic. Click here for more details.

xiaozhi_sdk/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
- __version__ = "0.0.7"
1
+ __version__ = "0.0.9"
2
2
 
3
3
  from xiaozhi_sdk.core import XiaoZhiWebsocket # noqa
xiaozhi_sdk/cli.py CHANGED
@@ -46,12 +46,14 @@ async def handle_message(message):
46
46
  is_end = True
47
47
 
48
48
 
49
- async def play_assistant_audio(audio_queue: deque[bytes]):
49
+ async def play_assistant_audio(audio_queue: deque[bytes], enable_audio):
50
50
  """播放音频流"""
51
51
  global is_playing_audio
52
52
 
53
- stream = sd.OutputStream(samplerate=INPUT_SERVER_AUDIO_SAMPLE_RATE, channels=1, dtype=np.int16)
54
- stream.start()
53
+ stream = None
54
+ if enable_audio:
55
+ stream = sd.OutputStream(samplerate=INPUT_SERVER_AUDIO_SAMPLE_RATE, channels=1, dtype=np.int16)
56
+ stream.start()
55
57
  last_audio_time = None
56
58
 
57
59
  while True:
@@ -66,7 +68,8 @@ async def play_assistant_audio(audio_queue: deque[bytes]):
66
68
 
67
69
  is_playing_audio = True
68
70
  pcm_data = audio_queue.popleft()
69
- stream.write(pcm_data)
71
+ if stream:
72
+ stream.write(pcm_data)
70
73
  last_audio_time = time.time()
71
74
 
72
75
 
@@ -83,7 +86,7 @@ class XiaoZhiClient:
83
86
  self.ota_url = ota_url
84
87
  self.mac_address = ""
85
88
 
86
- async def start(self, mac_address: str, serial_number: str = "", license_key: str = ""):
89
+ async def start(self, mac_address: str, serial_number: str, license_key: str, enable_audio):
87
90
  """启动客户端连接"""
88
91
  self.mac_address = mac_address
89
92
  self.xiaozhi = XiaoZhiWebsocket(handle_message, url=self.url, ota_url=self.ota_url, send_wake=True)
@@ -92,7 +95,7 @@ class XiaoZhiClient:
92
95
  self.mac_address, aec=False, serial_number=serial_number, license_key=license_key
93
96
  )
94
97
 
95
- asyncio.create_task(play_assistant_audio(self.xiaozhi.output_audio_queue))
98
+ asyncio.create_task(play_assistant_audio(self.xiaozhi.output_audio_queue, enable_audio))
96
99
 
97
100
  def audio_callback(self, indata, frames, time, status):
98
101
  """音频输入回调函数"""
@@ -115,11 +118,11 @@ class XiaoZhiClient:
115
118
  await self.xiaozhi.send_audio(pcm_data)
116
119
 
117
120
 
118
- async def run_client(mac_address: str, url: str, ota_url: str, serial_number: str, license_key: str):
121
+ async def run_client(mac_address: str, url: str, ota_url: str, serial_number: str, license_key: str, enable_audio: bool):
119
122
  """运行客户端的异步函数"""
120
123
  logger.debug("Recording... Press Ctrl+C to stop.")
121
124
  client = XiaoZhiClient(url, ota_url)
122
- await client.start(mac_address, serial_number, license_key)
125
+ await client.start(mac_address, serial_number, license_key, enable_audio)
123
126
 
124
127
  with sd.InputStream(callback=client.audio_callback, channels=1, samplerate=16000, blocksize=960):
125
128
  await client.process_audio_input()
@@ -131,9 +134,10 @@ async def run_client(mac_address: str, url: str, ota_url: str, serial_number: st
131
134
  @click.option("--ota_url", help="OTA地址")
132
135
  @click.option("--serial_number", default="", help="设备的序列号")
133
136
  @click.option("--license_key", default="", help="设备的授权密钥")
134
- def main(mac_address: str, url: str, ota_url: str, serial_number: str, license_key: str):
137
+ @click.option("--enable_audio", default=True, help="是否开启音频播放")
138
+ def main(mac_address: str, url: str, ota_url: str, serial_number: str, license_key: str, enable_audio: bool):
135
139
  """小智SDK客户端
136
140
 
137
141
  MAC_ADDRESS: 设备的MAC地址 (格式: XX:XX:XX:XX:XX:XX)
138
142
  """
139
- asyncio.run(run_client(mac_address, url, ota_url, serial_number, license_key))
143
+ asyncio.run(run_client(mac_address, url, ota_url, serial_number, license_key, enable_audio))
xiaozhi_sdk/mcp.py CHANGED
@@ -43,7 +43,7 @@ class McpTool(object):
43
43
  try:
44
44
  response = requests.post(self.explain_url, files=files, data=payload, headers=headers, timeout=5)
45
45
  res_json = response.json()
46
- except Exception as e:
46
+ except Exception:
47
47
  return "网络异常", True
48
48
  if res_json.get("error"):
49
49
  return res_json, True
@@ -72,10 +72,11 @@ class McpTool(object):
72
72
  else:
73
73
  tool_res, is_error = {"message": "正在为你播放: {}".format(arguments["music_name"])}, False
74
74
  data = {
75
- "type": "music", "state": "start",
75
+ "type": "music",
76
+ "state": "start",
76
77
  "url": music_info["url"],
77
78
  "text": arguments["music_name"],
78
- "source": "sdk.mcp_music_tool"
79
+ "source": "sdk.mcp_music_tool",
79
80
  }
80
81
  await self.message_handler_callback(data)
81
82
 
@@ -1,4 +1,4 @@
1
- from typing import Any, Dict, List
1
+ from typing import Any, Dict
2
2
 
3
3
  mcp_initialize_payload: Dict[str, Any] = {
4
4
  "jsonrpc": "2.0",
@@ -23,7 +23,10 @@ mcp_tool_conf: Dict[str, Dict[str, Any]] = {
23
23
  "description": "Play music using music IDs. IMPORTANT: You must call `search_custom_music` first to get the music IDs before using this tool. Use this tool after getting music IDs from search results. Args:\n `id_list`: The id list of the music to play (obtained from search_custom_music results). The list must contain more than 2 music IDs, and the system will randomly select one to play.\n `music_name`: The name of the music (obtained from search_custom_music results)",
24
24
  "inputSchema": {
25
25
  "type": "object",
26
- "properties": {"music_name": {"type": "string"}, "id_list": {"type": "array", "items": {"type": "string"}, "minItems": 3}},
26
+ "properties": {
27
+ "music_name": {"type": "string"},
28
+ "id_list": {"type": "array", "items": {"type": "string"}, "minItems": 3},
29
+ },
27
30
  "required": ["music_name", "id_list"],
28
31
  },
29
32
  },
@@ -3,7 +3,6 @@ import random
3
3
 
4
4
  import aiohttp
5
5
  import numpy as np
6
- from pydub import AudioSegment
7
6
 
8
7
 
9
8
  async def async_search_custom_music(data) -> tuple[dict, bool]:
@@ -57,6 +56,11 @@ async def _get_random_music_info(id_list: list) -> dict:
57
56
 
58
57
 
59
58
  async def async_mcp_play_music(data) -> tuple[list, bool]:
59
+ try:
60
+ from pydub import AudioSegment
61
+ except ImportError:
62
+ return [], True
63
+
60
64
  id_list = data["id_list"]
61
65
  res_json = await _get_random_music_info(id_list)
62
66
 
@@ -79,7 +83,7 @@ async def async_mcp_play_music(data) -> tuple[list, bool]:
79
83
 
80
84
  chunk_size = 960 * 2
81
85
  for i in range(0, len(pcm_data), chunk_size):
82
- chunk = pcm_data[i: i + chunk_size]
86
+ chunk = pcm_data[i : i + chunk_size]
83
87
 
84
88
  if chunk: # 确保不添加空块
85
89
  chunk = np.frombuffer(chunk, dtype=np.int16)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xiaozhi-sdk
3
- Version: 0.0.7
3
+ Version: 0.0.9
4
4
  Summary: 一个用于连接和控制小智智能设备的Python SDK,支持实时音频通信、MCP工具集成和设备管理功能。
5
5
  Author-email: dairoot <623815825@qq.com>
6
6
  License-Expression: MIT
@@ -8,19 +8,19 @@ file/opus/linux-x64-libopus.so,sha256=FmXJqkxLpDzNFOHYkmOzmsp1hP0eIS5b6x_XfOs-IQ
8
8
  file/opus/macos-arm64-libopus.dylib,sha256=H7wXwkrGwb-hesMMZGFxWb0Ri1Y4m5GWiKsd8CfOhE8,357584
9
9
  file/opus/macos-x64-libopus.dylib,sha256=MqyL_OjwSACF4Xs_-KrGbcScy4IEprr5Rlkk3ddZye8,550856
10
10
  file/opus/windows-opus.dll,sha256=kLfhioMvbJhOgNMAldpWk3DCZqC5Xd70LRbHnACvAnw,463360
11
- xiaozhi_sdk/__init__.py,sha256=42z4NTA7JPjhEk64Z2CmOkQ71dd3aPyLX02T6gQfe_4,77
11
+ xiaozhi_sdk/__init__.py,sha256=-gx5Vs8YIZLaWKtMWumKSkCiYu2Nu8Z7rFjFnYbkDhQ,77
12
12
  xiaozhi_sdk/__main__.py,sha256=i0ZJdHUqAKg9vwZrK_w0TJkzdotTYTK8aUeSPcJc1ks,210
13
- xiaozhi_sdk/cli.py,sha256=KCSTyH6ocMSNs3WYRSqQsvGlzJNRqBR88otz-w-yb9E,4241
13
+ xiaozhi_sdk/cli.py,sha256=LFZE4f4A44EIPXLsowxQ4z_EskTh62MLusPwwFVtXr8,4490
14
14
  xiaozhi_sdk/config.py,sha256=h4mpMeBf2vT9qYAqCCbGVGmMemkgk98pcXP2Rh4TEFc,89
15
15
  xiaozhi_sdk/core.py,sha256=564SefCBus6qNRApWqwI113aIN1p4eYpci1mLeMExIs,10007
16
16
  xiaozhi_sdk/iot.py,sha256=IO3SfiuQxucYl_917BCNCwIAv1dajCJI-IFTWwHnSDE,2580
17
- xiaozhi_sdk/mcp.py,sha256=kFkyZjLrjJNwZuZtFueMdeFAjzm0DJa7GsXcIg5YYi4,5524
17
+ xiaozhi_sdk/mcp.py,sha256=Pbr3JEDqEnWsPwLHKzRdrDYZMg6krYZoz74lXUSh9iI,5544
18
18
  xiaozhi_sdk/opus.py,sha256=r3nnYg0ZKAJTreb_3nKgfHJh06MJiMvnNMPO1SWdoMM,2224
19
19
  xiaozhi_sdk/utils/__init__.py,sha256=XKSHWoFmuSkpwaIr308HybRzfFIXoT1Fd-eUKo_im6Y,1705
20
- xiaozhi_sdk/utils/mcp_data.py,sha256=xeZhqucYCeKPJiRbrTptkNeCd0ampQXgb5lA5UsJW3U,3851
21
- xiaozhi_sdk/utils/mcp_tool.py,sha256=OU1mr3qr4XB0nvE8sX6-eCZyT2l-RdFe0caaTbOf4L8,3085
22
- xiaozhi_sdk-0.0.7.dist-info/licenses/LICENSE,sha256=Vwgps1iODKl43cAtME_0dawTjAzNW-O2BWiN5BHggww,1085
23
- xiaozhi_sdk-0.0.7.dist-info/METADATA,sha256=K4p1y2BqooqQ5gWqm4gf3iVQ5AbATsX-WgbBIM0jtHU,2091
24
- xiaozhi_sdk-0.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
- xiaozhi_sdk-0.0.7.dist-info/top_level.txt,sha256=nBpue4hU5Ykm5CtYPsAdxSa_yqbtZsIT_gF_EkBaJPM,12
26
- xiaozhi_sdk-0.0.7.dist-info/RECORD,,
20
+ xiaozhi_sdk/utils/mcp_data.py,sha256=r_GLjFpvUKeV8IhlkT7Pfb4c9bDO9q4k3f4iPZBBcKI,3892
21
+ xiaozhi_sdk/utils/mcp_tool.py,sha256=imwehfUlENjelYmGbGYgb6C82-ijs53XCxrtCpqrJps,3152
22
+ xiaozhi_sdk-0.0.9.dist-info/licenses/LICENSE,sha256=Vwgps1iODKl43cAtME_0dawTjAzNW-O2BWiN5BHggww,1085
23
+ xiaozhi_sdk-0.0.9.dist-info/METADATA,sha256=kqk96A4tgE9-b4rn-eyFKLLoXYqky1v3tlnVscck14k,2091
24
+ xiaozhi_sdk-0.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ xiaozhi_sdk-0.0.9.dist-info/top_level.txt,sha256=nBpue4hU5Ykm5CtYPsAdxSa_yqbtZsIT_gF_EkBaJPM,12
26
+ xiaozhi_sdk-0.0.9.dist-info/RECORD,,