audex 1.0.7a3__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.
- audex/__init__.py +9 -0
- audex/__main__.py +7 -0
- audex/cli/__init__.py +189 -0
- audex/cli/apis/__init__.py +12 -0
- audex/cli/apis/init/__init__.py +34 -0
- audex/cli/apis/init/gencfg.py +130 -0
- audex/cli/apis/init/setup.py +330 -0
- audex/cli/apis/init/vprgroup.py +125 -0
- audex/cli/apis/serve.py +141 -0
- audex/cli/args.py +356 -0
- audex/cli/exceptions.py +44 -0
- audex/cli/helper/__init__.py +0 -0
- audex/cli/helper/ansi.py +193 -0
- audex/cli/helper/display.py +288 -0
- audex/config/__init__.py +64 -0
- audex/config/core/__init__.py +30 -0
- audex/config/core/app.py +29 -0
- audex/config/core/audio.py +45 -0
- audex/config/core/logging.py +163 -0
- audex/config/core/session.py +11 -0
- audex/config/helper/__init__.py +1 -0
- audex/config/helper/client/__init__.py +1 -0
- audex/config/helper/client/http.py +28 -0
- audex/config/helper/client/websocket.py +21 -0
- audex/config/helper/provider/__init__.py +1 -0
- audex/config/helper/provider/dashscope.py +13 -0
- audex/config/helper/provider/unisound.py +18 -0
- audex/config/helper/provider/xfyun.py +23 -0
- audex/config/infrastructure/__init__.py +31 -0
- audex/config/infrastructure/cache.py +51 -0
- audex/config/infrastructure/database.py +48 -0
- audex/config/infrastructure/recorder.py +32 -0
- audex/config/infrastructure/store.py +19 -0
- audex/config/provider/__init__.py +18 -0
- audex/config/provider/transcription.py +109 -0
- audex/config/provider/vpr.py +99 -0
- audex/container.py +40 -0
- audex/entity/__init__.py +468 -0
- audex/entity/doctor.py +109 -0
- audex/entity/doctor.pyi +51 -0
- audex/entity/fields.py +401 -0
- audex/entity/segment.py +115 -0
- audex/entity/segment.pyi +38 -0
- audex/entity/session.py +133 -0
- audex/entity/session.pyi +47 -0
- audex/entity/utterance.py +142 -0
- audex/entity/utterance.pyi +48 -0
- audex/entity/vp.py +68 -0
- audex/entity/vp.pyi +35 -0
- audex/exceptions.py +157 -0
- audex/filters/__init__.py +692 -0
- audex/filters/generated/__init__.py +21 -0
- audex/filters/generated/doctor.py +987 -0
- audex/filters/generated/segment.py +723 -0
- audex/filters/generated/session.py +978 -0
- audex/filters/generated/utterance.py +939 -0
- audex/filters/generated/vp.py +815 -0
- audex/helper/__init__.py +1 -0
- audex/helper/hash.py +33 -0
- audex/helper/mixin.py +65 -0
- audex/helper/net.py +19 -0
- audex/helper/settings/__init__.py +830 -0
- audex/helper/settings/fields.py +317 -0
- audex/helper/stream.py +153 -0
- audex/injectors/__init__.py +1 -0
- audex/injectors/config.py +12 -0
- audex/injectors/lifespan.py +7 -0
- audex/lib/__init__.py +1 -0
- audex/lib/cache/__init__.py +383 -0
- audex/lib/cache/inmemory.py +513 -0
- audex/lib/database/__init__.py +83 -0
- audex/lib/database/sqlite.py +406 -0
- audex/lib/exporter.py +189 -0
- audex/lib/injectors/__init__.py +1 -0
- audex/lib/injectors/cache.py +25 -0
- audex/lib/injectors/container.py +47 -0
- audex/lib/injectors/exporter.py +26 -0
- audex/lib/injectors/recorder.py +33 -0
- audex/lib/injectors/server.py +17 -0
- audex/lib/injectors/session.py +18 -0
- audex/lib/injectors/sqlite.py +24 -0
- audex/lib/injectors/store.py +13 -0
- audex/lib/injectors/transcription.py +42 -0
- audex/lib/injectors/usb.py +12 -0
- audex/lib/injectors/vpr.py +65 -0
- audex/lib/injectors/wifi.py +7 -0
- audex/lib/recorder.py +844 -0
- audex/lib/repos/__init__.py +149 -0
- audex/lib/repos/container.py +23 -0
- audex/lib/repos/database/__init__.py +1 -0
- audex/lib/repos/database/sqlite.py +672 -0
- audex/lib/repos/decorators.py +74 -0
- audex/lib/repos/doctor.py +286 -0
- audex/lib/repos/segment.py +302 -0
- audex/lib/repos/session.py +285 -0
- audex/lib/repos/tables/__init__.py +70 -0
- audex/lib/repos/tables/doctor.py +137 -0
- audex/lib/repos/tables/segment.py +113 -0
- audex/lib/repos/tables/session.py +140 -0
- audex/lib/repos/tables/utterance.py +131 -0
- audex/lib/repos/tables/vp.py +102 -0
- audex/lib/repos/utterance.py +288 -0
- audex/lib/repos/vp.py +286 -0
- audex/lib/restful.py +251 -0
- audex/lib/server/__init__.py +97 -0
- audex/lib/server/auth.py +98 -0
- audex/lib/server/handlers.py +248 -0
- audex/lib/server/templates/index.html.j2 +226 -0
- audex/lib/server/templates/login.html.j2 +111 -0
- audex/lib/server/templates/static/script.js +68 -0
- audex/lib/server/templates/static/style.css +579 -0
- audex/lib/server/types.py +123 -0
- audex/lib/session.py +503 -0
- audex/lib/store/__init__.py +238 -0
- audex/lib/store/localfile.py +411 -0
- audex/lib/transcription/__init__.py +33 -0
- audex/lib/transcription/dashscope.py +525 -0
- audex/lib/transcription/events.py +62 -0
- audex/lib/usb.py +554 -0
- audex/lib/vpr/__init__.py +38 -0
- audex/lib/vpr/unisound/__init__.py +185 -0
- audex/lib/vpr/unisound/types.py +469 -0
- audex/lib/vpr/xfyun/__init__.py +483 -0
- audex/lib/vpr/xfyun/types.py +679 -0
- audex/lib/websocket/__init__.py +8 -0
- audex/lib/websocket/connection.py +485 -0
- audex/lib/websocket/pool.py +991 -0
- audex/lib/wifi.py +1146 -0
- audex/lifespan.py +75 -0
- audex/service/__init__.py +27 -0
- audex/service/decorators.py +73 -0
- audex/service/doctor/__init__.py +652 -0
- audex/service/doctor/const.py +36 -0
- audex/service/doctor/exceptions.py +96 -0
- audex/service/doctor/types.py +54 -0
- audex/service/export/__init__.py +236 -0
- audex/service/export/const.py +17 -0
- audex/service/export/exceptions.py +34 -0
- audex/service/export/types.py +21 -0
- audex/service/injectors/__init__.py +1 -0
- audex/service/injectors/container.py +53 -0
- audex/service/injectors/doctor.py +34 -0
- audex/service/injectors/export.py +27 -0
- audex/service/injectors/session.py +49 -0
- audex/service/session/__init__.py +754 -0
- audex/service/session/const.py +34 -0
- audex/service/session/exceptions.py +67 -0
- audex/service/session/types.py +91 -0
- audex/types.py +39 -0
- audex/utils.py +287 -0
- audex/valueobj/__init__.py +81 -0
- audex/valueobj/common/__init__.py +1 -0
- audex/valueobj/common/auth.py +84 -0
- audex/valueobj/common/email.py +16 -0
- audex/valueobj/common/ops.py +22 -0
- audex/valueobj/common/phone.py +84 -0
- audex/valueobj/common/version.py +72 -0
- audex/valueobj/session.py +19 -0
- audex/valueobj/utterance.py +15 -0
- audex/view/__init__.py +51 -0
- audex/view/container.py +17 -0
- audex/view/decorators.py +303 -0
- audex/view/pages/__init__.py +1 -0
- audex/view/pages/dashboard/__init__.py +286 -0
- audex/view/pages/dashboard/wifi.py +407 -0
- audex/view/pages/login.py +110 -0
- audex/view/pages/recording.py +348 -0
- audex/view/pages/register.py +202 -0
- audex/view/pages/sessions/__init__.py +196 -0
- audex/view/pages/sessions/details.py +224 -0
- audex/view/pages/sessions/export.py +443 -0
- audex/view/pages/settings.py +374 -0
- audex/view/pages/voiceprint/__init__.py +1 -0
- audex/view/pages/voiceprint/enroll.py +195 -0
- audex/view/pages/voiceprint/update.py +195 -0
- audex/view/static/css/dashboard.css +452 -0
- audex/view/static/css/glass.css +22 -0
- audex/view/static/css/global.css +541 -0
- audex/view/static/css/login.css +386 -0
- audex/view/static/css/recording.css +439 -0
- audex/view/static/css/register.css +293 -0
- audex/view/static/css/sessions/styles.css +501 -0
- audex/view/static/css/settings.css +186 -0
- audex/view/static/css/voiceprint/enroll.css +43 -0
- audex/view/static/css/voiceprint/styles.css +209 -0
- audex/view/static/css/voiceprint/update.css +44 -0
- audex/view/static/images/logo.svg +95 -0
- audex/view/static/js/recording.js +42 -0
- audex-1.0.7a3.dist-info/METADATA +361 -0
- audex-1.0.7a3.dist-info/RECORD +192 -0
- audex-1.0.7a3.dist-info/WHEEL +4 -0
- audex-1.0.7a3.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
import hashlib
|
|
5
|
+
import typing as t
|
|
6
|
+
import uuid
|
|
7
|
+
|
|
8
|
+
from httpx import URL
|
|
9
|
+
from httpx import AsyncClient
|
|
10
|
+
|
|
11
|
+
from audex import utils
|
|
12
|
+
from audex.lib.restful import RESTfulMixin
|
|
13
|
+
from audex.lib.vpr import VPR
|
|
14
|
+
from audex.lib.vpr import VPRError
|
|
15
|
+
from audex.lib.vpr.unisound.types import ConfirmFeatureRequest
|
|
16
|
+
from audex.lib.vpr.unisound.types import ConfirmFeatureResponse
|
|
17
|
+
from audex.lib.vpr.unisound.types import CreateFeatureRequest
|
|
18
|
+
from audex.lib.vpr.unisound.types import CreateFeatureResponse
|
|
19
|
+
from audex.lib.vpr.unisound.types import CreateGroupRequest
|
|
20
|
+
from audex.lib.vpr.unisound.types import CreateGroupResponse
|
|
21
|
+
from audex.lib.vpr.unisound.types import UpdateFeatureRequest
|
|
22
|
+
from audex.lib.vpr.unisound.types import UpdateFeatureResponse
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UnisoundVPR(RESTfulMixin, VPR):
|
|
26
|
+
__logtag__ = "audex.lib.vpr.unisound"
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
*,
|
|
31
|
+
appkey: str,
|
|
32
|
+
secret: str,
|
|
33
|
+
group_id: str | None = None,
|
|
34
|
+
base_url: str = "https://ai-vpr.hivoice.cn",
|
|
35
|
+
proxy: str | URL | None = None,
|
|
36
|
+
timeout: float = 10.0,
|
|
37
|
+
http_client: AsyncClient | None = None,
|
|
38
|
+
default_headers: dict[str, str] | None = None,
|
|
39
|
+
default_params: dict[str, t.Any] | None = None,
|
|
40
|
+
):
|
|
41
|
+
self.appkey = appkey
|
|
42
|
+
self.secret = secret
|
|
43
|
+
self.group_id = group_id
|
|
44
|
+
super().__init__(
|
|
45
|
+
base_url=base_url,
|
|
46
|
+
proxy=proxy,
|
|
47
|
+
timeout=timeout,
|
|
48
|
+
http_client=http_client,
|
|
49
|
+
default_headers=default_headers,
|
|
50
|
+
default_params=default_params,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def _generate_sign(self, timestamp: int, nonce: str) -> str:
|
|
54
|
+
"""Generate signature for authentication."""
|
|
55
|
+
sign_str = f"{self.appkey}{timestamp}{self.secret}{nonce}"
|
|
56
|
+
return hashlib.sha256(sign_str.encode("utf-8")).hexdigest().upper()
|
|
57
|
+
|
|
58
|
+
def _build_auth_params(self) -> dict[str, t.Any]:
|
|
59
|
+
"""Build authentication parameters."""
|
|
60
|
+
timestamp = int(utils.utcnow().timestamp() * 1000)
|
|
61
|
+
nonce = uuid.uuid4().hex
|
|
62
|
+
sign = self._generate_sign(timestamp, nonce)
|
|
63
|
+
return {
|
|
64
|
+
"appkey": self.appkey,
|
|
65
|
+
"timestamp": timestamp,
|
|
66
|
+
"nonce": nonce,
|
|
67
|
+
"sign": sign,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async def create_group(self, name: str, gid: str | None = None) -> str:
|
|
71
|
+
if self.group_id:
|
|
72
|
+
raise VPRError("Group already exists, cannot create a new one.")
|
|
73
|
+
group_id = gid or utils.gen_id()
|
|
74
|
+
auth_params = self._build_auth_params()
|
|
75
|
+
|
|
76
|
+
response = await self.request(
|
|
77
|
+
endpoint="/vpr/v1/createGroup",
|
|
78
|
+
method="POST",
|
|
79
|
+
json=CreateGroupRequest(
|
|
80
|
+
**auth_params,
|
|
81
|
+
groupId=group_id,
|
|
82
|
+
groupInfo=name,
|
|
83
|
+
).model_dump(by_alias=True),
|
|
84
|
+
cast_to=CreateGroupResponse,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if response.code != 0:
|
|
88
|
+
raise VPRError(f"Failed to create group: [{response.code}] {response.msg}")
|
|
89
|
+
|
|
90
|
+
if not response.data or response.data.group_id != group_id:
|
|
91
|
+
raise VPRError("Group ID mismatch after creation.")
|
|
92
|
+
|
|
93
|
+
self.group_id = group_id
|
|
94
|
+
return self.group_id
|
|
95
|
+
|
|
96
|
+
async def enroll(self, data: bytes, sr: int, uid: str | None = None) -> str:
|
|
97
|
+
if not self.group_id:
|
|
98
|
+
raise VPRError("Group ID is not set. Cannot enroll feature.")
|
|
99
|
+
|
|
100
|
+
uid = uid or utils.gen_id()
|
|
101
|
+
auth_params = self._build_auth_params()
|
|
102
|
+
|
|
103
|
+
audio_data = base64.b64encode(data).decode("utf-8")
|
|
104
|
+
|
|
105
|
+
response = await self.request(
|
|
106
|
+
endpoint="/vpr/v1/createFeature",
|
|
107
|
+
method="POST",
|
|
108
|
+
json=CreateFeatureRequest(
|
|
109
|
+
**auth_params,
|
|
110
|
+
groupId=self.group_id,
|
|
111
|
+
featureId=uid,
|
|
112
|
+
featureInfo=f"Feature {uid}",
|
|
113
|
+
audioData=audio_data,
|
|
114
|
+
audioSampleRate=sr,
|
|
115
|
+
audioFormat="pcm",
|
|
116
|
+
).model_dump(by_alias=True),
|
|
117
|
+
cast_to=CreateFeatureResponse,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if response.code != 0:
|
|
121
|
+
raise VPRError(f"Failed to enroll feature: [{response.code}] {response.msg}")
|
|
122
|
+
|
|
123
|
+
if not response.data or response.data.feature_id != uid:
|
|
124
|
+
raise VPRError("Feature ID mismatch after registration.")
|
|
125
|
+
|
|
126
|
+
return uid
|
|
127
|
+
|
|
128
|
+
async def update(self, uid: str, data: bytes, sr: int) -> None:
|
|
129
|
+
if not self.group_id:
|
|
130
|
+
raise VPRError("Group ID is not set. Cannot update feature.")
|
|
131
|
+
|
|
132
|
+
auth_params = self._build_auth_params()
|
|
133
|
+
|
|
134
|
+
audio_data = base64.b64encode(data).decode("utf-8")
|
|
135
|
+
|
|
136
|
+
response = await self.request(
|
|
137
|
+
endpoint="/vpr/v1/updateFeatureById",
|
|
138
|
+
method="POST",
|
|
139
|
+
json=UpdateFeatureRequest(
|
|
140
|
+
**auth_params,
|
|
141
|
+
groupId=self.group_id,
|
|
142
|
+
featureId=uid,
|
|
143
|
+
featureInfo=f"Updated feature {uid}",
|
|
144
|
+
audioData=audio_data,
|
|
145
|
+
audioSampleRate=sr,
|
|
146
|
+
audioFormat="pcm",
|
|
147
|
+
).model_dump(by_alias=True),
|
|
148
|
+
cast_to=UpdateFeatureResponse,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
if response.code != 0:
|
|
152
|
+
raise VPRError(f"Failed to update feature: [{response.code}] {response.msg}")
|
|
153
|
+
|
|
154
|
+
if not response.data or not response.data.result:
|
|
155
|
+
raise VPRError("Feature update failed.")
|
|
156
|
+
|
|
157
|
+
async def verify(self, uid: str, data: bytes, sr: int) -> float:
|
|
158
|
+
if not self.group_id:
|
|
159
|
+
raise VPRError("Group ID is not set. Cannot verify feature.")
|
|
160
|
+
|
|
161
|
+
auth_params = self._build_auth_params()
|
|
162
|
+
|
|
163
|
+
audio_data = base64.b64encode(data).decode("utf-8")
|
|
164
|
+
|
|
165
|
+
response = await self.request(
|
|
166
|
+
endpoint="/vpr/v1/confirmFeature",
|
|
167
|
+
method="POST",
|
|
168
|
+
json=ConfirmFeatureRequest(
|
|
169
|
+
**auth_params,
|
|
170
|
+
groupId=self.group_id,
|
|
171
|
+
featureId=uid,
|
|
172
|
+
audioData=audio_data,
|
|
173
|
+
audioSampleRate=sr,
|
|
174
|
+
audioFormat="pcm",
|
|
175
|
+
).model_dump(by_alias=True),
|
|
176
|
+
cast_to=ConfirmFeatureResponse,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
if response.code != 0:
|
|
180
|
+
raise VPRError(f"Failed to verify feature: [{response.code}] {response.msg}")
|
|
181
|
+
|
|
182
|
+
if not response.data:
|
|
183
|
+
raise VPRError("No verification data returned.")
|
|
184
|
+
|
|
185
|
+
return response.data.score # type: ignore
|
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing as t
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Base Authentication Parameters
|
|
10
|
+
class AuthParams(BaseModel):
|
|
11
|
+
appkey: str = Field(
|
|
12
|
+
...,
|
|
13
|
+
description="Application key",
|
|
14
|
+
)
|
|
15
|
+
timestamp: int = Field(
|
|
16
|
+
...,
|
|
17
|
+
description="Access timestamp in milliseconds (UNIX timestamp)",
|
|
18
|
+
)
|
|
19
|
+
nonce: str = Field(
|
|
20
|
+
...,
|
|
21
|
+
description="Random nonce, must change for each request",
|
|
22
|
+
)
|
|
23
|
+
sign: str = Field(
|
|
24
|
+
...,
|
|
25
|
+
description="Signature for authentication",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Base Response
|
|
30
|
+
DataT = t.TypeVar("DataT")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class UnisoundResponse(BaseModel, t.Generic[DataT]):
|
|
34
|
+
code: int = Field(
|
|
35
|
+
...,
|
|
36
|
+
description="Error code, 0 indicates success",
|
|
37
|
+
)
|
|
38
|
+
msg: str = Field(
|
|
39
|
+
...,
|
|
40
|
+
description="Response message",
|
|
41
|
+
)
|
|
42
|
+
sid: str = Field(
|
|
43
|
+
...,
|
|
44
|
+
description="Unique session identifier",
|
|
45
|
+
)
|
|
46
|
+
data: DataT | None = Field(
|
|
47
|
+
None,
|
|
48
|
+
description="Response data body",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# Create Group
|
|
53
|
+
class CreateGroupRequest(AuthParams):
|
|
54
|
+
group_id: str = Field(
|
|
55
|
+
...,
|
|
56
|
+
alias="groupId",
|
|
57
|
+
serialization_alias="groupId",
|
|
58
|
+
description="Voiceprint group ID",
|
|
59
|
+
)
|
|
60
|
+
group_info: str = Field(
|
|
61
|
+
...,
|
|
62
|
+
alias="groupInfo",
|
|
63
|
+
serialization_alias="groupInfo",
|
|
64
|
+
description="Voiceprint group information",
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class CreateGroupData(BaseModel):
|
|
69
|
+
group_id: str = Field(
|
|
70
|
+
...,
|
|
71
|
+
alias="groupId",
|
|
72
|
+
serialization_alias="groupId",
|
|
73
|
+
description="Voiceprint group ID",
|
|
74
|
+
)
|
|
75
|
+
group_info: str = Field(
|
|
76
|
+
...,
|
|
77
|
+
alias="groupInfo",
|
|
78
|
+
serialization_alias="groupInfo",
|
|
79
|
+
description="Voiceprint group information",
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class CreateGroupResponse(BaseModel):
|
|
84
|
+
code: int
|
|
85
|
+
msg: str
|
|
86
|
+
sid: str
|
|
87
|
+
data: CreateGroupData | None = None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# Create Feature
|
|
91
|
+
class CreateFeatureRequest(AuthParams):
|
|
92
|
+
group_id: str = Field(
|
|
93
|
+
...,
|
|
94
|
+
alias="groupId",
|
|
95
|
+
serialization_alias="groupId",
|
|
96
|
+
description="Voiceprint group ID",
|
|
97
|
+
)
|
|
98
|
+
feature_id: str = Field(
|
|
99
|
+
...,
|
|
100
|
+
alias="featureId",
|
|
101
|
+
serialization_alias="featureId",
|
|
102
|
+
description="Voiceprint feature ID",
|
|
103
|
+
)
|
|
104
|
+
feature_info: str = Field(
|
|
105
|
+
...,
|
|
106
|
+
alias="featureInfo",
|
|
107
|
+
serialization_alias="featureInfo",
|
|
108
|
+
description="Voiceprint feature description",
|
|
109
|
+
)
|
|
110
|
+
audio_data: str = Field(
|
|
111
|
+
...,
|
|
112
|
+
alias="audioData",
|
|
113
|
+
serialization_alias="audioData",
|
|
114
|
+
description="Base64 encoded audio data",
|
|
115
|
+
)
|
|
116
|
+
audio_sample_rate: int = Field(
|
|
117
|
+
...,
|
|
118
|
+
alias="audioSampleRate",
|
|
119
|
+
serialization_alias="audioSampleRate",
|
|
120
|
+
description="Audio sample rate",
|
|
121
|
+
)
|
|
122
|
+
audio_format: t.Literal["pcm", "mp3", "opus", "adpcm"] = Field(
|
|
123
|
+
...,
|
|
124
|
+
alias="audioFormat",
|
|
125
|
+
serialization_alias="audioFormat",
|
|
126
|
+
description="Audio format",
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class CreateFeatureData(BaseModel):
|
|
131
|
+
feature_id: str = Field(
|
|
132
|
+
...,
|
|
133
|
+
alias="featureId",
|
|
134
|
+
serialization_alias="featureId",
|
|
135
|
+
description="Voiceprint feature ID",
|
|
136
|
+
)
|
|
137
|
+
feature_info: str = Field(
|
|
138
|
+
...,
|
|
139
|
+
alias="featureInfo",
|
|
140
|
+
serialization_alias="featureInfo",
|
|
141
|
+
description="Voiceprint feature information",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class CreateFeatureResponse(BaseModel):
|
|
146
|
+
code: int
|
|
147
|
+
msg: str
|
|
148
|
+
sid: str
|
|
149
|
+
data: CreateFeatureData | None = None
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
# Update Feature
|
|
153
|
+
class UpdateFeatureRequest(AuthParams):
|
|
154
|
+
group_id: str = Field(
|
|
155
|
+
...,
|
|
156
|
+
alias="groupId",
|
|
157
|
+
serialization_alias="groupId",
|
|
158
|
+
description="Voiceprint group ID",
|
|
159
|
+
)
|
|
160
|
+
feature_id: str = Field(
|
|
161
|
+
...,
|
|
162
|
+
alias="featureId",
|
|
163
|
+
serialization_alias="featureId",
|
|
164
|
+
description="Voiceprint feature ID",
|
|
165
|
+
)
|
|
166
|
+
feature_info: str | None = Field(
|
|
167
|
+
None,
|
|
168
|
+
alias="featureInfo",
|
|
169
|
+
serialization_alias="featureInfo",
|
|
170
|
+
description="Voiceprint feature description",
|
|
171
|
+
)
|
|
172
|
+
audio_data: str = Field(
|
|
173
|
+
...,
|
|
174
|
+
alias="audioData",
|
|
175
|
+
serialization_alias="audioData",
|
|
176
|
+
description="Base64 encoded audio data",
|
|
177
|
+
)
|
|
178
|
+
audio_sample_rate: int = Field(
|
|
179
|
+
...,
|
|
180
|
+
alias="audioSampleRate",
|
|
181
|
+
serialization_alias="audioSampleRate",
|
|
182
|
+
description="Audio sample rate",
|
|
183
|
+
)
|
|
184
|
+
audio_format: t.Literal["pcm", "mp3", "opus", "adpcm"] = Field(
|
|
185
|
+
...,
|
|
186
|
+
alias="audioFormat",
|
|
187
|
+
serialization_alias="audioFormat",
|
|
188
|
+
description="Audio format",
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class UpdateFeatureData(BaseModel):
|
|
193
|
+
result: bool = Field(
|
|
194
|
+
...,
|
|
195
|
+
description="Update result, true for success, false for failure",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class UpdateFeatureResponse(BaseModel):
|
|
200
|
+
code: int
|
|
201
|
+
msg: str
|
|
202
|
+
sid: str
|
|
203
|
+
data: UpdateFeatureData | None = None
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# Confirm Feature (1:1 Verification)
|
|
207
|
+
class ConfirmFeatureRequest(AuthParams):
|
|
208
|
+
group_id: str = Field(
|
|
209
|
+
...,
|
|
210
|
+
alias="groupId",
|
|
211
|
+
serialization_alias="groupId",
|
|
212
|
+
description="Voiceprint group ID",
|
|
213
|
+
)
|
|
214
|
+
feature_id: str = Field(
|
|
215
|
+
...,
|
|
216
|
+
alias="featureId",
|
|
217
|
+
serialization_alias="featureId",
|
|
218
|
+
description="Voiceprint feature ID",
|
|
219
|
+
)
|
|
220
|
+
audio_data: str = Field(
|
|
221
|
+
...,
|
|
222
|
+
alias="audioData",
|
|
223
|
+
serialization_alias="audioData",
|
|
224
|
+
description="Base64 encoded audio data",
|
|
225
|
+
)
|
|
226
|
+
audio_sample_rate: int = Field(
|
|
227
|
+
...,
|
|
228
|
+
alias="audioSampleRate",
|
|
229
|
+
serialization_alias="audioSampleRate",
|
|
230
|
+
description="Audio sample rate",
|
|
231
|
+
)
|
|
232
|
+
audio_format: t.Literal["pcm", "mp3", "opus", "adpcm"] = Field(
|
|
233
|
+
...,
|
|
234
|
+
alias="audioFormat",
|
|
235
|
+
serialization_alias="audioFormat",
|
|
236
|
+
description="Audio format",
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class ConfirmFeatureData(BaseModel):
|
|
241
|
+
score: float = Field(
|
|
242
|
+
...,
|
|
243
|
+
description="Similarity score, 0 indicates no match",
|
|
244
|
+
)
|
|
245
|
+
feature_id: str = Field(
|
|
246
|
+
...,
|
|
247
|
+
alias="featureId",
|
|
248
|
+
serialization_alias="featureId",
|
|
249
|
+
description="Voiceprint feature ID",
|
|
250
|
+
)
|
|
251
|
+
feature_info: str = Field(
|
|
252
|
+
...,
|
|
253
|
+
alias="featureInfo",
|
|
254
|
+
serialization_alias="featureInfo",
|
|
255
|
+
description="Voiceprint feature information",
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
class ConfirmFeatureResponse(BaseModel):
|
|
260
|
+
code: int
|
|
261
|
+
msg: str
|
|
262
|
+
sid: str
|
|
263
|
+
data: ConfirmFeatureData | None = None
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
# Identify Feature by Group ID (1:N Identification)
|
|
267
|
+
class IdentifyFeatureByGroupIdRequest(AuthParams):
|
|
268
|
+
group_id: str = Field(
|
|
269
|
+
...,
|
|
270
|
+
alias="groupId",
|
|
271
|
+
serialization_alias="groupId",
|
|
272
|
+
description="Voiceprint group ID",
|
|
273
|
+
)
|
|
274
|
+
top_n: int = Field(
|
|
275
|
+
...,
|
|
276
|
+
alias="topN",
|
|
277
|
+
serialization_alias="topN",
|
|
278
|
+
ge=1,
|
|
279
|
+
le=10,
|
|
280
|
+
description="Number of top results to return",
|
|
281
|
+
)
|
|
282
|
+
audio_data: str = Field(
|
|
283
|
+
...,
|
|
284
|
+
alias="audioData",
|
|
285
|
+
serialization_alias="audioData",
|
|
286
|
+
description="Base64 encoded audio data",
|
|
287
|
+
)
|
|
288
|
+
audio_sample_rate: t.Literal[8000, 16000] = Field(
|
|
289
|
+
...,
|
|
290
|
+
alias="audioSampleRate",
|
|
291
|
+
serialization_alias="audioSampleRate",
|
|
292
|
+
description="Audio sample rate",
|
|
293
|
+
)
|
|
294
|
+
audio_format: t.Literal["pcm", "mp3", "opus", "adpcm"] = Field(
|
|
295
|
+
...,
|
|
296
|
+
alias="audioFormat",
|
|
297
|
+
serialization_alias="audioFormat",
|
|
298
|
+
description="Audio format",
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
class IdentifyFeatureResult(BaseModel):
|
|
303
|
+
score: float = Field(
|
|
304
|
+
...,
|
|
305
|
+
description="Similarity score, 0 indicates no match",
|
|
306
|
+
)
|
|
307
|
+
feature_id: str = Field(
|
|
308
|
+
...,
|
|
309
|
+
alias="featureId",
|
|
310
|
+
serialization_alias="featureId",
|
|
311
|
+
description="Voiceprint feature ID",
|
|
312
|
+
)
|
|
313
|
+
feature_info: str = Field(
|
|
314
|
+
...,
|
|
315
|
+
alias="featureInfo",
|
|
316
|
+
serialization_alias="featureInfo",
|
|
317
|
+
description="Voiceprint feature information",
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
class IdentifyFeatureByGroupIdResponse(BaseModel):
|
|
322
|
+
code: int
|
|
323
|
+
msg: str
|
|
324
|
+
sid: str
|
|
325
|
+
data: list[IdentifyFeatureResult] | None = None
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
# Identify Feature by IDs (1:N Identification)
|
|
329
|
+
class FeatureListItem(BaseModel):
|
|
330
|
+
group_id: str = Field(
|
|
331
|
+
...,
|
|
332
|
+
alias="groupId",
|
|
333
|
+
serialization_alias="groupId",
|
|
334
|
+
description="Voiceprint group ID",
|
|
335
|
+
)
|
|
336
|
+
feature_id: str = Field(
|
|
337
|
+
...,
|
|
338
|
+
alias="featureId",
|
|
339
|
+
serialization_alias="featureId",
|
|
340
|
+
description="Voiceprint feature ID",
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class IdentifyFeatureByIdsRequest(AuthParams):
|
|
345
|
+
feature_list: list[FeatureListItem] = Field(
|
|
346
|
+
...,
|
|
347
|
+
alias="featureList",
|
|
348
|
+
serialization_alias="featureList",
|
|
349
|
+
description="List of voiceprint feature IDs",
|
|
350
|
+
)
|
|
351
|
+
top_n: int = Field(
|
|
352
|
+
...,
|
|
353
|
+
alias="topN",
|
|
354
|
+
serialization_alias="topN",
|
|
355
|
+
ge=1,
|
|
356
|
+
le=10,
|
|
357
|
+
description="Number of top results to return",
|
|
358
|
+
)
|
|
359
|
+
audio_data: str = Field(
|
|
360
|
+
...,
|
|
361
|
+
alias="audioData",
|
|
362
|
+
serialization_alias="audioData",
|
|
363
|
+
description="Base64 encoded audio data",
|
|
364
|
+
)
|
|
365
|
+
audio_sample_rate: t.Literal[8000, 16000] = Field(
|
|
366
|
+
...,
|
|
367
|
+
alias="audioSampleRate",
|
|
368
|
+
serialization_alias="audioSampleRate",
|
|
369
|
+
description="Audio sample rate",
|
|
370
|
+
)
|
|
371
|
+
audio_format: t.Literal["pcm", "mp3", "opus", "adpcm"] = Field(
|
|
372
|
+
...,
|
|
373
|
+
alias="audioFormat",
|
|
374
|
+
serialization_alias="audioFormat",
|
|
375
|
+
description="Audio format",
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
class IdentifyFeatureByIdsResponse(BaseModel):
|
|
380
|
+
code: int
|
|
381
|
+
msg: str
|
|
382
|
+
sid: str
|
|
383
|
+
data: list[IdentifyFeatureResult] | None = None
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
# Delete Feature
|
|
387
|
+
class DeleteFeatureRequest(AuthParams):
|
|
388
|
+
group_id: str = Field(
|
|
389
|
+
...,
|
|
390
|
+
alias="groupId",
|
|
391
|
+
serialization_alias="groupId",
|
|
392
|
+
description="Voiceprint group ID",
|
|
393
|
+
)
|
|
394
|
+
feature_id: str = Field(
|
|
395
|
+
...,
|
|
396
|
+
alias="featureId",
|
|
397
|
+
serialization_alias="featureId",
|
|
398
|
+
description="Voiceprint feature ID",
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
class DeleteFeatureData(BaseModel):
|
|
403
|
+
result: bool = Field(
|
|
404
|
+
...,
|
|
405
|
+
description="Deletion result, true for success, false for failure",
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
class DeleteFeatureResponse(BaseModel):
|
|
410
|
+
code: int
|
|
411
|
+
msg: str
|
|
412
|
+
sid: str
|
|
413
|
+
data: DeleteFeatureData | None = None
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
# Delete Group
|
|
417
|
+
class DeleteGroupRequest(AuthParams):
|
|
418
|
+
group_id: str = Field(
|
|
419
|
+
...,
|
|
420
|
+
alias="groupId",
|
|
421
|
+
serialization_alias="groupId",
|
|
422
|
+
description="Voiceprint group ID",
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
class DeleteGroupData(BaseModel):
|
|
427
|
+
result: bool = Field(
|
|
428
|
+
...,
|
|
429
|
+
description="Deletion result, true for success, false for failure",
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
class DeleteGroupResponse(BaseModel):
|
|
434
|
+
code: int
|
|
435
|
+
msg: str
|
|
436
|
+
sid: str
|
|
437
|
+
data: DeleteGroupData | None = None
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
# Query Feature List
|
|
441
|
+
class QueryFeatureListRequest(AuthParams):
|
|
442
|
+
group_id: str = Field(
|
|
443
|
+
...,
|
|
444
|
+
alias="groupId",
|
|
445
|
+
serialization_alias="groupId",
|
|
446
|
+
description="Voiceprint group ID",
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
class FeatureInfo(BaseModel):
|
|
451
|
+
feature_id: str = Field(
|
|
452
|
+
...,
|
|
453
|
+
alias="featureId",
|
|
454
|
+
serialization_alias="featureId",
|
|
455
|
+
description="Voiceprint feature ID",
|
|
456
|
+
)
|
|
457
|
+
feature_info: str = Field(
|
|
458
|
+
...,
|
|
459
|
+
alias="featureInfo",
|
|
460
|
+
serialization_alias="featureInfo",
|
|
461
|
+
description="Voiceprint feature information",
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
class QueryFeatureListResponse(BaseModel):
|
|
466
|
+
code: int
|
|
467
|
+
msg: str
|
|
468
|
+
sid: str
|
|
469
|
+
data: list[FeatureInfo] | None = None
|