vocalstack 1.0.0a2__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.
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/PKG-INFO +1 -3
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/README.md +0 -2
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/SKILL.md +1 -31
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/pyproject.toml +1 -1
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/skills/vocalstack/SKILL.md +1 -31
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/src/vocalstack/__init__.py +1 -1
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/src/vocalstack/_models.py +187 -236
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/src/vocalstack/client.py +0 -2
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/src/vocalstack/realtime.py +1 -1
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/src/vocalstack/resources.py +0 -109
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/.gitignore +0 -0
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/LICENSE +0 -0
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/src/vocalstack/_http.py +0 -0
- {vocalstack-1.0.0a2 → vocalstack-1.0.0a3}/src/vocalstack/errors.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vocalstack
|
|
3
|
-
Version: 1.0.
|
|
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
|
|
@@ -48,7 +48,6 @@ pip install vocalstack
|
|
|
48
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.
|
|
49
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.
|
|
50
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
|
-
- [Transcribe a batch of files](https://github.com/vocalstack/python-sdk/blob/main/docs/transcribe-a-batch.md): Send many files or links as one batch, start it once, and read every transcript when it is done. Cheaper than one transcription per file.
|
|
52
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.
|
|
53
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.
|
|
54
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.
|
|
@@ -69,7 +68,6 @@ pip install vocalstack
|
|
|
69
68
|
| transcription | a file, link, microphone or stream, transcribed and stored | `vs.transcriptions` |
|
|
70
69
|
| recording | one take inside a broadcast or a transcription | `vs.recordings` |
|
|
71
70
|
| job | a file or link recording's transcription work | `vs.jobs` |
|
|
72
|
-
| batch | many files transcribed together, for less than one transcription each | `vs.batches` |
|
|
73
71
|
|
|
74
72
|
The other groups: `vs.corrections`, `vs.share_links`, `vs.voices`,
|
|
75
73
|
`vs.search`, `vs.me`, `vs.languages`, `vs.rtmp`, `vs.events`, `vs.meta`.
|
|
@@ -35,7 +35,6 @@ pip install vocalstack
|
|
|
35
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.
|
|
36
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.
|
|
37
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
|
-
- [Transcribe a batch of files](https://github.com/vocalstack/python-sdk/blob/main/docs/transcribe-a-batch.md): Send many files or links as one batch, start it once, and read every transcript when it is done. Cheaper than one transcription per file.
|
|
39
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.
|
|
40
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.
|
|
41
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.
|
|
@@ -56,7 +55,6 @@ pip install vocalstack
|
|
|
56
55
|
| transcription | a file, link, microphone or stream, transcribed and stored | `vs.transcriptions` |
|
|
57
56
|
| recording | one take inside a broadcast or a transcription | `vs.recordings` |
|
|
58
57
|
| job | a file or link recording's transcription work | `vs.jobs` |
|
|
59
|
-
| batch | many files transcribed together, for less than one transcription each | `vs.batches` |
|
|
60
58
|
|
|
61
59
|
The other groups: `vs.corrections`, `vs.share_links`, `vs.voices`,
|
|
62
60
|
`vs.search`, `vs.me`, `vs.languages`, `vs.rtmp`, `vs.events`, `vs.meta`.
|
|
@@ -20,9 +20,6 @@ labels and translation. The `vocalstack` package has one asyncio client,
|
|
|
20
20
|
- A **job** is a file or link recording's transcription work:
|
|
21
21
|
`await vs.jobs.wait(recording_id)` polls it until it is `done` or `failed`
|
|
22
22
|
(`on_progress=lambda job: ...` sees each read: `job.state`, `job.progress.pct`).
|
|
23
|
-
- A **batch** is many files transcribed together for less than one
|
|
24
|
-
transcription each: `vs.batches.create()`, `add_file`/`add_url` per file,
|
|
25
|
-
`start`, then `wait` (section 6).
|
|
26
23
|
- A **broadcast** is a link listeners open to follow a live recording.
|
|
27
24
|
- A **realtime session** (`vs.realtime`) is a socket you stream audio into and
|
|
28
25
|
read the transcript from. Nothing is stored. "Session" means only this.
|
|
@@ -196,32 +193,6 @@ for h in res.hits:
|
|
|
196
193
|
print(f"{h.similarity:.2f}", h.passage.media_start, h.passage.text)
|
|
197
194
|
```
|
|
198
195
|
|
|
199
|
-
## 6. A batch of files
|
|
200
|
-
|
|
201
|
-
Many files at once cost less as a batch: one create, one minimum charge for
|
|
202
|
-
the whole batch. Its files get transcripts, exports and speaker labels (when
|
|
203
|
-
`settings.speakerLabels` asks), never a summary, title, share link or voices.
|
|
204
|
-
|
|
205
|
-
```python
|
|
206
|
-
import asyncio, os, sys
|
|
207
|
-
from vocalstack import VocalStack
|
|
208
|
-
|
|
209
|
-
async def main(paths):
|
|
210
|
-
async with VocalStack(os.environ.get("VOCALSTACK_BASE_URL"), api_key=os.environ["VOCALSTACK_API_KEY"]) as vs:
|
|
211
|
-
batch = await vs.batches.create(name="Interviews", settings={"spokenLanguage": "en"})
|
|
212
|
-
for path in paths:
|
|
213
|
-
await vs.batches.add_file(batch.id, file=path) # or add_url(batch.id, url)
|
|
214
|
-
await vs.batches.start(batch.id)
|
|
215
|
-
done = await vs.batches.wait(batch.id) # done (or stopped); check done.counts.failed
|
|
216
|
-
for tx in done.files or []:
|
|
217
|
-
if tx.job and tx.job.state == "done":
|
|
218
|
-
snap = await vs.recordings.transcript(tx.job.recording_id)
|
|
219
|
-
print(tx.name, " ".join(s.text for s in snap.sentences))
|
|
220
|
-
# vs.batches.export(batch.id, "srt") is every finished transcript in one zip.
|
|
221
|
-
|
|
222
|
-
asyncio.run(main(sys.argv[1:]))
|
|
223
|
-
```
|
|
224
|
-
|
|
225
196
|
## Errors
|
|
226
197
|
|
|
227
198
|
A failed call raises `vocalstack.VocalStackError` with `.code`, `.message`,
|
|
@@ -257,8 +228,7 @@ except VocalStackError as e:
|
|
|
257
228
|
- The other groups: `vs.transcriptions` (`list`, `get`, `update`, `archive`,
|
|
258
229
|
`restore`, `purge`, `list_share_links`, `create_share_link`), `vs.recordings`
|
|
259
230
|
(`get`, `summarize`, `summary`, `translation`, `audio_url`, `subscribe`),
|
|
260
|
-
`vs.
|
|
261
|
-
`export`, `stop`, `delete`), `vs.corrections`, `vs.share_links`, `vs.voices`, `vs.broadcasts`,
|
|
231
|
+
`vs.corrections`, `vs.share_links`, `vs.voices`, `vs.broadcasts`,
|
|
262
232
|
`vs.me` (`get`, `usage`), `vs.languages`, `vs.rtmp`, `vs.events`, `vs.meta`.
|
|
263
233
|
Each method is its operation's name in the OpenAPI document, in snake_case
|
|
264
234
|
(`transcriptions.create` is `POST /v1/transcriptions`).
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vocalstack"
|
|
7
|
-
version = "1.0.
|
|
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"
|
|
@@ -20,9 +20,6 @@ labels and translation. The `vocalstack` package has one asyncio client,
|
|
|
20
20
|
- A **job** is a file or link recording's transcription work:
|
|
21
21
|
`await vs.jobs.wait(recording_id)` polls it until it is `done` or `failed`
|
|
22
22
|
(`on_progress=lambda job: ...` sees each read: `job.state`, `job.progress.pct`).
|
|
23
|
-
- A **batch** is many files transcribed together for less than one
|
|
24
|
-
transcription each: `vs.batches.create()`, `add_file`/`add_url` per file,
|
|
25
|
-
`start`, then `wait` (section 6).
|
|
26
23
|
- A **broadcast** is a link listeners open to follow a live recording.
|
|
27
24
|
- A **realtime session** (`vs.realtime`) is a socket you stream audio into and
|
|
28
25
|
read the transcript from. Nothing is stored. "Session" means only this.
|
|
@@ -196,32 +193,6 @@ for h in res.hits:
|
|
|
196
193
|
print(f"{h.similarity:.2f}", h.passage.media_start, h.passage.text)
|
|
197
194
|
```
|
|
198
195
|
|
|
199
|
-
## 6. A batch of files
|
|
200
|
-
|
|
201
|
-
Many files at once cost less as a batch: one create, one minimum charge for
|
|
202
|
-
the whole batch. Its files get transcripts, exports and speaker labels (when
|
|
203
|
-
`settings.speakerLabels` asks), never a summary, title, share link or voices.
|
|
204
|
-
|
|
205
|
-
```python
|
|
206
|
-
import asyncio, os, sys
|
|
207
|
-
from vocalstack import VocalStack
|
|
208
|
-
|
|
209
|
-
async def main(paths):
|
|
210
|
-
async with VocalStack(os.environ.get("VOCALSTACK_BASE_URL"), api_key=os.environ["VOCALSTACK_API_KEY"]) as vs:
|
|
211
|
-
batch = await vs.batches.create(name="Interviews", settings={"spokenLanguage": "en"})
|
|
212
|
-
for path in paths:
|
|
213
|
-
await vs.batches.add_file(batch.id, file=path) # or add_url(batch.id, url)
|
|
214
|
-
await vs.batches.start(batch.id)
|
|
215
|
-
done = await vs.batches.wait(batch.id) # done (or stopped); check done.counts.failed
|
|
216
|
-
for tx in done.files or []:
|
|
217
|
-
if tx.job and tx.job.state == "done":
|
|
218
|
-
snap = await vs.recordings.transcript(tx.job.recording_id)
|
|
219
|
-
print(tx.name, " ".join(s.text for s in snap.sentences))
|
|
220
|
-
# vs.batches.export(batch.id, "srt") is every finished transcript in one zip.
|
|
221
|
-
|
|
222
|
-
asyncio.run(main(sys.argv[1:]))
|
|
223
|
-
```
|
|
224
|
-
|
|
225
196
|
## Errors
|
|
226
197
|
|
|
227
198
|
A failed call raises `vocalstack.VocalStackError` with `.code`, `.message`,
|
|
@@ -257,8 +228,7 @@ except VocalStackError as e:
|
|
|
257
228
|
- The other groups: `vs.transcriptions` (`list`, `get`, `update`, `archive`,
|
|
258
229
|
`restore`, `purge`, `list_share_links`, `create_share_link`), `vs.recordings`
|
|
259
230
|
(`get`, `summarize`, `summary`, `translation`, `audio_url`, `subscribe`),
|
|
260
|
-
`vs.
|
|
261
|
-
`export`, `stop`, `delete`), `vs.corrections`, `vs.share_links`, `vs.voices`, `vs.broadcasts`,
|
|
231
|
+
`vs.corrections`, `vs.share_links`, `vs.voices`, `vs.broadcasts`,
|
|
262
232
|
`vs.me` (`get`, `usage`), `vs.languages`, `vs.rtmp`, `vs.events`, `vs.meta`.
|
|
263
233
|
Each method is its operation's name in the OpenAPI document, in snake_case
|
|
264
234
|
(`transcriptions.create` is `POST /v1/transcriptions`).
|
|
@@ -26,12 +26,6 @@ AudioSourceState = Literal["ready", "error"]
|
|
|
26
26
|
|
|
27
27
|
RecordingState = Literal["pending", "live", "paused", "processing", "ended", "finalized"]
|
|
28
28
|
|
|
29
|
-
QueueReason = Literal["concurrency"]
|
|
30
|
-
|
|
31
|
-
SourceKind = Literal["file", "url"]
|
|
32
|
-
|
|
33
|
-
JobState = Literal["queued", "fetching", "transcribing", "done", "failed", "cropping", "stopped"]
|
|
34
|
-
|
|
35
29
|
Lifecycle = Literal["active", "archived", "purged"]
|
|
36
30
|
|
|
37
31
|
LatencyMode = Literal["auto", "fast", "accuracy"]
|
|
@@ -58,6 +52,10 @@ IngestState = Literal["connecting", "streaming", "reconnecting", "stopped", "fai
|
|
|
58
52
|
|
|
59
53
|
InputKind = Literal["live", "file", "url", "stream"]
|
|
60
54
|
|
|
55
|
+
QueueReason = Literal["concurrency"]
|
|
56
|
+
|
|
57
|
+
JobState = Literal["queued", "fetching", "transcribing", "done", "failed", "cropping", "stopped"]
|
|
58
|
+
|
|
61
59
|
LanguageStatusState = Literal["matches", "mismatch", "unknown", "change_unsupported"]
|
|
62
60
|
|
|
63
61
|
LinkKind = Literal["live", "file", "unknown"]
|
|
@@ -68,6 +66,8 @@ LoadingStage = Literal["download", "model"]
|
|
|
68
66
|
|
|
69
67
|
RecordingKind = Literal["live", "upload"]
|
|
70
68
|
|
|
69
|
+
SourceKind = Literal["file", "url"]
|
|
70
|
+
|
|
71
71
|
PullState = Literal["connecting", "streaming", "reconnecting", "failed"]
|
|
72
72
|
|
|
73
73
|
SentenceStatus = Literal["open", "closed", "dropped"]
|
|
@@ -236,225 +236,6 @@ class AutoTopUpView(_Base):
|
|
|
236
236
|
threshold: Optional[float] = None
|
|
237
237
|
|
|
238
238
|
|
|
239
|
-
class BatchCounts(_Base):
|
|
240
|
-
"""How many of a batch's files are in each state."""
|
|
241
|
-
|
|
242
|
-
done: int
|
|
243
|
-
failed: int
|
|
244
|
-
queued: int
|
|
245
|
-
running: int
|
|
246
|
-
stopped: int
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
class Blocked(_Base):
|
|
250
|
-
at: str
|
|
251
|
-
contact: str
|
|
252
|
-
reason: str
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
class BroadcastRef(_Base):
|
|
256
|
-
"""A broadcast a live transcription feeds (`Transcription.broadcasts`)."""
|
|
257
|
-
|
|
258
|
-
access: Access
|
|
259
|
-
code: str
|
|
260
|
-
id: str
|
|
261
|
-
name: str
|
|
262
|
-
share_url: str = Field(alias="shareUrl")
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
class CurrentRecording(_Base):
|
|
266
|
-
"""The recording in flight (`currentRecording`): on a transcription, its
|
|
267
|
-
open recording; on a broadcast, the open recording
|
|
268
|
-
of a live transcription feeding it, which is what its listeners are sent."""
|
|
269
|
-
|
|
270
|
-
recording_id: str = Field(alias="recordingId")
|
|
271
|
-
started_at: Optional[str] = Field(default=None, alias="startedAt")
|
|
272
|
-
state: RecordingState
|
|
273
|
-
transcription_id: Optional[str] = Field(default=None, alias="transcriptionId")
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
class CropWindow(_Base):
|
|
277
|
-
"""A window of the source, in seconds into it. `end_s` absent = to the end."""
|
|
278
|
-
|
|
279
|
-
end_s: Optional[float] = Field(default=None, alias="endS")
|
|
280
|
-
start_s: float = Field(alias="startS")
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
class JobProgress(_Base):
|
|
284
|
-
fetch_total_bytes: Optional[int] = Field(default=None, alias="fetchTotalBytes")
|
|
285
|
-
fetched_bytes: Optional[int] = Field(default=None, alias="fetchedBytes")
|
|
286
|
-
pct: int
|
|
287
|
-
phase: Optional[str] = None
|
|
288
|
-
phase_pct: Optional[int] = Field(default=None, alias="phasePct")
|
|
289
|
-
processed_s: float = Field(alias="processedS")
|
|
290
|
-
segments_done: int = Field(alias="segmentsDone")
|
|
291
|
-
segments_total: Optional[int] = Field(default=None, alias="segmentsTotal")
|
|
292
|
-
total_s: Optional[float] = Field(default=None, alias="totalS")
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
class JobQueue(_Base):
|
|
296
|
-
"""Why a `queued` job is waiting, and where it stands (`Job.queue`)."""
|
|
297
|
-
|
|
298
|
-
position: int
|
|
299
|
-
reason: QueueReason
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
class SourceInfo(_Base):
|
|
303
|
-
"""What the recording was made from (design `j.meta`: "M4A · 34.2 MB",
|
|
304
|
-
"Video URL")."""
|
|
305
|
-
|
|
306
|
-
bytes: Optional[int] = None
|
|
307
|
-
duration_s: Optional[float] = Field(default=None, alias="durationS")
|
|
308
|
-
embed_id: Optional[str] = Field(default=None, alias="embedId")
|
|
309
|
-
format: Optional[str] = None
|
|
310
|
-
kind: SourceKind
|
|
311
|
-
mime: Optional[str] = None
|
|
312
|
-
name: str
|
|
313
|
-
site: Optional[str] = None
|
|
314
|
-
thumbnail_url: Optional[str] = Field(default=None, alias="thumbnailUrl")
|
|
315
|
-
url: Optional[str] = None
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
class TranscriptionJob(_Base):
|
|
319
|
-
attempts: int
|
|
320
|
-
created_at: str = Field(alias="createdAt")
|
|
321
|
-
crop: Optional["CropWindow"] = None
|
|
322
|
-
error: Optional[str] = None
|
|
323
|
-
error_code: Optional[str] = Field(default=None, alias="errorCode")
|
|
324
|
-
finished_at: Optional[str] = Field(default=None, alias="finishedAt")
|
|
325
|
-
has_audio: bool = Field(alias="hasAudio")
|
|
326
|
-
has_video: Optional[bool] = Field(default=None, alias="hasVideo")
|
|
327
|
-
peaks: Optional[List[float]] = None
|
|
328
|
-
preview: Optional[bool] = None
|
|
329
|
-
progress: "JobProgress"
|
|
330
|
-
queue: Optional["JobQueue"] = None
|
|
331
|
-
recording_id: str = Field(alias="recordingId")
|
|
332
|
-
source: Optional["SourceInfo"] = None
|
|
333
|
-
started_at: Optional[str] = Field(default=None, alias="startedAt")
|
|
334
|
-
state: JobState
|
|
335
|
-
transcription_id: str = Field(alias="transcriptionId")
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
class LastRecording(_Base):
|
|
339
|
-
"""A live transcription's newest recording (`lastRecording`): what
|
|
340
|
-
its row in a list reads from — how long it ran, when, and whether it is
|
|
341
|
-
still running — and the recording a tap on that row opens."""
|
|
342
|
-
|
|
343
|
-
duration_s: Optional[float] = Field(default=None, alias="durationS")
|
|
344
|
-
recording_id: str = Field(alias="recordingId")
|
|
345
|
-
started_at: Optional[str] = Field(default=None, alias="startedAt")
|
|
346
|
-
state: RecordingState
|
|
347
|
-
title: Optional[str] = None
|
|
348
|
-
transcription_id: Optional[str] = Field(default=None, alias="transcriptionId")
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
class ConfidencePolicy(_Base):
|
|
352
|
-
"""Env defaults, overridden per broadcast, transcription or recording."""
|
|
353
|
-
|
|
354
|
-
hide_below: Optional[float] = Field(default=None, alias="hideBelow")
|
|
355
|
-
low_threshold: Optional[float] = Field(default=None, alias="lowThreshold")
|
|
356
|
-
suppress_count: Optional[int] = Field(default=None, alias="suppressCount")
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
class Settings(_Base):
|
|
360
|
-
"""A broadcast's, transcription's or recording's capture settings (the
|
|
361
|
-
design's settings sheet): what a recording made in it starts with."""
|
|
362
|
-
|
|
363
|
-
confidence: Optional["ConfidencePolicy"] = None
|
|
364
|
-
latency_mode: Optional[LatencyMode] = Field(default=None, alias="latencyMode")
|
|
365
|
-
max_duration_s: Optional[int] = Field(default=None, alias="maxDurationS")
|
|
366
|
-
max_pause_s: Optional[int] = Field(default=None, alias="maxPauseS")
|
|
367
|
-
silence_auto_pause_s: Optional[int] = Field(default=None, alias="silenceAutoPauseS")
|
|
368
|
-
speaker_labels: Optional[SpeakerLabels] = Field(default=None, alias="speakerLabels")
|
|
369
|
-
spoken_language: Optional[str] = Field(default=None, alias="spokenLanguage")
|
|
370
|
-
summary: Optional[bool] = None
|
|
371
|
-
summary_translations: Optional[bool] = Field(default=None, alias="summaryTranslations")
|
|
372
|
-
title: Optional[bool] = None
|
|
373
|
-
voice: Optional[bool] = None
|
|
374
|
-
voice_by_lang: Optional[Dict[str, str]] = Field(default=None, alias="voiceByLang")
|
|
375
|
-
voice_cloning: Optional[bool] = Field(default=None, alias="voiceCloning")
|
|
376
|
-
voice_cloning_consent: Optional[bool] = Field(default=None, alias="voiceCloningConsent")
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
class TagRef(_Base):
|
|
380
|
-
"""A tag as a transcription lists it."""
|
|
381
|
-
|
|
382
|
-
color: Literal["coral", "amber", "lime", "green", "teal", "blue", "violet", "pink"]
|
|
383
|
-
id: str
|
|
384
|
-
name: str
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
class Transcription(_Base):
|
|
388
|
-
"""A transcription: a file, a link (with its `transcription` job), or
|
|
389
|
-
something captured as it is spoken (`live: true`: a microphone, a
|
|
390
|
-
stream, an RTMP encoder), which may feed broadcasts (`broadcasts`)."""
|
|
391
|
-
|
|
392
|
-
archived_at: Optional[str] = Field(default=None, alias="archivedAt")
|
|
393
|
-
batch_id: Optional[str] = Field(default=None, alias="batchId")
|
|
394
|
-
blocked: Optional["Blocked"] = None
|
|
395
|
-
broadcasts: Optional[List["BroadcastRef"]] = None
|
|
396
|
-
code: str
|
|
397
|
-
created_at: str = Field(alias="createdAt")
|
|
398
|
-
created_by_api_key_id: Optional[str] = Field(default=None, alias="createdByApiKeyId")
|
|
399
|
-
current_recording: Optional["CurrentRecording"] = Field(default=None, alias="currentRecording")
|
|
400
|
-
id: str
|
|
401
|
-
job: Optional["TranscriptionJob"] = None
|
|
402
|
-
kind: Literal["transcription"] = "transcription"
|
|
403
|
-
last_recorded_at: Optional[str] = Field(default=None, alias="lastRecordedAt")
|
|
404
|
-
last_recording: Optional["LastRecording"] = Field(default=None, alias="lastRecording")
|
|
405
|
-
lifecycle: Lifecycle
|
|
406
|
-
live: Optional[bool] = None
|
|
407
|
-
locked: Optional[bool] = None
|
|
408
|
-
name: str
|
|
409
|
-
origin: Literal["dashboard", "api", "extension", "desktop_app", "obs", "wordpress", "payload", "strapi", "sanity", "contentful", "mcp", "batch_api", "broadcast", "unknown"]
|
|
410
|
-
owner_principal_id: str = Field(alias="ownerPrincipalId")
|
|
411
|
-
purge_after: Optional[str] = Field(default=None, alias="purgeAfter")
|
|
412
|
-
recording_count: int = Field(alias="recordingCount")
|
|
413
|
-
settings: "Settings"
|
|
414
|
-
share_code: Optional[str] = Field(default=None, alias="shareCode")
|
|
415
|
-
share_url: str = Field(alias="shareUrl")
|
|
416
|
-
source: "CaptureSource"
|
|
417
|
-
tags: Optional[List["TagRef"]] = None
|
|
418
|
-
updated_at: str = Field(alias="updatedAt")
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
class BatchSettings(_Base):
|
|
422
|
-
"""What every file of a batch runs with. Summary, title, voices and the
|
|
423
|
-
share link are never made for a batch file, so they are not here.
|
|
424
|
-
Voice cloning is (design 120: the New transcription form asks it for
|
|
425
|
-
every file it starts, one file or several)."""
|
|
426
|
-
|
|
427
|
-
latency_mode: Optional[LatencyMode] = Field(default=None, alias="latencyMode")
|
|
428
|
-
speaker_labels: Optional[SpeakerLabels] = Field(default=None, alias="speakerLabels")
|
|
429
|
-
spoken_language: Optional[str] = Field(default=None, alias="spokenLanguage")
|
|
430
|
-
voice_cloning: Optional[bool] = Field(default=None, alias="voiceCloning")
|
|
431
|
-
voice_cloning_consent: Optional[bool] = Field(default=None, alias="voiceCloningConsent")
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
class Batch(_Base):
|
|
435
|
-
"""A batch of files."""
|
|
436
|
-
|
|
437
|
-
counts: "BatchCounts"
|
|
438
|
-
created_at: str = Field(alias="createdAt")
|
|
439
|
-
created_by_api_key_id: Optional[str] = Field(default=None, alias="createdByApiKeyId")
|
|
440
|
-
file_count: int = Field(alias="fileCount")
|
|
441
|
-
files: Optional[List["Transcription"]] = None
|
|
442
|
-
files_per_batch: Optional[int] = Field(default=None, alias="filesPerBatch")
|
|
443
|
-
finished_at: Optional[str] = Field(default=None, alias="finishedAt")
|
|
444
|
-
id: str
|
|
445
|
-
name: str
|
|
446
|
-
settings: "BatchSettings"
|
|
447
|
-
started_at: Optional[str] = Field(default=None, alias="startedAt")
|
|
448
|
-
state: str
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
class BatchPage(_Base):
|
|
452
|
-
"""`GET /v1/batches`: one page, newest first."""
|
|
453
|
-
|
|
454
|
-
batches: List["Batch"]
|
|
455
|
-
next_cursor: Optional[str] = Field(default=None, alias="nextCursor")
|
|
456
|
-
|
|
457
|
-
|
|
458
239
|
class BillingDetails(_Base):
|
|
459
240
|
"""`GET / PUT /v1/billing/details`."""
|
|
460
241
|
|
|
@@ -488,7 +269,6 @@ class Limits2(_Base):
|
|
|
488
269
|
concurrent_transcriptions: Optional[int] = Field(default=None, alias="concurrentTranscriptions")
|
|
489
270
|
creates_per_hour: Optional[int] = Field(default=None, alias="createsPerHour")
|
|
490
271
|
creates_per_hour_unpaid: Optional[int] = Field(default=None, alias="createsPerHourUnpaid")
|
|
491
|
-
files_per_batch: Optional[int] = Field(default=None, alias="filesPerBatch")
|
|
492
272
|
max_file_bytes: Optional[int] = Field(default=None, alias="maxFileBytes")
|
|
493
273
|
max_live_seconds: Optional[int] = Field(default=None, alias="maxLiveSeconds")
|
|
494
274
|
questions_per_day: Optional[int] = Field(default=None, alias="questionsPerDay")
|
|
@@ -533,7 +313,6 @@ class Rates(_Base):
|
|
|
533
313
|
"""The rate card of a version: dollars per hour, and the least a
|
|
534
314
|
transcription is billed."""
|
|
535
315
|
|
|
536
|
-
batch_file_minimum_seconds: Optional[int] = Field(default=None, alias="batchFileMinimumSeconds")
|
|
537
316
|
file_per_hour: float = Field(alias="filePerHour")
|
|
538
317
|
live_per_hour: float = Field(alias="livePerHour")
|
|
539
318
|
minimum_seconds: int = Field(alias="minimumSeconds")
|
|
@@ -646,6 +425,64 @@ running transcriptions go on below zero, never how far."""
|
|
|
646
425
|
top_up_url: str = Field(alias="topUpUrl")
|
|
647
426
|
|
|
648
427
|
|
|
428
|
+
class Blocked(_Base):
|
|
429
|
+
at: str
|
|
430
|
+
contact: str
|
|
431
|
+
reason: str
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
class CurrentRecording(_Base):
|
|
435
|
+
"""The recording in flight (`currentRecording`): on a transcription, its
|
|
436
|
+
open recording; on a broadcast, the open recording
|
|
437
|
+
of a live transcription feeding it, which is what its listeners are sent."""
|
|
438
|
+
|
|
439
|
+
recording_id: str = Field(alias="recordingId")
|
|
440
|
+
started_at: Optional[str] = Field(default=None, alias="startedAt")
|
|
441
|
+
state: RecordingState
|
|
442
|
+
transcription_id: Optional[str] = Field(default=None, alias="transcriptionId")
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
class LastRecording(_Base):
|
|
446
|
+
"""A live transcription's newest recording (`lastRecording`): what
|
|
447
|
+
its row in a list reads from — how long it ran, when, and whether it is
|
|
448
|
+
still running — and the recording a tap on that row opens."""
|
|
449
|
+
|
|
450
|
+
duration_s: Optional[float] = Field(default=None, alias="durationS")
|
|
451
|
+
recording_id: str = Field(alias="recordingId")
|
|
452
|
+
started_at: Optional[str] = Field(default=None, alias="startedAt")
|
|
453
|
+
state: RecordingState
|
|
454
|
+
title: Optional[str] = None
|
|
455
|
+
transcription_id: Optional[str] = Field(default=None, alias="transcriptionId")
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
class ConfidencePolicy(_Base):
|
|
459
|
+
"""Env defaults, overridden per broadcast, transcription or recording."""
|
|
460
|
+
|
|
461
|
+
hide_below: Optional[float] = Field(default=None, alias="hideBelow")
|
|
462
|
+
low_threshold: Optional[float] = Field(default=None, alias="lowThreshold")
|
|
463
|
+
suppress_count: Optional[int] = Field(default=None, alias="suppressCount")
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
class Settings(_Base):
|
|
467
|
+
"""A broadcast's, transcription's or recording's capture settings (the
|
|
468
|
+
design's settings sheet): what a recording made in it starts with."""
|
|
469
|
+
|
|
470
|
+
confidence: Optional["ConfidencePolicy"] = None
|
|
471
|
+
latency_mode: Optional[LatencyMode] = Field(default=None, alias="latencyMode")
|
|
472
|
+
max_duration_s: Optional[int] = Field(default=None, alias="maxDurationS")
|
|
473
|
+
max_pause_s: Optional[int] = Field(default=None, alias="maxPauseS")
|
|
474
|
+
silence_auto_pause_s: Optional[int] = Field(default=None, alias="silenceAutoPauseS")
|
|
475
|
+
speaker_labels: Optional[SpeakerLabels] = Field(default=None, alias="speakerLabels")
|
|
476
|
+
spoken_language: Optional[str] = Field(default=None, alias="spokenLanguage")
|
|
477
|
+
summary: Optional[bool] = None
|
|
478
|
+
summary_translations: Optional[bool] = Field(default=None, alias="summaryTranslations")
|
|
479
|
+
title: Optional[bool] = None
|
|
480
|
+
voice: Optional[bool] = None
|
|
481
|
+
voice_by_lang: Optional[Dict[str, str]] = Field(default=None, alias="voiceByLang")
|
|
482
|
+
voice_cloning: Optional[bool] = Field(default=None, alias="voiceCloning")
|
|
483
|
+
voice_cloning_consent: Optional[bool] = Field(default=None, alias="voiceCloningConsent")
|
|
484
|
+
|
|
485
|
+
|
|
649
486
|
class TranscriptionRef(_Base):
|
|
650
487
|
"""A live transcription feeding a broadcast (`Broadcast.transcriptions`)."""
|
|
651
488
|
|
|
@@ -686,6 +523,16 @@ those live transcriptions."""
|
|
|
686
523
|
updated_at: str = Field(alias="updatedAt")
|
|
687
524
|
|
|
688
525
|
|
|
526
|
+
class BroadcastRef(_Base):
|
|
527
|
+
"""A broadcast a live transcription feeds (`Transcription.broadcasts`)."""
|
|
528
|
+
|
|
529
|
+
access: Access
|
|
530
|
+
code: str
|
|
531
|
+
id: str
|
|
532
|
+
name: str
|
|
533
|
+
share_url: str = Field(alias="shareUrl")
|
|
534
|
+
|
|
535
|
+
|
|
689
536
|
class Limits(_Base):
|
|
690
537
|
audio_buffer_s: int = Field(alias="audioBufferS")
|
|
691
538
|
max_duration_s: int = Field(alias="maxDurationS")
|
|
@@ -862,13 +709,6 @@ class CreateAudioSource(_Base):
|
|
|
862
709
|
url: str
|
|
863
710
|
|
|
864
711
|
|
|
865
|
-
class CreateBatch(_Base):
|
|
866
|
-
"""`POST /v1/batches`."""
|
|
867
|
-
|
|
868
|
-
name: Optional[str] = None
|
|
869
|
-
settings: Optional["BatchSettings"] = None
|
|
870
|
-
|
|
871
|
-
|
|
872
712
|
class CreateBroadcast(_Base):
|
|
873
713
|
"""`POST /v1/broadcasts`."""
|
|
874
714
|
|
|
@@ -999,6 +839,13 @@ class CropRange(_Base):
|
|
|
999
839
|
start_s: Optional[float] = Field(default=None, alias="startS")
|
|
1000
840
|
|
|
1001
841
|
|
|
842
|
+
class CropWindow(_Base):
|
|
843
|
+
"""A window of the source, in seconds into it. `end_s` absent = to the end."""
|
|
844
|
+
|
|
845
|
+
end_s: Optional[float] = Field(default=None, alias="endS")
|
|
846
|
+
start_s: float = Field(alias="startS")
|
|
847
|
+
|
|
848
|
+
|
|
1002
849
|
class DraftSegment(_Base):
|
|
1003
850
|
speaker: int
|
|
1004
851
|
start: float
|
|
@@ -1031,6 +878,25 @@ class InputOptions(_Base):
|
|
|
1031
878
|
url: Optional[str] = None
|
|
1032
879
|
|
|
1033
880
|
|
|
881
|
+
class JobProgress(_Base):
|
|
882
|
+
fetch_total_bytes: Optional[int] = Field(default=None, alias="fetchTotalBytes")
|
|
883
|
+
fetched_bytes: Optional[int] = Field(default=None, alias="fetchedBytes")
|
|
884
|
+
pct: int
|
|
885
|
+
phase: Optional[str] = None
|
|
886
|
+
phase_pct: Optional[int] = Field(default=None, alias="phasePct")
|
|
887
|
+
processed_s: float = Field(alias="processedS")
|
|
888
|
+
segments_done: int = Field(alias="segmentsDone")
|
|
889
|
+
segments_total: Optional[int] = Field(default=None, alias="segmentsTotal")
|
|
890
|
+
total_s: Optional[float] = Field(default=None, alias="totalS")
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
class JobQueue(_Base):
|
|
894
|
+
"""Why a `queued` job is waiting, and where it stands (`Job.queue`)."""
|
|
895
|
+
|
|
896
|
+
position: int
|
|
897
|
+
reason: QueueReason
|
|
898
|
+
|
|
899
|
+
|
|
1034
900
|
class KnownVoice(_Base):
|
|
1035
901
|
"""One voice a realtime session may recognise a speaker as.
|
|
1036
902
|
|
|
@@ -1309,6 +1175,22 @@ class PublisherInfo(_Base):
|
|
|
1309
1175
|
machine_id: Optional[str] = Field(default=None, alias="machineId")
|
|
1310
1176
|
|
|
1311
1177
|
|
|
1178
|
+
class SourceInfo(_Base):
|
|
1179
|
+
"""What the recording was made from (design `j.meta`: "M4A · 34.2 MB",
|
|
1180
|
+
"Video URL")."""
|
|
1181
|
+
|
|
1182
|
+
bytes: Optional[int] = None
|
|
1183
|
+
duration_s: Optional[float] = Field(default=None, alias="durationS")
|
|
1184
|
+
embed_id: Optional[str] = Field(default=None, alias="embedId")
|
|
1185
|
+
format: Optional[str] = None
|
|
1186
|
+
kind: SourceKind
|
|
1187
|
+
mime: Optional[str] = None
|
|
1188
|
+
name: str
|
|
1189
|
+
site: Optional[str] = None
|
|
1190
|
+
thumbnail_url: Optional[str] = Field(default=None, alias="thumbnailUrl")
|
|
1191
|
+
url: Optional[str] = None
|
|
1192
|
+
|
|
1193
|
+
|
|
1312
1194
|
class Recording(_Base):
|
|
1313
1195
|
created_at: str = Field(alias="createdAt")
|
|
1314
1196
|
end_reason: Optional[str] = Field(default=None, alias="endReason")
|
|
@@ -1551,6 +1433,26 @@ Flattened into its owner."""
|
|
|
1551
1433
|
views: int
|
|
1552
1434
|
|
|
1553
1435
|
|
|
1436
|
+
class TranscriptionJob(_Base):
|
|
1437
|
+
attempts: int
|
|
1438
|
+
created_at: str = Field(alias="createdAt")
|
|
1439
|
+
crop: Optional["CropWindow"] = None
|
|
1440
|
+
error: Optional[str] = None
|
|
1441
|
+
error_code: Optional[str] = Field(default=None, alias="errorCode")
|
|
1442
|
+
finished_at: Optional[str] = Field(default=None, alias="finishedAt")
|
|
1443
|
+
has_audio: bool = Field(alias="hasAudio")
|
|
1444
|
+
has_video: Optional[bool] = Field(default=None, alias="hasVideo")
|
|
1445
|
+
peaks: Optional[List[float]] = None
|
|
1446
|
+
preview: Optional[bool] = None
|
|
1447
|
+
progress: "JobProgress"
|
|
1448
|
+
queue: Optional["JobQueue"] = None
|
|
1449
|
+
recording_id: str = Field(alias="recordingId")
|
|
1450
|
+
source: Optional["SourceInfo"] = None
|
|
1451
|
+
started_at: Optional[str] = Field(default=None, alias="startedAt")
|
|
1452
|
+
state: JobState
|
|
1453
|
+
transcription_id: str = Field(alias="transcriptionId")
|
|
1454
|
+
|
|
1455
|
+
|
|
1554
1456
|
class SharedTranscript(_Base):
|
|
1555
1457
|
"""What the public page learns from a code: the transcript's name, who
|
|
1556
1458
|
shared it (display name only), what the link allows, and the recording
|
|
@@ -1624,6 +1526,14 @@ class TagList(_Base):
|
|
|
1624
1526
|
tags: List["Tag"]
|
|
1625
1527
|
|
|
1626
1528
|
|
|
1529
|
+
class TagRef(_Base):
|
|
1530
|
+
"""A tag as a transcription lists it."""
|
|
1531
|
+
|
|
1532
|
+
color: Literal["coral", "amber", "lime", "green", "teal", "blue", "violet", "pink"]
|
|
1533
|
+
id: str
|
|
1534
|
+
name: str
|
|
1535
|
+
|
|
1536
|
+
|
|
1627
1537
|
class TagTranscriptions(_Base):
|
|
1628
1538
|
"""Transcriptions to put the tag on and to take it off, by id."""
|
|
1629
1539
|
|
|
@@ -1644,6 +1554,39 @@ class TranscriptSnapshot(_Base):
|
|
|
1644
1554
|
translation_pending: Optional[bool] = Field(default=None, alias="translationPending")
|
|
1645
1555
|
|
|
1646
1556
|
|
|
1557
|
+
class Transcription(_Base):
|
|
1558
|
+
"""A transcription: a file, a link (with its `transcription` job), or
|
|
1559
|
+
something captured as it is spoken (`live: true`: a microphone, a
|
|
1560
|
+
stream, an RTMP encoder), which may feed broadcasts (`broadcasts`)."""
|
|
1561
|
+
|
|
1562
|
+
archived_at: Optional[str] = Field(default=None, alias="archivedAt")
|
|
1563
|
+
blocked: Optional["Blocked"] = None
|
|
1564
|
+
broadcasts: Optional[List["BroadcastRef"]] = None
|
|
1565
|
+
code: str
|
|
1566
|
+
created_at: str = Field(alias="createdAt")
|
|
1567
|
+
created_by_api_key_id: Optional[str] = Field(default=None, alias="createdByApiKeyId")
|
|
1568
|
+
current_recording: Optional["CurrentRecording"] = Field(default=None, alias="currentRecording")
|
|
1569
|
+
id: str
|
|
1570
|
+
job: Optional["TranscriptionJob"] = None
|
|
1571
|
+
kind: Literal["transcription"] = "transcription"
|
|
1572
|
+
last_recorded_at: Optional[str] = Field(default=None, alias="lastRecordedAt")
|
|
1573
|
+
last_recording: Optional["LastRecording"] = Field(default=None, alias="lastRecording")
|
|
1574
|
+
lifecycle: Lifecycle
|
|
1575
|
+
live: Optional[bool] = None
|
|
1576
|
+
locked: Optional[bool] = None
|
|
1577
|
+
name: str
|
|
1578
|
+
origin: Literal["dashboard", "api", "extension", "desktop_app", "obs", "wordpress", "payload", "strapi", "sanity", "contentful", "mcp", "broadcast", "unknown"]
|
|
1579
|
+
owner_principal_id: str = Field(alias="ownerPrincipalId")
|
|
1580
|
+
purge_after: Optional[str] = Field(default=None, alias="purgeAfter")
|
|
1581
|
+
recording_count: int = Field(alias="recordingCount")
|
|
1582
|
+
settings: "Settings"
|
|
1583
|
+
share_code: Optional[str] = Field(default=None, alias="shareCode")
|
|
1584
|
+
share_url: str = Field(alias="shareUrl")
|
|
1585
|
+
source: "CaptureSource"
|
|
1586
|
+
tags: Optional[List["TagRef"]] = None
|
|
1587
|
+
updated_at: str = Field(alias="updatedAt")
|
|
1588
|
+
|
|
1589
|
+
|
|
1647
1590
|
class TranscriptionLookup(_Base):
|
|
1648
1591
|
transcription: Optional["Transcription"] = None
|
|
1649
1592
|
|
|
@@ -1902,6 +1845,14 @@ class SessionLoading(_Base):
|
|
|
1902
1845
|
type: Literal["session.loading"] = "session.loading"
|
|
1903
1846
|
|
|
1904
1847
|
|
|
1848
|
+
class SessionQueued(_Base):
|
|
1849
|
+
buffered_s: Optional[float] = Field(default=None, alias="bufferedS")
|
|
1850
|
+
dropped_s: Optional[float] = Field(default=None, alias="droppedS")
|
|
1851
|
+
position: Optional[int] = None
|
|
1852
|
+
type: Literal["session.queued"] = "session.queued"
|
|
1853
|
+
waited_s: float = Field(alias="waitedS")
|
|
1854
|
+
|
|
1855
|
+
|
|
1905
1856
|
class SessionReady(_Base):
|
|
1906
1857
|
type: Literal["session.ready"] = "session.ready"
|
|
1907
1858
|
|
|
@@ -2080,7 +2031,7 @@ class ErrorFrame(_Base):
|
|
|
2080
2031
|
type: Literal["error"] = "error"
|
|
2081
2032
|
|
|
2082
2033
|
|
|
2083
|
-
ServerFrame = Annotated[Union[SessionLoading, SessionReady, TranscriptCommitted, TranscriptDraft, TranscriptWords, TranscriptAmended, TranscriptLatency, TranscriptSpeaker, TranscriptSpeakerGender, TranscriptSpeakerIdentified, TranscriptSpeakerNumbers, TranscriptSentence, TranscriptTranslated, TranscriptVoice, TranscriptVoiceStatus, TranscriptLanguageStatus, TranscriptRetracted, TranscriptHeld, TranscriptProgress, StreamPull, SourceProgress, SourcePrepared, SessionDone, ErrorFrame], Field(discriminator="type")]
|
|
2034
|
+
ServerFrame = Annotated[Union[SessionLoading, SessionQueued, SessionReady, TranscriptCommitted, TranscriptDraft, TranscriptWords, TranscriptAmended, TranscriptLatency, TranscriptSpeaker, TranscriptSpeakerGender, TranscriptSpeakerIdentified, TranscriptSpeakerNumbers, TranscriptSentence, TranscriptTranslated, TranscriptVoice, TranscriptVoiceStatus, TranscriptLanguageStatus, TranscriptRetracted, TranscriptHeld, TranscriptProgress, StreamPull, SourceProgress, SourcePrepared, SessionDone, ErrorFrame], Field(discriminator="type")]
|
|
2084
2035
|
|
|
2085
2036
|
class SubscribeUpdate(_Base):
|
|
2086
2037
|
audio: Optional[bool] = None
|
|
@@ -2226,7 +2177,7 @@ class SubscribeGap(_Base):
|
|
|
2226
2177
|
|
|
2227
2178
|
SubscriberFrame = Annotated[Union[SubscribeReady, RecordingState, RecordingSettings, RecordingSilence, RecordingExpiring, TranscriptCorrected, TranscriptSpeakerGender, TranscriptSpeakerIdentified, TranscriptSpeakerNamed, TranscriptSpeakerNumbers, RecordingStarted, JobProgress, StreamIngest, RecordingEnded, Audience, SubscribeGap], Field(discriminator="type")]
|
|
2228
2179
|
|
|
2229
|
-
SERVER_FRAME_TYPES = frozenset(["session.loading", "session.ready", "transcript.committed", "transcript.draft", "transcript.words", "transcript.amended", "transcript.latency", "transcript.speaker", "transcript.speakerGender", "transcript.speakerIdentified", "transcript.speakerNumbers", "transcript.sentence", "transcript.translated", "transcript.voice", "transcript.voiceStatus", "transcript.languageStatus", "transcript.retracted", "transcript.held", "transcript.progress", "stream.pull", "source.progress", "source.prepared", "session.done", "error"])
|
|
2180
|
+
SERVER_FRAME_TYPES = frozenset(["session.loading", "session.queued", "session.ready", "transcript.committed", "transcript.draft", "transcript.words", "transcript.amended", "transcript.latency", "transcript.speaker", "transcript.speakerGender", "transcript.speakerIdentified", "transcript.speakerNumbers", "transcript.sentence", "transcript.translated", "transcript.voice", "transcript.voiceStatus", "transcript.languageStatus", "transcript.retracted", "transcript.held", "transcript.progress", "stream.pull", "source.progress", "source.prepared", "session.done", "error"])
|
|
2230
2181
|
|
|
2231
2182
|
_server_frame_adapter: TypeAdapter[ServerFrame] = TypeAdapter(ServerFrame)
|
|
2232
2183
|
|
|
@@ -28,7 +28,6 @@ import httpx
|
|
|
28
28
|
from ._http import DEFAULT_BASE_URL, Transport
|
|
29
29
|
from .realtime import Realtime
|
|
30
30
|
from .resources import (
|
|
31
|
-
Batches,
|
|
32
31
|
Billing,
|
|
33
32
|
Broadcasts,
|
|
34
33
|
Connect,
|
|
@@ -84,7 +83,6 @@ class VocalStack:
|
|
|
84
83
|
self.realtime = Realtime(t, ready_deadline_s)
|
|
85
84
|
self.broadcasts = Broadcasts(t)
|
|
86
85
|
self.transcriptions = Transcriptions(t)
|
|
87
|
-
self.batches = Batches(t)
|
|
88
86
|
self.recordings = Recordings(t, ready_deadline_s)
|
|
89
87
|
self.jobs = Jobs(t)
|
|
90
88
|
self.corrections = Corrections(t)
|
|
@@ -382,7 +382,7 @@ async def pace_realtime(
|
|
|
382
382
|
speed: float = 1.0,
|
|
383
383
|
) -> None:
|
|
384
384
|
"""Feed a whole PCM buffer at ``speed``× realtime, then ``eof()``.
|
|
385
|
-
Convenience for file
|
|
385
|
+
Convenience for file sources against the realtime API."""
|
|
386
386
|
bytes_per_second = 16000 * 4
|
|
387
387
|
chunk = max(4, int(bytes_per_second * chunk_seconds) & ~3)
|
|
388
388
|
start = time.monotonic()
|
|
@@ -349,115 +349,6 @@ class Transcriptions(_ParentResource):
|
|
|
349
349
|
return _one(m.Transcription, data)
|
|
350
350
|
|
|
351
351
|
|
|
352
|
-
class Batches(_Group):
|
|
353
|
-
"""``vs.batches``: several files transcribed together, for less than a
|
|
354
|
-
transcription each (one create, one minimum charge). Create a batch, add
|
|
355
|
-
each file or link with ``add_file``, then ``start`` it; ``get`` shows its
|
|
356
|
-
files (each a transcription with its job) and their counts. A batch's
|
|
357
|
-
files get no summary, title, share link or spoken translations."""
|
|
358
|
-
|
|
359
|
-
@staticmethod
|
|
360
|
-
def _path(id: str, rest: str = "") -> str:
|
|
361
|
-
return f"/v1/batches/{_p(id)}{rest}"
|
|
362
|
-
|
|
363
|
-
async def create(self, *, idempotency_key: Optional[str] = None, **fields: Any) -> m.Batch:
|
|
364
|
-
"""An open batch, ready for files (``name`` defaults to "Batch of
|
|
365
|
-
<date>"; ``settings``: ``spoken_language``, ``speaker_labels``,
|
|
366
|
-
``latency_mode`` for every file)."""
|
|
367
|
-
body = _body(m.CreateBatch, fields)
|
|
368
|
-
return _one(m.Batch, await self._t.json("POST", "/v1/batches", json_body=body, idempotency_key=idempotency_key))
|
|
369
|
-
|
|
370
|
-
async def list(self) -> List[m.Batch]:
|
|
371
|
-
"""Every batch, newest first (every page of ``list_page``); each with its counts, not its files."""
|
|
372
|
-
items = await _all_pages(lambda c: self._t.json("GET", "/v1/batches", query={"cursor": c}), "batches")
|
|
373
|
-
return [m.Batch.model_validate(x) for x in items]
|
|
374
|
-
|
|
375
|
-
async def list_page(self, *, cursor: Optional[str] = None, limit: Optional[int] = None) -> m.BatchPage:
|
|
376
|
-
"""One page of batches, newest first; ``cursor`` is the previous page's ``next_cursor``."""
|
|
377
|
-
return _one(m.BatchPage, await self._t.json("GET", "/v1/batches", query={"cursor": cursor, "limit": limit}))
|
|
378
|
-
|
|
379
|
-
async def get(self, id: str) -> m.Batch:
|
|
380
|
-
"""A batch with its files (``files``, each a transcription with its job), in the order they were added."""
|
|
381
|
-
return _one(m.Batch, await self._t.json("GET", self._path(id)))
|
|
382
|
-
|
|
383
|
-
async def delete(self, id: str) -> None:
|
|
384
|
-
"""Discard a batch that was never started, with its files (nothing was charged)."""
|
|
385
|
-
await self._t.json("DELETE", self._path(id))
|
|
386
|
-
|
|
387
|
-
async def add_file(
|
|
388
|
-
self,
|
|
389
|
-
id: str,
|
|
390
|
-
*,
|
|
391
|
-
file: Optional[Upload] = None,
|
|
392
|
-
file_name: Optional[str] = None,
|
|
393
|
-
idempotency_key: Optional[str] = None,
|
|
394
|
-
**fields: Any,
|
|
395
|
-
) -> m.Transcription:
|
|
396
|
-
"""Add one file (``file``: a path, bytes or an open binary file) or
|
|
397
|
-
public link (``url=...``) to an open batch: a transcription of its
|
|
398
|
-
own (``batch_id``), waiting for the batch's ``start``. Of the
|
|
399
|
-
transcription options it takes ``name``, ``start_s``, ``end_s`` and
|
|
400
|
-
``duration_s`` (the settings are the batch's)."""
|
|
401
|
-
options = _body(m.CreateTranscription, fields)
|
|
402
|
-
if file is None:
|
|
403
|
-
data = await self._t.json("POST", self._path(id, "/files"), json_body=options, idempotency_key=idempotency_key)
|
|
404
|
-
else:
|
|
405
|
-
part = await asyncio.to_thread(_file_part, file, file_name, "upload")
|
|
406
|
-
data = await self._t.json(
|
|
407
|
-
"POST",
|
|
408
|
-
self._path(id, "/files"),
|
|
409
|
-
data={"options": json.dumps(options)},
|
|
410
|
-
files={"file": part},
|
|
411
|
-
idempotency_key=idempotency_key,
|
|
412
|
-
)
|
|
413
|
-
return _one(m.Transcription, data)
|
|
414
|
-
|
|
415
|
-
async def add_url(self, id: str, url: str, **fields: Any) -> m.Transcription:
|
|
416
|
-
"""``add_file(id, url=url, ...)``."""
|
|
417
|
-
return await self.add_file(id, url=url, **fields)
|
|
418
|
-
|
|
419
|
-
async def start(self, id: str, *, idempotency_key: Optional[str] = None) -> m.Batch:
|
|
420
|
-
"""Seal the batch and queue its files, longest first; ``wait`` follows it to the end."""
|
|
421
|
-
return _one(m.Batch, await self._t.json("POST", self._path(id, "/start"), idempotency_key=idempotency_key))
|
|
422
|
-
|
|
423
|
-
async def export(self, id: str, format: str) -> bytes:
|
|
424
|
-
"""Every finished file's transcript in one ``format`` (``json``,
|
|
425
|
-
``srt``, ``xlsx`` or ``pdf``, as ``recordings.export`` makes one), in
|
|
426
|
-
one zip: its bytes. Files still running or failed are left out."""
|
|
427
|
-
resp = await self._t.raw("GET", self._path(id, "/export"), headers={"accept": "*/*"}, query={"format": format})
|
|
428
|
-
return resp.content
|
|
429
|
-
|
|
430
|
-
async def stop(self, id: str) -> m.Batch:
|
|
431
|
-
"""Stop every file not finished yet: queued files never start, a
|
|
432
|
-
running one is cancelled and billed for what it transcribed."""
|
|
433
|
-
return _one(m.Batch, await self._t.json("POST", self._path(id, "/stop")))
|
|
434
|
-
|
|
435
|
-
async def wait(
|
|
436
|
-
self,
|
|
437
|
-
id: str,
|
|
438
|
-
*,
|
|
439
|
-
interval_s: float = 5.0,
|
|
440
|
-
timeout_s: Optional[float] = None,
|
|
441
|
-
on_progress: Optional[Callable[[m.Batch], None]] = None,
|
|
442
|
-
) -> m.Batch:
|
|
443
|
-
"""Poll a started batch until it is ``done`` (every file finished or
|
|
444
|
-
failed) or ``stopped``, and return it with its files. It does not
|
|
445
|
-
raise on a failed file: check ``counts.failed`` and each file's
|
|
446
|
-
``job.state``. ``on_progress`` sees every read, the last one included."""
|
|
447
|
-
deadline = None if timeout_s is None else time.monotonic() + timeout_s
|
|
448
|
-
while True:
|
|
449
|
-
batch = await self.get(id)
|
|
450
|
-
if on_progress is not None:
|
|
451
|
-
on_progress(batch)
|
|
452
|
-
if batch.state in ("done", "stopped") and batch.finished_at:
|
|
453
|
-
return batch
|
|
454
|
-
if batch.state == "open":
|
|
455
|
-
raise VocalStackError("invalid_state", "the batch is open: start it before waiting for it")
|
|
456
|
-
if deadline is not None and time.monotonic() + interval_s > deadline:
|
|
457
|
-
raise VocalStackError("timeout", f"batch still {batch.state} after {timeout_s}s", retryable=True)
|
|
458
|
-
await asyncio.sleep(interval_s)
|
|
459
|
-
|
|
460
|
-
|
|
461
352
|
class Recordings(_Group):
|
|
462
353
|
"""``vs.recordings``: one take, live or uploaded."""
|
|
463
354
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|