xiaozhi-sdk 0.2.0__tar.gz → 0.2.1__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.

Potentially problematic release.


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

Files changed (36) hide show
  1. {xiaozhi_sdk-0.2.0/xiaozhi_sdk.egg-info → xiaozhi_sdk-0.2.1}/PKG-INFO +1 -1
  2. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/tests/test_xiaozhi.py +2 -2
  3. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/__init__.py +1 -1
  4. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/mcp.py +1 -1
  5. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/utils/mcp_tool.py +2 -94
  6. xiaozhi_sdk-0.2.1/xiaozhi_sdk/utils/tool_func.py +92 -0
  7. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1/xiaozhi_sdk.egg-info}/PKG-INFO +1 -1
  8. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk.egg-info/SOURCES.txt +2 -1
  9. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/LICENSE +0 -0
  10. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/MANIFEST.in +0 -0
  11. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/README.md +0 -0
  12. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/audio/greet.wav +0 -0
  13. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/audio/play_music.wav +0 -0
  14. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/audio/say_hello.wav +0 -0
  15. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/audio/take_photo.wav +0 -0
  16. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/image/leijun.jpg +0 -0
  17. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/opus/linux-arm64-libopus.so +0 -0
  18. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/opus/linux-x64-libopus.so +0 -0
  19. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/opus/macos-arm64-libopus.dylib +0 -0
  20. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/opus/macos-x64-libopus.dylib +0 -0
  21. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/file/opus/windows-opus.dll +0 -0
  22. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/pyproject.toml +0 -0
  23. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/setup.cfg +0 -0
  24. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/tests/test_iot.py +0 -0
  25. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/tests/test_pic.py +0 -0
  26. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/tests/test_wake_word.py +0 -0
  27. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/__main__.py +0 -0
  28. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/cli.py +0 -0
  29. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/config.py +0 -0
  30. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/core.py +0 -0
  31. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/iot.py +0 -0
  32. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/opus.py +0 -0
  33. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk/utils/__init__.py +0 -0
  34. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk.egg-info/dependency_links.txt +0 -0
  35. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/xiaozhi_sdk.egg-info/requires.txt +0 -0
  36. {xiaozhi_sdk-0.2.0 → xiaozhi_sdk-0.2.1}/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.2.0
3
+ Version: 0.2.1
4
4
  Summary: 一个用于连接和控制小智智能设备的Python SDK,支持实时音频通信、MCP工具集成和设备管理功能。
5
5
  Author-email: dairoot <623815825@qq.com>
6
6
  License-Expression: MIT
@@ -54,13 +54,13 @@ def mcp_tool_func():
54
54
  def mcp_set_volume(data) -> tuple[dict, bool]:
55
55
  return {}, False
56
56
 
57
- from xiaozhi_sdk.utils.mcp_tool import take_photo, get_device_status, set_volume
57
+ from xiaozhi_sdk.utils.mcp_tool import take_photo, get_device_status, set_volume, search_custom_music, play_custom_music
58
58
 
59
59
  take_photo["tool_func"] = mcp_take_photo
60
60
  get_device_status["tool_func"] = mcp_get_device_status
61
61
  set_volume["tool_func"] = mcp_set_volume
62
62
 
63
- return [take_photo, get_device_status, set_volume]
63
+ return [take_photo, get_device_status, set_volume, search_custom_music, play_custom_music]
64
64
 
65
65
 
66
66
  async def message_handler_callback(message):
@@ -1,3 +1,3 @@
1
- __version__ = "0.2.0"
1
+ __version__ = "0.2.1"
2
2
 
3
3
  from xiaozhi_sdk.core import XiaoZhiWebsocket # noqa
@@ -8,7 +8,7 @@ from typing import Any, Dict
8
8
  import numpy as np
9
9
  import requests
10
10
 
11
- from xiaozhi_sdk.utils.mcp_tool import _get_random_music_info
11
+ from xiaozhi_sdk.utils.tool_func import _get_random_music_info
12
12
 
13
13
  logger = logging.getLogger("xiaozhi_sdk")
14
14
 
@@ -1,96 +1,4 @@
1
- import io
2
- import random
3
-
4
- import aiohttp
5
- import numpy as np
6
-
7
-
8
- async def async_search_custom_music(data) -> tuple[dict, bool]:
9
- search_url = f"https://music-api.gdstudio.xyz/api.php?types=search&name={data['music_name']}&count=100&pages=1"
10
-
11
- # 为搜索请求设置 10 秒超时
12
- timeout = aiohttp.ClientTimeout(total=10)
13
- async with aiohttp.ClientSession(timeout=timeout) as session:
14
- async with session.get(search_url) as response:
15
- response_json = await response.json()
16
-
17
- music_list = []
18
- first_music_list = []
19
- other_music_list1 = []
20
- other_music_list2 = []
21
- for line in response_json:
22
- if data.get("author_name") and data["author_name"] in line["artist"][0]:
23
- first_music_list.append(line)
24
- elif data.get("author_name") and (data["author_name"] in line["artist"] or data["author_name"] in line["name"]):
25
- other_music_list1.append(line)
26
- else:
27
- other_music_list2.append(line)
28
-
29
- if len(first_music_list) <= 10:
30
- music_list = first_music_list
31
- random.shuffle(other_music_list2)
32
- music_list = music_list + other_music_list1[: 20 - len(music_list)]
33
- music_list = music_list + other_music_list2[: 20 - len(music_list)]
34
-
35
- # print(data)
36
- # print("找到音乐,数量:", len(first_music_list), len(music_list))
37
-
38
- if not music_list:
39
- return {}, False
40
- return {"message": "已找到歌曲", "music_list": music_list}, False
41
-
42
-
43
- async def _get_random_music_info(id_list: list) -> dict:
44
- timeout = aiohttp.ClientTimeout(total=10)
45
- async with aiohttp.ClientSession(timeout=timeout) as session:
46
- random.shuffle(id_list)
47
-
48
- for music_id in id_list:
49
- url = f"https://music-api.gdstudio.xyz/api.php?types=url&id={music_id}&br=128"
50
- async with session.get(url) as response:
51
- res_json = await response.json()
52
- if res_json.get("url"):
53
- break
54
-
55
- return res_json
56
-
57
-
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
-
64
- id_list = data["id_list"]
65
- res_json = await _get_random_music_info(id_list)
66
-
67
- if not res_json:
68
- return [], False
69
-
70
- pcm_list = []
71
- buffer = io.BytesIO()
72
- # 为下载音乐文件设置 60 秒超时(音乐文件可能比较大)
73
- download_timeout = aiohttp.ClientTimeout(total=60)
74
- async with aiohttp.ClientSession(timeout=download_timeout) as session:
75
- async with session.get(res_json["url"]) as resp:
76
- async for chunk in resp.content.iter_chunked(1024):
77
- buffer.write(chunk)
78
-
79
- buffer.seek(0)
80
- audio = AudioSegment.from_mp3(buffer)
81
- audio = audio.set_frame_rate(16000).set_channels(1).set_sample_width(2) # 2 bytes = 16 bits
82
- pcm_data = audio.raw_data
83
-
84
- chunk_size = 960 * 2
85
- for i in range(0, len(pcm_data), chunk_size):
86
- chunk = pcm_data[i : i + chunk_size]
87
-
88
- if chunk: # 确保不添加空块
89
- chunk = np.frombuffer(chunk, dtype=np.int16)
90
- pcm_list.extend(chunk)
91
-
92
- return pcm_list, False
93
-
1
+ from xiaozhi_sdk.utils.tool_func import async_mcp_play_music, async_search_custom_music
94
2
 
95
3
  search_custom_music = {
96
4
  "name": "search_custom_music",
@@ -164,7 +72,7 @@ set_theme = {
164
72
 
165
73
  take_photo = {
166
74
  "name": "take_photo",
167
- "description": "Use this tool when the user asks you to look at something, take a picture, or solve a problem based on what is captured.\nArgs:\n`question`: A clear question or task you want to ask about the captured photo (e.g., identify objects, read text, explain content, or solve a math/logic problem).\nReturn:\n A JSON object that provides the photo information, including answers, explanations, or problem-solving results if applicable.",
75
+ "description": "Have visual ability, Use this tool when the user asks you to look at something, take a picture, or solve a problem based on what is captured.\nArgs:\n`question`: A clear question or task you want to ask about the captured photo (e.g., identify objects, read text, explain content, or solve a math/logic problem).\nReturn:\n A JSON object that provides the photo information, including answers, explanations, or problem-solving results if applicable.",
168
76
  "inputSchema": {
169
77
  "type": "object",
170
78
  "properties": {"question": {"type": "string"}},
@@ -0,0 +1,92 @@
1
+ import io
2
+ import random
3
+
4
+ import aiohttp
5
+ import numpy as np
6
+
7
+
8
+ async def async_search_custom_music(data) -> tuple[dict, bool]:
9
+ search_url = f"https://music-api.gdstudio.xyz/api.php?types=search&name={data['music_name']}&count=100&pages=1"
10
+
11
+ # 为搜索请求设置 10 秒超时
12
+ timeout = aiohttp.ClientTimeout(total=10)
13
+ async with aiohttp.ClientSession(timeout=timeout) as session:
14
+ async with session.get(search_url) as response:
15
+ response_json = await response.json()
16
+
17
+ music_list = []
18
+ first_music_list = []
19
+ other_music_list1 = []
20
+ other_music_list2 = []
21
+ for line in response_json:
22
+ if data.get("author_name") and data["author_name"] in line["artist"][0]:
23
+ first_music_list.append(line)
24
+ elif data.get("author_name") and (data["author_name"] in line["artist"] or data["author_name"] in line["name"]):
25
+ other_music_list1.append(line)
26
+ else:
27
+ other_music_list2.append(line)
28
+
29
+ if len(first_music_list) <= 10:
30
+ music_list = first_music_list
31
+ random.shuffle(other_music_list2)
32
+ music_list = music_list + other_music_list1[: 20 - len(music_list)]
33
+ music_list = music_list + other_music_list2[: 20 - len(music_list)]
34
+
35
+ # print(data)
36
+ # print("找到音乐,数量:", len(first_music_list), len(music_list))
37
+
38
+ if not music_list:
39
+ return {}, False
40
+ return {"message": "已找到歌曲", "music_list": music_list}, False
41
+
42
+
43
+ async def _get_random_music_info(id_list: list) -> dict:
44
+ timeout = aiohttp.ClientTimeout(total=10)
45
+ async with aiohttp.ClientSession(timeout=timeout) as session:
46
+ random.shuffle(id_list)
47
+
48
+ for music_id in id_list:
49
+ url = f"https://music-api.gdstudio.xyz/api.php?types=url&id={music_id}&br=128"
50
+ async with session.get(url) as response:
51
+ res_json = await response.json()
52
+ if res_json.get("url"):
53
+ break
54
+
55
+ return res_json
56
+
57
+
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
+
64
+ id_list = data["id_list"]
65
+ res_json = await _get_random_music_info(id_list)
66
+
67
+ if not res_json:
68
+ return [], False
69
+
70
+ pcm_list = []
71
+ buffer = io.BytesIO()
72
+ # 为下载音乐文件设置 60 秒超时(音乐文件可能比较大)
73
+ download_timeout = aiohttp.ClientTimeout(total=60)
74
+ async with aiohttp.ClientSession(timeout=download_timeout) as session:
75
+ async with session.get(res_json["url"]) as resp:
76
+ async for chunk in resp.content.iter_chunked(1024):
77
+ buffer.write(chunk)
78
+
79
+ buffer.seek(0)
80
+ audio = AudioSegment.from_mp3(buffer)
81
+ audio = audio.set_frame_rate(16000).set_channels(1).set_sample_width(2) # 2 bytes = 16 bits
82
+ pcm_data = audio.raw_data
83
+
84
+ chunk_size = 960 * 2
85
+ for i in range(0, len(pcm_data), chunk_size):
86
+ chunk = pcm_data[i : i + chunk_size]
87
+
88
+ if chunk: # 确保不添加空块
89
+ chunk = np.frombuffer(chunk, dtype=np.int16)
90
+ pcm_list.extend(chunk)
91
+
92
+ return pcm_list, False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xiaozhi-sdk
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: 一个用于连接和控制小智智能设备的Python SDK,支持实时音频通信、MCP工具集成和设备管理功能。
5
5
  Author-email: dairoot <623815825@qq.com>
6
6
  License-Expression: MIT
@@ -40,4 +40,5 @@ xiaozhi_sdk/../file/opus/macos-arm64-libopus.dylib
40
40
  xiaozhi_sdk/../file/opus/macos-x64-libopus.dylib
41
41
  xiaozhi_sdk/../file/opus/windows-opus.dll
42
42
  xiaozhi_sdk/utils/__init__.py
43
- xiaozhi_sdk/utils/mcp_tool.py
43
+ xiaozhi_sdk/utils/mcp_tool.py
44
+ xiaozhi_sdk/utils/tool_func.py
File without changes
File without changes
File without changes
File without changes
File without changes