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.
Files changed (192) hide show
  1. audex/__init__.py +9 -0
  2. audex/__main__.py +7 -0
  3. audex/cli/__init__.py +189 -0
  4. audex/cli/apis/__init__.py +12 -0
  5. audex/cli/apis/init/__init__.py +34 -0
  6. audex/cli/apis/init/gencfg.py +130 -0
  7. audex/cli/apis/init/setup.py +330 -0
  8. audex/cli/apis/init/vprgroup.py +125 -0
  9. audex/cli/apis/serve.py +141 -0
  10. audex/cli/args.py +356 -0
  11. audex/cli/exceptions.py +44 -0
  12. audex/cli/helper/__init__.py +0 -0
  13. audex/cli/helper/ansi.py +193 -0
  14. audex/cli/helper/display.py +288 -0
  15. audex/config/__init__.py +64 -0
  16. audex/config/core/__init__.py +30 -0
  17. audex/config/core/app.py +29 -0
  18. audex/config/core/audio.py +45 -0
  19. audex/config/core/logging.py +163 -0
  20. audex/config/core/session.py +11 -0
  21. audex/config/helper/__init__.py +1 -0
  22. audex/config/helper/client/__init__.py +1 -0
  23. audex/config/helper/client/http.py +28 -0
  24. audex/config/helper/client/websocket.py +21 -0
  25. audex/config/helper/provider/__init__.py +1 -0
  26. audex/config/helper/provider/dashscope.py +13 -0
  27. audex/config/helper/provider/unisound.py +18 -0
  28. audex/config/helper/provider/xfyun.py +23 -0
  29. audex/config/infrastructure/__init__.py +31 -0
  30. audex/config/infrastructure/cache.py +51 -0
  31. audex/config/infrastructure/database.py +48 -0
  32. audex/config/infrastructure/recorder.py +32 -0
  33. audex/config/infrastructure/store.py +19 -0
  34. audex/config/provider/__init__.py +18 -0
  35. audex/config/provider/transcription.py +109 -0
  36. audex/config/provider/vpr.py +99 -0
  37. audex/container.py +40 -0
  38. audex/entity/__init__.py +468 -0
  39. audex/entity/doctor.py +109 -0
  40. audex/entity/doctor.pyi +51 -0
  41. audex/entity/fields.py +401 -0
  42. audex/entity/segment.py +115 -0
  43. audex/entity/segment.pyi +38 -0
  44. audex/entity/session.py +133 -0
  45. audex/entity/session.pyi +47 -0
  46. audex/entity/utterance.py +142 -0
  47. audex/entity/utterance.pyi +48 -0
  48. audex/entity/vp.py +68 -0
  49. audex/entity/vp.pyi +35 -0
  50. audex/exceptions.py +157 -0
  51. audex/filters/__init__.py +692 -0
  52. audex/filters/generated/__init__.py +21 -0
  53. audex/filters/generated/doctor.py +987 -0
  54. audex/filters/generated/segment.py +723 -0
  55. audex/filters/generated/session.py +978 -0
  56. audex/filters/generated/utterance.py +939 -0
  57. audex/filters/generated/vp.py +815 -0
  58. audex/helper/__init__.py +1 -0
  59. audex/helper/hash.py +33 -0
  60. audex/helper/mixin.py +65 -0
  61. audex/helper/net.py +19 -0
  62. audex/helper/settings/__init__.py +830 -0
  63. audex/helper/settings/fields.py +317 -0
  64. audex/helper/stream.py +153 -0
  65. audex/injectors/__init__.py +1 -0
  66. audex/injectors/config.py +12 -0
  67. audex/injectors/lifespan.py +7 -0
  68. audex/lib/__init__.py +1 -0
  69. audex/lib/cache/__init__.py +383 -0
  70. audex/lib/cache/inmemory.py +513 -0
  71. audex/lib/database/__init__.py +83 -0
  72. audex/lib/database/sqlite.py +406 -0
  73. audex/lib/exporter.py +189 -0
  74. audex/lib/injectors/__init__.py +1 -0
  75. audex/lib/injectors/cache.py +25 -0
  76. audex/lib/injectors/container.py +47 -0
  77. audex/lib/injectors/exporter.py +26 -0
  78. audex/lib/injectors/recorder.py +33 -0
  79. audex/lib/injectors/server.py +17 -0
  80. audex/lib/injectors/session.py +18 -0
  81. audex/lib/injectors/sqlite.py +24 -0
  82. audex/lib/injectors/store.py +13 -0
  83. audex/lib/injectors/transcription.py +42 -0
  84. audex/lib/injectors/usb.py +12 -0
  85. audex/lib/injectors/vpr.py +65 -0
  86. audex/lib/injectors/wifi.py +7 -0
  87. audex/lib/recorder.py +844 -0
  88. audex/lib/repos/__init__.py +149 -0
  89. audex/lib/repos/container.py +23 -0
  90. audex/lib/repos/database/__init__.py +1 -0
  91. audex/lib/repos/database/sqlite.py +672 -0
  92. audex/lib/repos/decorators.py +74 -0
  93. audex/lib/repos/doctor.py +286 -0
  94. audex/lib/repos/segment.py +302 -0
  95. audex/lib/repos/session.py +285 -0
  96. audex/lib/repos/tables/__init__.py +70 -0
  97. audex/lib/repos/tables/doctor.py +137 -0
  98. audex/lib/repos/tables/segment.py +113 -0
  99. audex/lib/repos/tables/session.py +140 -0
  100. audex/lib/repos/tables/utterance.py +131 -0
  101. audex/lib/repos/tables/vp.py +102 -0
  102. audex/lib/repos/utterance.py +288 -0
  103. audex/lib/repos/vp.py +286 -0
  104. audex/lib/restful.py +251 -0
  105. audex/lib/server/__init__.py +97 -0
  106. audex/lib/server/auth.py +98 -0
  107. audex/lib/server/handlers.py +248 -0
  108. audex/lib/server/templates/index.html.j2 +226 -0
  109. audex/lib/server/templates/login.html.j2 +111 -0
  110. audex/lib/server/templates/static/script.js +68 -0
  111. audex/lib/server/templates/static/style.css +579 -0
  112. audex/lib/server/types.py +123 -0
  113. audex/lib/session.py +503 -0
  114. audex/lib/store/__init__.py +238 -0
  115. audex/lib/store/localfile.py +411 -0
  116. audex/lib/transcription/__init__.py +33 -0
  117. audex/lib/transcription/dashscope.py +525 -0
  118. audex/lib/transcription/events.py +62 -0
  119. audex/lib/usb.py +554 -0
  120. audex/lib/vpr/__init__.py +38 -0
  121. audex/lib/vpr/unisound/__init__.py +185 -0
  122. audex/lib/vpr/unisound/types.py +469 -0
  123. audex/lib/vpr/xfyun/__init__.py +483 -0
  124. audex/lib/vpr/xfyun/types.py +679 -0
  125. audex/lib/websocket/__init__.py +8 -0
  126. audex/lib/websocket/connection.py +485 -0
  127. audex/lib/websocket/pool.py +991 -0
  128. audex/lib/wifi.py +1146 -0
  129. audex/lifespan.py +75 -0
  130. audex/service/__init__.py +27 -0
  131. audex/service/decorators.py +73 -0
  132. audex/service/doctor/__init__.py +652 -0
  133. audex/service/doctor/const.py +36 -0
  134. audex/service/doctor/exceptions.py +96 -0
  135. audex/service/doctor/types.py +54 -0
  136. audex/service/export/__init__.py +236 -0
  137. audex/service/export/const.py +17 -0
  138. audex/service/export/exceptions.py +34 -0
  139. audex/service/export/types.py +21 -0
  140. audex/service/injectors/__init__.py +1 -0
  141. audex/service/injectors/container.py +53 -0
  142. audex/service/injectors/doctor.py +34 -0
  143. audex/service/injectors/export.py +27 -0
  144. audex/service/injectors/session.py +49 -0
  145. audex/service/session/__init__.py +754 -0
  146. audex/service/session/const.py +34 -0
  147. audex/service/session/exceptions.py +67 -0
  148. audex/service/session/types.py +91 -0
  149. audex/types.py +39 -0
  150. audex/utils.py +287 -0
  151. audex/valueobj/__init__.py +81 -0
  152. audex/valueobj/common/__init__.py +1 -0
  153. audex/valueobj/common/auth.py +84 -0
  154. audex/valueobj/common/email.py +16 -0
  155. audex/valueobj/common/ops.py +22 -0
  156. audex/valueobj/common/phone.py +84 -0
  157. audex/valueobj/common/version.py +72 -0
  158. audex/valueobj/session.py +19 -0
  159. audex/valueobj/utterance.py +15 -0
  160. audex/view/__init__.py +51 -0
  161. audex/view/container.py +17 -0
  162. audex/view/decorators.py +303 -0
  163. audex/view/pages/__init__.py +1 -0
  164. audex/view/pages/dashboard/__init__.py +286 -0
  165. audex/view/pages/dashboard/wifi.py +407 -0
  166. audex/view/pages/login.py +110 -0
  167. audex/view/pages/recording.py +348 -0
  168. audex/view/pages/register.py +202 -0
  169. audex/view/pages/sessions/__init__.py +196 -0
  170. audex/view/pages/sessions/details.py +224 -0
  171. audex/view/pages/sessions/export.py +443 -0
  172. audex/view/pages/settings.py +374 -0
  173. audex/view/pages/voiceprint/__init__.py +1 -0
  174. audex/view/pages/voiceprint/enroll.py +195 -0
  175. audex/view/pages/voiceprint/update.py +195 -0
  176. audex/view/static/css/dashboard.css +452 -0
  177. audex/view/static/css/glass.css +22 -0
  178. audex/view/static/css/global.css +541 -0
  179. audex/view/static/css/login.css +386 -0
  180. audex/view/static/css/recording.css +439 -0
  181. audex/view/static/css/register.css +293 -0
  182. audex/view/static/css/sessions/styles.css +501 -0
  183. audex/view/static/css/settings.css +186 -0
  184. audex/view/static/css/voiceprint/enroll.css +43 -0
  185. audex/view/static/css/voiceprint/styles.css +209 -0
  186. audex/view/static/css/voiceprint/update.css +44 -0
  187. audex/view/static/images/logo.svg +95 -0
  188. audex/view/static/js/recording.js +42 -0
  189. audex-1.0.7a3.dist-info/METADATA +361 -0
  190. audex-1.0.7a3.dist-info/RECORD +192 -0
  191. audex-1.0.7a3.dist-info/WHEEL +4 -0
  192. audex-1.0.7a3.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from audex.helper.settings import BaseModel
4
+ from audex.helper.settings.fields import Field
5
+ from audex.utils import UNSET
6
+ from audex.utils import Unset
7
+
8
+
9
+ class DashscopeCredentialConfig(BaseModel):
10
+ api_key: str | Unset = Field(
11
+ default=UNSET,
12
+ description="Dashscope API key for authentication.",
13
+ )
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from audex.helper.settings import BaseModel
4
+ from audex.helper.settings.fields import Field
5
+ from audex.utils import UNSET
6
+ from audex.utils import Unset
7
+
8
+
9
+ class UnisoundCredentialConfig(BaseModel):
10
+ appkey: str | Unset = Field(
11
+ default=UNSET,
12
+ description="Unisound App Key",
13
+ )
14
+
15
+ secret: str | Unset = Field(
16
+ default=UNSET,
17
+ description="Unisound Secret",
18
+ )
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from audex.helper.settings import BaseModel
4
+ from audex.helper.settings.fields import Field
5
+ from audex.utils import UNSET
6
+ from audex.utils import Unset
7
+
8
+
9
+ class XFYunCredentialConfig(BaseModel):
10
+ app_id: str | Unset = Field(
11
+ default=UNSET,
12
+ description="XFYun Application ID. Must be provided for authentication.",
13
+ )
14
+
15
+ api_key: str | Unset = Field(
16
+ default=UNSET,
17
+ description="XFYun API Key. Must be provided for authentication.",
18
+ )
19
+
20
+ api_secret: str | Unset = Field(
21
+ default=UNSET,
22
+ description="XFYun API Secret. Must be provided for authentication.",
23
+ )
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import Field
4
+
5
+ from audex.config.infrastructure.cache import CacheConfig
6
+ from audex.config.infrastructure.database import SQLiteConfig
7
+ from audex.config.infrastructure.recorder import RecorderConfig
8
+ from audex.config.infrastructure.store import StoreConfig
9
+ from audex.helper.settings import BaseModel
10
+
11
+
12
+ class InfrastructureConfig(BaseModel):
13
+ sqlite: SQLiteConfig = Field(
14
+ default_factory=SQLiteConfig,
15
+ description="SQLite configuration.",
16
+ )
17
+
18
+ cache: CacheConfig = Field(
19
+ default_factory=CacheConfig,
20
+ description="Cache configuration.",
21
+ )
22
+
23
+ store: StoreConfig = Field(
24
+ default_factory=StoreConfig,
25
+ description="Store configuration.",
26
+ )
27
+
28
+ recorder: RecorderConfig = Field(
29
+ default_factory=RecorderConfig,
30
+ description="Recorder configuration.",
31
+ )
@@ -0,0 +1,51 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from audex import __prog__
6
+ from audex.helper.settings import BaseModel
7
+ from audex.helper.settings.fields import Field
8
+
9
+
10
+ class InmemoryCacheConfig(BaseModel):
11
+ cache_type: t.Literal["lru", "lfu", "ttl", "fifo"] = Field(
12
+ default="ttl",
13
+ description="Type of in-memory cache algorithm to use.",
14
+ )
15
+
16
+ max_size: int = Field(
17
+ default=1024,
18
+ description="Maximum number of items to store in the cache.",
19
+ )
20
+
21
+ default_ttl: int = Field(
22
+ default=300,
23
+ description="Default time-to-live (TTL) for cache items in seconds.",
24
+ )
25
+
26
+ negative_ttl: int = Field(
27
+ default=60,
28
+ description="TTL for negative cache entries in seconds.",
29
+ )
30
+
31
+
32
+ class CacheConfig(BaseModel):
33
+ provider: t.Literal["inmemory"] = Field(
34
+ default="inmemory",
35
+ description="Type of cache backend to use.",
36
+ )
37
+
38
+ split_char: str = Field(
39
+ default=":",
40
+ description="Character used to split cache keys.",
41
+ )
42
+
43
+ prefix: str = Field(
44
+ default=__prog__,
45
+ description="Prefix for all cache keys.",
46
+ )
47
+
48
+ inmemory: InmemoryCacheConfig = Field(
49
+ default_factory=InmemoryCacheConfig,
50
+ description="Configuration for in-memory cache backend.",
51
+ )
@@ -0,0 +1,48 @@
1
+ from __future__ import annotations
2
+
3
+ from audex.helper.settings import BaseModel
4
+ from audex.helper.settings.fields import Field
5
+
6
+
7
+ class SQLiteConfig(BaseModel):
8
+ uri: str = Field(
9
+ default="sqlite+aiosqlite:///./audex.db",
10
+ description="SQLite database URI.",
11
+ windows_default="sqlite+aiosqlite:///C:/ProgramData/Audex/audex.db",
12
+ linux_default="sqlite+aiosqlite://${HOME}/.local/share/audex/audex.db",
13
+ )
14
+
15
+ echo: bool = Field(
16
+ default=False,
17
+ description="Enable SQL query logging for debugging purposes.",
18
+ )
19
+
20
+ pool_size: int = Field(
21
+ default=20,
22
+ description="The size of the database connection pool.",
23
+ )
24
+
25
+ max_overflow: int = Field(
26
+ default=10,
27
+ description="The maximum overflow size of the connection pool.",
28
+ )
29
+
30
+ pool_timeout: float = Field(
31
+ default=30.0,
32
+ description="The timeout in seconds to wait for a connection from the pool.",
33
+ )
34
+
35
+ pool_recycle: int = Field(
36
+ default=3600,
37
+ description="The number of seconds after which a connection is automatically recycled.",
38
+ )
39
+
40
+ pool_pre_ping: bool = Field(
41
+ default=True,
42
+ description="Enable connection health checks before using a connection from the pool.",
43
+ )
44
+
45
+ create_all: bool = Field(
46
+ default=True,
47
+ description="Whether to create all tables on initialization.",
48
+ )
@@ -0,0 +1,32 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from audex.helper.settings import BaseModel
6
+ from audex.helper.settings.fields import Field
7
+
8
+
9
+ class RecorderConfig(BaseModel):
10
+ format: t.Literal["float32", "int32", "int16", "int8", "uint8"] = Field(
11
+ default="int16",
12
+ description="Audio sample format.",
13
+ )
14
+
15
+ channels: int = Field(
16
+ default=1,
17
+ ge=1,
18
+ le=8,
19
+ description="Number of audio channels.",
20
+ )
21
+
22
+ chunk: int = Field(
23
+ default=1024,
24
+ ge=256,
25
+ le=8192,
26
+ description="Number of frames per buffer.",
27
+ )
28
+
29
+ input_device_index: int | None = Field(
30
+ default=None,
31
+ description="Index of the input audio device. If None, the default device is used.",
32
+ )
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from audex.helper.settings import BaseModel
6
+ from audex.helper.settings.fields import Field
7
+
8
+
9
+ class StoreConfig(BaseModel):
10
+ type: t.Literal["localfile"] = Field(
11
+ default="localfile",
12
+ description="Type of the store.",
13
+ )
14
+
15
+ base_url: str = Field(
16
+ default="store",
17
+ description="Store base URL. In case of 'file' type, it is the local directory path. In case of 'obs' type, it is the OBS bucket URL.",
18
+ system_path_type="data",
19
+ )
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from audex.config.provider.transcription import TranscriptionConfig
4
+ from audex.config.provider.vpr import VPRConfig
5
+ from audex.helper.settings import BaseModel
6
+ from audex.helper.settings.fields import Field
7
+
8
+
9
+ class ProviderConfig(BaseModel):
10
+ transcription: TranscriptionConfig = Field(
11
+ default_factory=TranscriptionConfig,
12
+ description="Transcription provider configuration",
13
+ )
14
+
15
+ vpr: VPRConfig = Field(
16
+ default_factory=VPRConfig,
17
+ description="VPR provider configuration",
18
+ )
@@ -0,0 +1,109 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from audex.config.helper.client.websocket import WebsocketClientConfig
6
+ from audex.config.helper.provider.dashscope import DashscopeCredentialConfig
7
+ from audex.helper.settings import BaseModel
8
+ from audex.helper.settings.fields import Field
9
+
10
+
11
+ class DashscopeTranscriptionSessionConfig(BaseModel):
12
+ fmt: t.Literal["pcm", "wav", "mp3", "opus", "speex", "aac", "amr"] = Field(
13
+ default="pcm",
14
+ description="Audio format for transcription session.",
15
+ )
16
+
17
+ silence_duration_ms: int | None = Field(
18
+ default=None,
19
+ description="Duration of silence in milliseconds to consider as end of speech.",
20
+ )
21
+
22
+ vocabulary_id: str | None = Field(
23
+ default=None,
24
+ description="Custom vocabulary ID for transcription.",
25
+ )
26
+
27
+ disfluency_removal_enabled: bool | None = Field(
28
+ default=None,
29
+ description="Enable disfluency removal in transcription.",
30
+ )
31
+
32
+ lang_hints: list[t.Literal["zh", "en", "ja", "yue", "ko", "de", "fr", "ru"]] | None = Field(
33
+ default=None,
34
+ description="Language hints for transcription.",
35
+ )
36
+
37
+ semantic_punctuation: bool | None = Field(
38
+ default=None,
39
+ description="Enable semantic punctuation in transcription.",
40
+ )
41
+
42
+ multi_thres_mode: bool | None = Field(
43
+ default=None,
44
+ description="Enable multi-threshold mode for transcription.",
45
+ )
46
+
47
+ punctuation_pred: bool | None = Field(
48
+ default=None,
49
+ description="Enable punctuation prediction in transcription.",
50
+ )
51
+
52
+ heartbeat: bool | None = Field(
53
+ default=None,
54
+ description="Enable heartbeat messages during transcription.",
55
+ )
56
+
57
+ itn: bool | None = Field(
58
+ default=None,
59
+ description="Enable inverse text normalization in transcription.",
60
+ )
61
+
62
+ resources: list[str] | None = Field(
63
+ default=None,
64
+ description="List of resource identifiers for transcription.",
65
+ )
66
+
67
+
68
+ class DashscopeTranscriptionConfig(BaseModel):
69
+ credential: DashscopeCredentialConfig = Field(
70
+ default_factory=DashscopeCredentialConfig,
71
+ description="Credentials for Dashscope API access.",
72
+ )
73
+
74
+ model: str = Field(
75
+ default="paraformer-realtime-v2",
76
+ description="Dashscope transcription model to use.",
77
+ )
78
+
79
+ user_agent: str | None = Field(
80
+ default=None,
81
+ description="Custom User-Agent header for API requests.",
82
+ )
83
+
84
+ workspace: str | None = Field(
85
+ default=None,
86
+ description="Workspace identifier for Dashscope service.",
87
+ )
88
+
89
+ websocket: WebsocketClientConfig = Field(
90
+ default_factory=WebsocketClientConfig,
91
+ description="WebSocket client configuration for Dashscope.",
92
+ )
93
+
94
+ session: DashscopeTranscriptionSessionConfig = Field(
95
+ default_factory=DashscopeTranscriptionSessionConfig,
96
+ description="Session configuration for Dashscope transcription.",
97
+ )
98
+
99
+
100
+ class TranscriptionConfig(BaseModel):
101
+ provider: t.Literal["dashscope"] = Field(
102
+ default="dashscope",
103
+ description="The transcription service provider.",
104
+ )
105
+
106
+ dashscope: DashscopeTranscriptionConfig = Field(
107
+ default_factory=DashscopeTranscriptionConfig,
108
+ description="Configuration for Dashscope transcription service.",
109
+ )
@@ -0,0 +1,99 @@
1
+ from __future__ import annotations
2
+
3
+ import contextlib
4
+ import os
5
+ import pathlib
6
+ import typing as t
7
+
8
+ from pydantic import model_validator
9
+
10
+ from audex.config.helper.client.http import HttpClientConfig
11
+ from audex.config.helper.provider.unisound import UnisoundCredentialConfig
12
+ from audex.config.helper.provider.xfyun import XFYunCredentialConfig
13
+ from audex.helper.settings import BaseModel
14
+ from audex.helper.settings.fields import Field
15
+
16
+
17
+ class XFYunVPRConfig(BaseModel):
18
+ credential: XFYunCredentialConfig = Field(
19
+ default_factory=XFYunCredentialConfig,
20
+ description="Credentials for XFYun VPR service.",
21
+ )
22
+
23
+ group_id: str | None = Field(
24
+ default=None,
25
+ description="The group ID for voiceprint recognition.",
26
+ )
27
+
28
+ group_id_path: os.PathLike[str] = Field(
29
+ default=pathlib.Path(".xf.vprgroup"),
30
+ description="The file path to read the group ID from if not provided directly.",
31
+ system_default=".xf.vprgroup",
32
+ system_path_type="config",
33
+ )
34
+
35
+ http: HttpClientConfig = Field(
36
+ default_factory=HttpClientConfig,
37
+ description="HTTP client configuration for XFYun VPR service.",
38
+ )
39
+
40
+ @model_validator(mode="after")
41
+ def load_group_id_from_file(self) -> t.Self:
42
+ if self.group_id is None:
43
+ with (
44
+ contextlib.suppress(FileNotFoundError),
45
+ pathlib.Path(self.group_id_path).open("r") as f,
46
+ ):
47
+ self.group_id = f.read().strip()
48
+ return self
49
+
50
+
51
+ class UnisoundVPRConfig(BaseModel):
52
+ credential: UnisoundCredentialConfig = Field(
53
+ default_factory=UnisoundCredentialConfig,
54
+ description="Credentials for Unisound VPR service.",
55
+ )
56
+
57
+ group_id: str | None = Field(
58
+ default=None,
59
+ description="The group ID for voiceprint recognition.",
60
+ )
61
+
62
+ group_id_path: os.PathLike[str] = Field(
63
+ default=pathlib.Path(".unisound.vprgroup"),
64
+ description="The file path to read the group ID from if not provided directly.",
65
+ system_default=".unisound.vprgroup",
66
+ system_path_type="config",
67
+ )
68
+
69
+ http: HttpClientConfig = Field(
70
+ default_factory=HttpClientConfig,
71
+ description="HTTP client configuration for Unisound VPR service.",
72
+ )
73
+
74
+ @model_validator(mode="after")
75
+ def load_group_id_from_file(self) -> t.Self:
76
+ if self.group_id is None:
77
+ with (
78
+ contextlib.suppress(FileNotFoundError),
79
+ pathlib.Path(self.group_id_path).open("r") as f,
80
+ ):
81
+ self.group_id = f.read().strip()
82
+ return self
83
+
84
+
85
+ class VPRConfig(BaseModel):
86
+ provider: t.Literal["xfyun", "unisound"] = Field(
87
+ default="xfyun",
88
+ description="The VPR service provider to use.",
89
+ )
90
+
91
+ xfyun: XFYunVPRConfig = Field(
92
+ default_factory=XFYunVPRConfig,
93
+ description="Configuration for the XFYun VPR service.",
94
+ )
95
+
96
+ unisound: UnisoundVPRConfig = Field(
97
+ default_factory=UnisoundVPRConfig,
98
+ description="Configuration for the Unisound VPR service.",
99
+ )
audex/container.py ADDED
@@ -0,0 +1,40 @@
1
+ from __future__ import annotations
2
+
3
+ from dependency_injector import containers
4
+ from dependency_injector import providers
5
+
6
+ from audex.injectors.config import config
7
+ from audex.injectors.lifespan import lifespan
8
+ from audex.lib.injectors.container import InfrastructureContainer
9
+ from audex.service.injectors.container import ServiceContainer
10
+ from audex.view.container import ViewContainer
11
+
12
+
13
+ class Container(containers.DeclarativeContainer):
14
+ # Configuration
15
+ config = providers.Callable(config)
16
+
17
+ # Containers
18
+ infrastructure = providers.Container(InfrastructureContainer, config=config)
19
+ service = providers.Container(
20
+ ServiceContainer,
21
+ config=config,
22
+ infrastructure=infrastructure,
23
+ repository=infrastructure.repository,
24
+ )
25
+
26
+ # Lifespan
27
+ lifespan = providers.Singleton(
28
+ lifespan,
29
+ config,
30
+ infrastructure.session_manager,
31
+ infrastructure.wifi,
32
+ infrastructure.cache,
33
+ infrastructure.sqlite,
34
+ infrastructure.vpr,
35
+ infrastructure.recorder,
36
+ infrastructure.transcription,
37
+ )
38
+
39
+ # Views
40
+ views = providers.Container(ViewContainer, config=config, service=service, lifespan=lifespan)