vocalstack 1.0.0a1__tar.gz → 1.0.0a3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vocalstack
3
- Version: 1.0.0a1
3
+ Version: 1.0.0a3
4
4
  Summary: VocalStack speech API SDK (asyncio): one client grouped by resource, typed models from the API contract, realtime WebSocket streaming.
5
5
  Project-URL: Homepage, https://vocalstack.com
6
6
  License-Expression: MIT
@@ -18,6 +18,8 @@ The VocalStack speech API for Python (3.10 or newer, asyncio): one client,
18
18
  are pydantic models generated from the API's one OpenAPI document
19
19
  (`/v1/openapi.json`), with snake_case attributes.
20
20
 
21
+ Read more about the [VocalStack Python SDK](https://vocalstack.com/#developers) and our other SDKs on the [VocalStack website](https://vocalstack.com/).
22
+
21
23
  ```python
22
24
  import asyncio, os
23
25
  from vocalstack import VocalStack
@@ -45,7 +47,8 @@ pip install vocalstack
45
47
 
46
48
  - [Quickstart](https://github.com/vocalstack/python-sdk/blob/main/docs/quickstart.md): An API key, the SDK, and your first transcript in a dozen lines.
47
49
  - [Transcribe a file](https://github.com/vocalstack/python-sdk/blob/main/docs/transcribe-a-file.md): Upload a file, wait for its job, read the transcript and export it. Asynchronous; nothing to keep open.
48
- - [Transcribe a link](https://github.com/vocalstack/python-sdk/blob/main/docs/transcribe-a-link.md): The server fetches a public URL or a YouTube video, then transcribes it like a file. Asynchronous, with a fetch phase first.
50
+ - [Transcribe a link](https://github.com/vocalstack/python-sdk/blob/main/docs/transcribe-a-link.md): The server fetches a public URL, a YouTube video or a recording on a video or audio site, then transcribes it like a file. Asynchronous, with a fetch phase first.
51
+ - [Search your transcriptions](https://github.com/vocalstack/python-sdk/blob/main/docs/search-transcriptions.md): Find transcriptions by words in their name or link, site, language, kind, tag and date, keep the shared ones, and play each with its share code.
49
52
  - [Stream a microphone](https://github.com/vocalstack/python-sdk/blob/main/docs/stream-a-microphone.md): Live audio in, transcript events out, over one WebSocket. Drafts replace the live tail; commits append.
50
53
  - [Stream a file at full speed](https://github.com/vocalstack/python-sdk/blob/main/docs/stream-a-file.md): Send a file's bytes through a realtime session and read the transcript as fast as the server makes it. Nothing is stored.
51
54
  - [Go live](https://github.com/vocalstack/python-sdk/blob/main/docs/go-live.md): Publish live audio to a stored transcription, and put it on a broadcast link listeners open. Control is HTTP; audio is one WebSocket.
@@ -5,6 +5,8 @@ The VocalStack speech API for Python (3.10 or newer, asyncio): one client,
5
5
  are pydantic models generated from the API's one OpenAPI document
6
6
  (`/v1/openapi.json`), with snake_case attributes.
7
7
 
8
+ Read more about the [VocalStack Python SDK](https://vocalstack.com/#developers) and our other SDKs on the [VocalStack website](https://vocalstack.com/).
9
+
8
10
  ```python
9
11
  import asyncio, os
10
12
  from vocalstack import VocalStack
@@ -32,7 +34,8 @@ pip install vocalstack
32
34
 
33
35
  - [Quickstart](https://github.com/vocalstack/python-sdk/blob/main/docs/quickstart.md): An API key, the SDK, and your first transcript in a dozen lines.
34
36
  - [Transcribe a file](https://github.com/vocalstack/python-sdk/blob/main/docs/transcribe-a-file.md): Upload a file, wait for its job, read the transcript and export it. Asynchronous; nothing to keep open.
35
- - [Transcribe a link](https://github.com/vocalstack/python-sdk/blob/main/docs/transcribe-a-link.md): The server fetches a public URL or a YouTube video, then transcribes it like a file. Asynchronous, with a fetch phase first.
37
+ - [Transcribe a link](https://github.com/vocalstack/python-sdk/blob/main/docs/transcribe-a-link.md): The server fetches a public URL, a YouTube video or a recording on a video or audio site, then transcribes it like a file. Asynchronous, with a fetch phase first.
38
+ - [Search your transcriptions](https://github.com/vocalstack/python-sdk/blob/main/docs/search-transcriptions.md): Find transcriptions by words in their name or link, site, language, kind, tag and date, keep the shared ones, and play each with its share code.
36
39
  - [Stream a microphone](https://github.com/vocalstack/python-sdk/blob/main/docs/stream-a-microphone.md): Live audio in, transcript events out, over one WebSocket. Drafts replace the live tail; commits append.
37
40
  - [Stream a file at full speed](https://github.com/vocalstack/python-sdk/blob/main/docs/stream-a-file.md): Send a file's bytes through a realtime session and read the transcript as fast as the server makes it. Nothing is stored.
38
41
  - [Go live](https://github.com/vocalstack/python-sdk/blob/main/docs/go-live.md): Publish live audio to a stored transcription, and put it on a broadcast link listeners open. Control is HTTP; audio is one WebSocket.
@@ -94,7 +94,9 @@ async def main(path): # mp3, wav, flac, ogg, m4a, mp4 ...
94
94
  async with VocalStack(os.environ.get("VOCALSTACK_BASE_URL"), api_key=os.environ["VOCALSTACK_API_KEY"]) as vs:
95
95
  tx = await vs.transcriptions.create(
96
96
  file=path, # a path, bytes, or an open binary file
97
- settings={"spokenLanguage": "en", "speakerLabels": "on"}, # both optional; "auto" | "on" | "off"
97
+ settings={"spokenLanguage": "en", "speakerLabels": "on"}, # both optional; "auto" (default) | "on" | "off"
98
+ # Off unless asked for: settings summary, title, summaryTranslations,
99
+ # voice (spoken translations), and share_link=True (a public share link).
98
100
  )
99
101
  job = await vs.jobs.wait(tx.job.recording_id)
100
102
  if job.state != "done":
@@ -180,6 +182,17 @@ async def main(q): # 2+ characters
180
182
  asyncio.run(main(sys.argv[1]))
181
183
  ```
182
184
 
185
+ By meaning, in any language, even with none of the words (vector search). Each
186
+ hit's `passage` is its whole paragraph: give the passages to your own model as
187
+ context to answer questions about what was said (RAG). Pay as you go counts 60
188
+ an hour (`allowance`); Premium and Enterprise have no limit.
189
+
190
+ ```python
191
+ res = await vs.search.vector("how much does housing cost")
192
+ for h in res.hits:
193
+ print(f"{h.similarity:.2f}", h.passage.media_start, h.passage.text)
194
+ ```
195
+
183
196
  ## Errors
184
197
 
185
198
  A failed call raises `vocalstack.VocalStackError` with `.code`, `.message`,
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "vocalstack"
7
- version = "1.0.0a1"
7
+ version = "1.0.0a3"
8
8
  description = "VocalStack speech API SDK (asyncio): one client grouped by resource, typed models from the API contract, realtime WebSocket streaming."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -22,11 +22,8 @@ Homepage = "https://vocalstack.com"
22
22
  [tool.hatch.build.targets.wheel]
23
23
  packages = ["src/vocalstack"]
24
24
 
25
- # The Agent Skill ships inside the package (site-packages/vocalstack/SKILL.md)
26
- # so an agent can find it next to the code.
27
25
  [tool.hatch.build.targets.wheel.force-include]
28
26
  "SKILL.md" = "vocalstack/SKILL.md"
29
27
 
30
- # An explicit list: nothing else from the repository goes into the sdist.
31
28
  [tool.hatch.build.targets.sdist]
32
29
  only-include = ["src/vocalstack", "LICENSE", "README.md", "SKILL.md", "skills", "pyproject.toml"]
@@ -94,7 +94,9 @@ async def main(path): # mp3, wav, flac, ogg, m4a, mp4 ...
94
94
  async with VocalStack(os.environ.get("VOCALSTACK_BASE_URL"), api_key=os.environ["VOCALSTACK_API_KEY"]) as vs:
95
95
  tx = await vs.transcriptions.create(
96
96
  file=path, # a path, bytes, or an open binary file
97
- settings={"spokenLanguage": "en", "speakerLabels": "on"}, # both optional; "auto" | "on" | "off"
97
+ settings={"spokenLanguage": "en", "speakerLabels": "on"}, # both optional; "auto" (default) | "on" | "off"
98
+ # Off unless asked for: settings summary, title, summaryTranslations,
99
+ # voice (spoken translations), and share_link=True (a public share link).
98
100
  )
99
101
  job = await vs.jobs.wait(tx.job.recording_id)
100
102
  if job.state != "done":
@@ -180,6 +182,17 @@ async def main(q): # 2+ characters
180
182
  asyncio.run(main(sys.argv[1]))
181
183
  ```
182
184
 
185
+ By meaning, in any language, even with none of the words (vector search). Each
186
+ hit's `passage` is its whole paragraph: give the passages to your own model as
187
+ context to answer questions about what was said (RAG). Pay as you go counts 60
188
+ an hour (`allowance`); Premium and Enterprise have no limit.
189
+
190
+ ```python
191
+ res = await vs.search.vector("how much does housing cost")
192
+ for h in res.hits:
193
+ print(f"{h.similarity:.2f}", h.passage.media_start, h.passage.text)
194
+ ```
195
+
183
196
  ## Errors
184
197
 
185
198
  A failed call raises `vocalstack.VocalStackError` with `.code`, `.message`,
@@ -30,7 +30,7 @@ from .errors import VocalStackError
30
30
  from .realtime import RealtimeTranscript
31
31
  from .realtime import RealtimeSession, pace_realtime
32
32
 
33
- __version__ = "1.0.0a1"
33
+ __version__ = "1.0.0a3"
34
34
 
35
35
  __all__ = [
36
36
  "DEFAULT_BASE_URL",
@@ -8,7 +8,7 @@ from typing import Any, Callable, Dict, Mapping, Optional, Union
8
8
 
9
9
  import httpx
10
10
 
11
- from .errors import from_envelope, from_oauth
11
+ from .errors import VocalStackError, from_envelope, from_oauth
12
12
 
13
13
  DEFAULT_BASE_URL = "https://api.vocalstack.com"
14
14
 
@@ -30,7 +30,6 @@ def listener_query(listener_token: Optional[str], share_code: Optional[str]) ->
30
30
  return {"listenerToken": listener_token, "shareCode": share_code}
31
31
 
32
32
 
33
- #: The wait before retrying ``503 unavailable`` when it names none.
34
33
  UNAVAILABLE_WAIT_S = 2.0
35
34
 
36
35
 
@@ -120,16 +119,19 @@ class Transport:
120
119
  h["idempotency-key"] = idempotency_key
121
120
  attempt = 0
122
121
  while True:
123
- resp = await self.http.request(
124
- method,
125
- self.url(path),
126
- params=_clean(query),
127
- json=json_body,
128
- files=files,
129
- data=data,
130
- headers=h,
131
- follow_redirects=False,
132
- )
122
+ try:
123
+ resp = await self.http.request(
124
+ method,
125
+ self.url(path),
126
+ params=_clean(query),
127
+ json=json_body,
128
+ files=files,
129
+ data=data,
130
+ headers=h,
131
+ follow_redirects=False,
132
+ )
133
+ except httpx.TransportError as e:
134
+ raise VocalStackError("unavailable", "could not reach the VocalStack API", retryable=True) from e
133
135
  if resp.status_code < 400:
134
136
  return resp
135
137
  body = None
@@ -152,7 +154,12 @@ class Transport:
152
154
  resp = await self.raw(method, path, **kw)
153
155
  if 300 <= resp.status_code < 400:
154
156
  return {"location": resp.headers.get("location")}
155
- return resp.json() if resp.content else None
157
+ if not resp.content:
158
+ return None
159
+ try:
160
+ return resp.json()
161
+ except (json.JSONDecodeError, ValueError) as e:
162
+ raise VocalStackError("internal", "the API answered with a body that is not JSON", status=resp.status_code, headers=resp.headers) from e
156
163
 
157
164
  async def aclose(self) -> None:
158
165
  if self.own_http: