xiaozhi-sdk 0.0.7__tar.gz → 0.0.9__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.
Files changed (35) hide show
  1. {xiaozhi_sdk-0.0.7/xiaozhi_sdk.egg-info → xiaozhi_sdk-0.0.9}/PKG-INFO +1 -1
  2. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/tests/test_xiaozhi.py +13 -16
  3. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/__init__.py +1 -1
  4. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/cli.py +14 -10
  5. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/mcp.py +4 -3
  6. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/utils/mcp_data.py +5 -2
  7. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/utils/mcp_tool.py +6 -2
  8. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9/xiaozhi_sdk.egg-info}/PKG-INFO +1 -1
  9. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/LICENSE +0 -0
  10. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/MANIFEST.in +0 -0
  11. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/README.md +0 -0
  12. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/audio/greet.wav +0 -0
  13. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/audio/play_music.wav +0 -0
  14. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/audio/say_hello.wav +0 -0
  15. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/audio/take_photo.wav +0 -0
  16. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/image/leijun.jpg +0 -0
  17. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/opus/linux-arm64-libopus.so +0 -0
  18. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/opus/linux-x64-libopus.so +0 -0
  19. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/opus/macos-arm64-libopus.dylib +0 -0
  20. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/opus/macos-x64-libopus.dylib +0 -0
  21. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/file/opus/windows-opus.dll +0 -0
  22. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/pyproject.toml +0 -0
  23. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/setup.cfg +0 -0
  24. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/tests/test_iot.py +0 -0
  25. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/tests/test_pic.py +0 -0
  26. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/__main__.py +0 -0
  27. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/config.py +0 -0
  28. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/core.py +0 -0
  29. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/iot.py +0 -0
  30. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/opus.py +0 -0
  31. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk/utils/__init__.py +0 -0
  32. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk.egg-info/SOURCES.txt +0 -0
  33. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk.egg-info/dependency_links.txt +0 -0
  34. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk.egg-info/requires.txt +0 -0
  35. {xiaozhi_sdk-0.0.7 → xiaozhi_sdk-0.0.9}/xiaozhi_sdk.egg-info/top_level.txt +0 -0
@@ -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
@@ -69,9 +69,6 @@ async def message_handler_callback(message):
69
69
 
70
70
  MAC_ADDR = "00:22:44:66:88:00"
71
71
 
72
- ota_url = "http://localhost:3080/api/ota"
73
- URL = "ws://120.79.156.134:8380"
74
-
75
72
  ota_url = None
76
73
  URL = None
77
74
 
@@ -86,21 +83,21 @@ async def test_main():
86
83
  await xiaozhi.init_connection(MAC_ADDR)
87
84
 
88
85
  # # say hellow
89
- # for pcm in read_audio_file("./file/audio/say_hello.wav"):
90
- # await xiaozhi.send_audio(pcm)
91
- # await xiaozhi.send_silence_audio()
92
- # await assistant_audio_play(xiaozhi.output_audio_queue)
93
-
94
- # # say take photo
95
- # for pcm in read_audio_file("./file/audio/take_photo.wav"):
96
- # await xiaozhi.send_audio(pcm)
97
- # await xiaozhi.send_silence_audio()
98
- # await assistant_audio_play(xiaozhi.output_audio_queue, 5)
86
+ for pcm in read_audio_file("./file/audio/say_hello.wav"):
87
+ await xiaozhi.send_audio(pcm)
88
+ await xiaozhi.send_silence_audio()
89
+ await assistant_audio_play(xiaozhi.output_audio_queue)
99
90
 
100
- # play music
101
- for pcm in read_audio_file("./file/audio/play_music.wav"):
91
+ # say take photo
92
+ for pcm in read_audio_file("./file/audio/take_photo.wav"):
102
93
  await xiaozhi.send_audio(pcm)
103
94
  await xiaozhi.send_silence_audio()
104
- await assistant_audio_play(xiaozhi.output_audio_queue, 500)
95
+ await assistant_audio_play(xiaozhi.output_audio_queue, 5)
96
+
97
+ # play music
98
+ # for pcm in read_audio_file("./file/audio/play_music.wav"):
99
+ # await xiaozhi.send_audio(pcm)
100
+ # await xiaozhi.send_silence_audio()
101
+ # await assistant_audio_play(xiaozhi.output_audio_queue, 500)
105
102
 
106
103
  await xiaozhi.close()
@@ -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
@@ -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))
@@ -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
File without changes
File without changes
File without changes
File without changes
File without changes