xiaozhi-sdk 0.2.0__py3-none-any.whl → 0.2.1__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.2.0"
1
+ __version__ = "0.2.1"
2
2
 
3
3
  from xiaozhi_sdk.core import XiaoZhiWebsocket # noqa
xiaozhi_sdk/mcp.py CHANGED
@@ -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
@@ -8,18 +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=EnDhE3nCihG1u1vq2yjaZLzlHRKoNmEC-eJSlD7BXxo,77
11
+ xiaozhi_sdk/__init__.py,sha256=kGE9WH-1FCNkLeRKBW9JxKexpUulSVdsoRj-sdU2YLI,77
12
12
  xiaozhi_sdk/__main__.py,sha256=i0ZJdHUqAKg9vwZrK_w0TJkzdotTYTK8aUeSPcJc1ks,210
13
13
  xiaozhi_sdk/cli.py,sha256=CEpjXW-vnT8DieaK1MV0AYCG4bmK2_vpIz-9zhWHVgE,7001
14
14
  xiaozhi_sdk/config.py,sha256=h4mpMeBf2vT9qYAqCCbGVGmMemkgk98pcXP2Rh4TEFc,89
15
15
  xiaozhi_sdk/core.py,sha256=kTcENYV7s91kpVyb5-E72l3GMweBpC8bKVZQ_SHR1GU,9807
16
16
  xiaozhi_sdk/iot.py,sha256=VVAheynp1iV4GCaoPywQWpKtlyoACDLswH8yfV_JZgI,2699
17
- xiaozhi_sdk/mcp.py,sha256=YLZOj1F2ILwqhfevETVK2_K7pVweJGMnuMcdRmu6PJg,6558
17
+ xiaozhi_sdk/mcp.py,sha256=TVSHrWIy7qDy8DQOjQ9EAzVZ1SFtXkSgTDYysL-dRhk,6559
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_tool.py,sha256=uxT8jUANGs1mDrTGVkIv1eO89k4qn8WAgXYzITBLObg,7251
21
- xiaozhi_sdk-0.2.0.dist-info/licenses/LICENSE,sha256=Vwgps1iODKl43cAtME_0dawTjAzNW-O2BWiN5BHggww,1085
22
- xiaozhi_sdk-0.2.0.dist-info/METADATA,sha256=PN5vqqocSqZEoQl30P_IO_QMfMY_cZo7YkboXP8SR3M,2121
23
- xiaozhi_sdk-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
- xiaozhi_sdk-0.2.0.dist-info/top_level.txt,sha256=nBpue4hU5Ykm5CtYPsAdxSa_yqbtZsIT_gF_EkBaJPM,12
25
- xiaozhi_sdk-0.2.0.dist-info/RECORD,,
20
+ xiaozhi_sdk/utils/mcp_tool.py,sha256=T6OIrSqcyAHQ85sduz5Klx646SoEnGD5ROBTKoX6NhE,4207
21
+ xiaozhi_sdk/utils/tool_func.py,sha256=imwehfUlENjelYmGbGYgb6C82-ijs53XCxrtCpqrJps,3152
22
+ xiaozhi_sdk-0.2.1.dist-info/licenses/LICENSE,sha256=Vwgps1iODKl43cAtME_0dawTjAzNW-O2BWiN5BHggww,1085
23
+ xiaozhi_sdk-0.2.1.dist-info/METADATA,sha256=rA2thvU3rvDsCuERU9NYZbm-RQkOpMdfUdmBWeAYJi8,2121
24
+ xiaozhi_sdk-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ xiaozhi_sdk-0.2.1.dist-info/top_level.txt,sha256=nBpue4hU5Ykm5CtYPsAdxSa_yqbtZsIT_gF_EkBaJPM,12
26
+ xiaozhi_sdk-0.2.1.dist-info/RECORD,,