transcribe-cpp 0.2.1__tar.gz → 0.2.2__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.
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/PKG-INFO +16 -3
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/README.md +13 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/pyproject.toml +3 -3
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/src/transcribe_cpp/__init__.py +37 -6
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/conftest.py +14 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_errors.py +52 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_streaming.py +8 -0
- transcribe_cpp-0.2.2/tests/test_text_controls.py +28 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/uv.lock +3 -3
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/.gitignore +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/LICENSE +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/_generate/README.md +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/_generate/check_version_sync.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/_generate/generate.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/examples/stream_wav.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/examples/transcribe_wav.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/src/transcribe_cpp/_abi.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/src/transcribe_cpp/_generated.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/src/transcribe_cpp/_library.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/src/transcribe_cpp/errors.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/src/transcribe_cpp/py.typed +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_abi.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_backends.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_device_select.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_example.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_family_ext.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_lifetime.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_pcm.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_provider_discovery.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_transcribe.py +0 -0
- {transcribe_cpp-0.2.1 → transcribe_cpp-0.2.2}/tests/test_utf8_paths.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: transcribe-cpp
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Python bindings for transcribe.cpp
|
|
5
5
|
Project-URL: Homepage, https://github.com/handy-computer/transcribe.cpp
|
|
6
6
|
Project-URL: Repository, https://github.com/handy-computer/transcribe.cpp
|
|
@@ -21,9 +21,9 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
21
21
|
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
22
22
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
23
|
Requires-Python: >=3.9
|
|
24
|
-
Requires-Dist: transcribe-cpp-native==0.2.
|
|
24
|
+
Requires-Dist: transcribe-cpp-native==0.2.2.*
|
|
25
25
|
Provides-Extra: cu12
|
|
26
|
-
Requires-Dist: transcribe-cpp-native-cu12==0.2.
|
|
26
|
+
Requires-Dist: transcribe-cpp-native-cu12==0.2.2.*; extra == 'cu12'
|
|
27
27
|
Provides-Extra: test
|
|
28
28
|
Requires-Dist: numpy; extra == 'test'
|
|
29
29
|
Requires-Dist: pytest>=7; extra == 'test'
|
|
@@ -62,6 +62,18 @@ pcm = np.asarray(audio, dtype=np.float32) # 1-D, 16 kHz mono
|
|
|
62
62
|
result = session.run(pcm)
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
### Punctuation, capitalization, and text normalization
|
|
66
|
+
|
|
67
|
+
Generic run controls use `"default"` to preserve each model family's shipped
|
|
68
|
+
behavior. Models advertising `model.supports("pnc")` accept `pnc="off"` or
|
|
69
|
+
`pnc="on"`; models advertising `model.supports("itn")` accept the equivalent
|
|
70
|
+
`itn` values. The options are available on `run()`, `run_batch()`, `stream()`,
|
|
71
|
+
and the one-shot `transcribe()` helper.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
result = session.run(pcm, pnc="off", itn="on")
|
|
75
|
+
```
|
|
76
|
+
|
|
65
77
|
Streaming models expose incremental transcription with committed/tentative
|
|
66
78
|
text views — see `examples/stream_wav.py`:
|
|
67
79
|
|
|
@@ -71,6 +83,7 @@ with model.session() as session, session.stream() as stream:
|
|
|
71
83
|
stream.feed(chunk)
|
|
72
84
|
text = stream.text() # .committed (stable) + .tentative
|
|
73
85
|
stream.finalize()
|
|
86
|
+
result = stream.snapshot() # language, segments, words, tokens, timings
|
|
74
87
|
```
|
|
75
88
|
|
|
76
89
|
Long transcriptions can be cancelled from another thread with
|
|
@@ -31,6 +31,18 @@ pcm = np.asarray(audio, dtype=np.float32) # 1-D, 16 kHz mono
|
|
|
31
31
|
result = session.run(pcm)
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
### Punctuation, capitalization, and text normalization
|
|
35
|
+
|
|
36
|
+
Generic run controls use `"default"` to preserve each model family's shipped
|
|
37
|
+
behavior. Models advertising `model.supports("pnc")` accept `pnc="off"` or
|
|
38
|
+
`pnc="on"`; models advertising `model.supports("itn")` accept the equivalent
|
|
39
|
+
`itn` values. The options are available on `run()`, `run_batch()`, `stream()`,
|
|
40
|
+
and the one-shot `transcribe()` helper.
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
result = session.run(pcm, pnc="off", itn="on")
|
|
44
|
+
```
|
|
45
|
+
|
|
34
46
|
Streaming models expose incremental transcription with committed/tentative
|
|
35
47
|
text views — see `examples/stream_wav.py`:
|
|
36
48
|
|
|
@@ -40,6 +52,7 @@ with model.session() as session, session.stream() as stream:
|
|
|
40
52
|
stream.feed(chunk)
|
|
41
53
|
text = stream.text() # .committed (stable) + .tentative
|
|
42
54
|
stream.finalize()
|
|
55
|
+
result = stream.snapshot() # language, segments, words, tokens, timings
|
|
43
56
|
```
|
|
44
57
|
|
|
45
58
|
Long transcriptions can be cancelled from another thread with
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "transcribe-cpp"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Python bindings for transcribe.cpp"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
# 3.8 is EOL (2024-10); 3.9 is the floor. The binding is ctypes-only, so there
|
|
@@ -34,13 +34,13 @@ classifiers = [
|
|
|
34
34
|
# packaging fix still resolves); the import-time version/header-hash check in
|
|
35
35
|
# _library.py is the runtime backstop. check_version_sync.py gates this pin
|
|
36
36
|
# against include/transcribe.h.
|
|
37
|
-
dependencies = ["transcribe-cpp-native==0.2.
|
|
37
|
+
dependencies = ["transcribe-cpp-native==0.2.2.*"]
|
|
38
38
|
|
|
39
39
|
[project.optional-dependencies]
|
|
40
40
|
# Opt-in accelerator providers — ADDITIVE: they install alongside the default
|
|
41
41
|
# provider and the best one wins at runtime. Same base-version pin contract
|
|
42
42
|
# as the hard dependency (gated by check_version_sync.py).
|
|
43
|
-
cu12 = ["transcribe-cpp-native-cu12==0.2.
|
|
43
|
+
cu12 = ["transcribe-cpp-native-cu12==0.2.2.*"]
|
|
44
44
|
# Test-only deps. Run with: uv run --extra test pytest (from bindings/python).
|
|
45
45
|
# numpy is here so the numpy PCM-input tests run in every lane instead of
|
|
46
46
|
# silently skipping wherever numpy happens to be absent.
|
|
@@ -46,13 +46,15 @@ from .errors import (
|
|
|
46
46
|
raise_for_status,
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
-
__version__ = "0.2.
|
|
49
|
+
__version__ = "0.2.2"
|
|
50
50
|
|
|
51
51
|
# String-enum types, exported so callers (and type checkers) can name them.
|
|
52
52
|
Backend = Literal["auto", "cpu", "metal", "vulkan", "cpu_accel", "cuda", "rocm"]
|
|
53
53
|
KVType = Literal["auto", "f32", "f16"]
|
|
54
54
|
Task = Literal["transcribe", "translate"]
|
|
55
55
|
Timestamps = Literal["none", "auto", "segment", "word", "token"]
|
|
56
|
+
Pnc = Literal["default", "off", "on"]
|
|
57
|
+
Itn = Literal["default", "off", "on"]
|
|
56
58
|
Diarize = Literal["default", "off", "on"]
|
|
57
59
|
SortformerPreset = Literal["default", "very_high_latency", "high_latency", "low_latency"]
|
|
58
60
|
CommitPolicy = Literal["auto", "on_finalize", "stable_prefix"]
|
|
@@ -89,6 +91,8 @@ __all__ = [
|
|
|
89
91
|
"KVType",
|
|
90
92
|
"Task",
|
|
91
93
|
"Timestamps",
|
|
94
|
+
"Pnc",
|
|
95
|
+
"Itn",
|
|
92
96
|
"Diarize",
|
|
93
97
|
"CommitPolicy",
|
|
94
98
|
"Feature",
|
|
@@ -206,6 +210,16 @@ _TIMESTAMPS = {
|
|
|
206
210
|
"token": _generated.TRANSCRIBE_TIMESTAMPS_TOKEN,
|
|
207
211
|
}
|
|
208
212
|
_TIMESTAMP_NAMES = {v: k for k, v in _TIMESTAMPS.items()}
|
|
213
|
+
_PNC = {
|
|
214
|
+
"default": _generated.TRANSCRIBE_PNC_MODE_DEFAULT,
|
|
215
|
+
"off": _generated.TRANSCRIBE_PNC_MODE_OFF,
|
|
216
|
+
"on": _generated.TRANSCRIBE_PNC_MODE_ON,
|
|
217
|
+
}
|
|
218
|
+
_ITN = {
|
|
219
|
+
"default": _generated.TRANSCRIBE_ITN_MODE_DEFAULT,
|
|
220
|
+
"off": _generated.TRANSCRIBE_ITN_MODE_OFF,
|
|
221
|
+
"on": _generated.TRANSCRIBE_ITN_MODE_ON,
|
|
222
|
+
}
|
|
209
223
|
_DIARIZE = {
|
|
210
224
|
"default": _generated.TRANSCRIBE_DIARIZE_MODE_DEFAULT,
|
|
211
225
|
"off": _generated.TRANSCRIBE_DIARIZE_MODE_OFF,
|
|
@@ -638,7 +652,8 @@ def _stream_update_from(u) -> StreamUpdate:
|
|
|
638
652
|
|
|
639
653
|
|
|
640
654
|
def _build_run_params(task, language, target_language, timestamps,
|
|
641
|
-
keep_special_tags, spec_k_drafts, diarize="default"
|
|
655
|
+
keep_special_tags, spec_k_drafts, diarize="default",
|
|
656
|
+
pnc="default", itn="default"):
|
|
642
657
|
if not isinstance(spec_k_drafts, int) or spec_k_drafts < -1:
|
|
643
658
|
raise InvalidArgument(
|
|
644
659
|
f"spec_k_drafts must be -1 (family default), 0 (disabled), or a "
|
|
@@ -648,6 +663,8 @@ def _build_run_params(task, language, target_language, timestamps,
|
|
|
648
663
|
_lib.transcribe_run_params_init(_byref(params))
|
|
649
664
|
params.task = _enum(_TASKS, task, "task")
|
|
650
665
|
params.timestamps = _enum(_TIMESTAMPS, timestamps, "timestamps")
|
|
666
|
+
params.pnc = _enum(_PNC, pnc, "pnc")
|
|
667
|
+
params.itn = _enum(_ITN, itn, "itn")
|
|
651
668
|
params.diarize = _enum(_DIARIZE, diarize, "diarize")
|
|
652
669
|
params.language = language.encode("utf-8") if language else None
|
|
653
670
|
params.target_language = target_language.encode("utf-8") if target_language else None
|
|
@@ -1079,12 +1096,16 @@ class Session:
|
|
|
1079
1096
|
language: str | None = None,
|
|
1080
1097
|
target_language: str | None = None,
|
|
1081
1098
|
timestamps: Timestamps = "auto",
|
|
1099
|
+
pnc: Pnc = "default",
|
|
1100
|
+
itn: Itn = "default",
|
|
1082
1101
|
diarize: Diarize = "default",
|
|
1083
1102
|
keep_special_tags: bool = False,
|
|
1084
1103
|
spec_k_drafts: int = -1,
|
|
1085
1104
|
family: FamilyExtension | None = None) -> Result:
|
|
1086
1105
|
"""Transcribe 16 kHz mono float32 PCM and return a materialized Result.
|
|
1087
1106
|
|
|
1107
|
+
``pnc`` controls punctuation/capitalization and ``itn`` controls
|
|
1108
|
+
inverse text normalization on models advertising those features.
|
|
1088
1109
|
``family`` is an optional family-specific extension (e.g.
|
|
1089
1110
|
WhisperRunOptions) carrying per-run knobs for models that accept it.
|
|
1090
1111
|
``spec_k_drafts`` tunes speculative decoding on models whose
|
|
@@ -1097,7 +1118,7 @@ class Session:
|
|
|
1097
1118
|
self._cancel.clear()
|
|
1098
1119
|
array, n_samples = _pcm_to_carray(pcm)
|
|
1099
1120
|
params = _build_run_params(task, language, target_language, timestamps,
|
|
1100
|
-
keep_special_tags, spec_k_drafts, diarize)
|
|
1121
|
+
keep_special_tags, spec_k_drafts, diarize, pnc, itn)
|
|
1101
1122
|
ext = self._resolve_family(family, "run") if family is not None else None
|
|
1102
1123
|
if ext is not None:
|
|
1103
1124
|
params.family = ctypes.cast(
|
|
@@ -1116,6 +1137,8 @@ class Session:
|
|
|
1116
1137
|
language: str | None = None,
|
|
1117
1138
|
target_language: str | None = None,
|
|
1118
1139
|
timestamps: Timestamps = "auto",
|
|
1140
|
+
pnc: Pnc = "default",
|
|
1141
|
+
itn: Itn = "default",
|
|
1119
1142
|
diarize: Diarize = "default",
|
|
1120
1143
|
keep_special_tags: bool = False,
|
|
1121
1144
|
spec_k_drafts: int = -1,
|
|
@@ -1153,7 +1176,7 @@ class Session:
|
|
|
1153
1176
|
counts[k] = n
|
|
1154
1177
|
|
|
1155
1178
|
params = _build_run_params(task, language, target_language, timestamps,
|
|
1156
|
-
keep_special_tags, spec_k_drafts, diarize)
|
|
1179
|
+
keep_special_tags, spec_k_drafts, diarize, pnc, itn)
|
|
1157
1180
|
ext = self._resolve_family(family, "run") if family is not None else None
|
|
1158
1181
|
if ext is not None:
|
|
1159
1182
|
params.family = ctypes.cast(
|
|
@@ -1204,6 +1227,7 @@ class Session:
|
|
|
1204
1227
|
|
|
1205
1228
|
def stream(self, *, task: Task = "transcribe", language: str | None = None,
|
|
1206
1229
|
target_language: str | None = None, timestamps: Timestamps = "none",
|
|
1230
|
+
pnc: Pnc = "default", itn: Itn = "default",
|
|
1207
1231
|
diarize: Diarize = "default",
|
|
1208
1232
|
keep_special_tags: bool = False, commit_policy: CommitPolicy = "auto",
|
|
1209
1233
|
stable_prefix_agreement_n: int = 0,
|
|
@@ -1219,7 +1243,7 @@ class Session:
|
|
|
1219
1243
|
# spec_k_drafts is an offline-decode knob; streaming always uses the
|
|
1220
1244
|
# family default (-1).
|
|
1221
1245
|
run_params = _build_run_params(task, language, target_language, timestamps,
|
|
1222
|
-
keep_special_tags, -1, diarize)
|
|
1246
|
+
keep_special_tags, -1, diarize, pnc, itn)
|
|
1223
1247
|
sp = _StreamParams()
|
|
1224
1248
|
_lib.transcribe_stream_params_init(_byref(sp))
|
|
1225
1249
|
sp.commit_policy = _enum(_COMMIT_POLICIES, commit_policy, "commit_policy")
|
|
@@ -1413,6 +1437,11 @@ class Stream:
|
|
|
1413
1437
|
tentative=_decode(txt.tentative_text),
|
|
1414
1438
|
)
|
|
1415
1439
|
|
|
1440
|
+
def snapshot(self) -> Result:
|
|
1441
|
+
"""Full structured snapshot of the current hypothesis (owned copies)."""
|
|
1442
|
+
_ = self._h # validate that this stream has not been reset
|
|
1443
|
+
return self._session._materialize()
|
|
1444
|
+
|
|
1416
1445
|
@property
|
|
1417
1446
|
def state(self) -> str:
|
|
1418
1447
|
"""``"idle"`` / ``"active"`` / ``"finished"`` / ``"failed"``."""
|
|
@@ -1461,6 +1490,8 @@ def transcribe(
|
|
|
1461
1490
|
language: str | None = None,
|
|
1462
1491
|
target_language: str | None = None,
|
|
1463
1492
|
timestamps: Timestamps = "auto",
|
|
1493
|
+
pnc: Pnc = "default",
|
|
1494
|
+
itn: Itn = "default",
|
|
1464
1495
|
diarize: Diarize = "default",
|
|
1465
1496
|
keep_special_tags: bool = False,
|
|
1466
1497
|
spec_k_drafts: int = -1,
|
|
@@ -1477,7 +1508,7 @@ def transcribe(
|
|
|
1477
1508
|
"""
|
|
1478
1509
|
session_opts = dict(n_threads=n_threads, kv_type=kv_type, n_ctx=n_ctx)
|
|
1479
1510
|
run_opts = dict(task=task, language=language, target_language=target_language,
|
|
1480
|
-
timestamps=timestamps, diarize=diarize,
|
|
1511
|
+
timestamps=timestamps, pnc=pnc, itn=itn, diarize=diarize,
|
|
1481
1512
|
keep_special_tags=keep_special_tags,
|
|
1482
1513
|
spec_k_drafts=spec_k_drafts, family=family)
|
|
1483
1514
|
|
|
@@ -59,6 +59,8 @@ VOXTRAL_MODEL = (
|
|
|
59
59
|
REPO
|
|
60
60
|
/ "models/Voxtral-Mini-4B-Realtime-2602/Voxtral-Mini-4B-Realtime-2602-Q4_K_M.gguf"
|
|
61
61
|
)
|
|
62
|
+
PNC_MODEL = REPO / "models/canary-180m-flash/canary-180m-flash-Q8_0.gguf"
|
|
63
|
+
ITN_MODEL = REPO / "models/SenseVoiceSmall/SenseVoiceSmall-Q8_0.gguf"
|
|
62
64
|
|
|
63
65
|
|
|
64
66
|
def load_wav(path: Path) -> "array.array":
|
|
@@ -157,3 +159,15 @@ def parakeet_buffered_model_path() -> Path:
|
|
|
157
159
|
def voxtral_model_path() -> Path:
|
|
158
160
|
"""Voxtral realtime streaming canary (accepts VOXTRAL_REALTIME_STREAM)."""
|
|
159
161
|
return _family_model("TRANSCRIBE_SMOKE_VOXTRAL_MODEL", VOXTRAL_MODEL)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@pytest.fixture(scope="session")
|
|
165
|
+
def pnc_model_path() -> Path:
|
|
166
|
+
"""Canary model whose generic PNC run parameter changes the prompt."""
|
|
167
|
+
return _family_model("TRANSCRIBE_SMOKE_PNC_MODEL", PNC_MODEL)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@pytest.fixture(scope="session")
|
|
171
|
+
def itn_model_path() -> Path:
|
|
172
|
+
"""SenseVoice model whose generic ITN parameter changes text normalization."""
|
|
173
|
+
return _family_model("TRANSCRIBE_SMOKE_ITN_MODEL", ITN_MODEL)
|
|
@@ -13,6 +13,8 @@ Two layers, both model-free:
|
|
|
13
13
|
|
|
14
14
|
from __future__ import annotations
|
|
15
15
|
|
|
16
|
+
import inspect
|
|
17
|
+
|
|
16
18
|
import pytest
|
|
17
19
|
|
|
18
20
|
import transcribe_cpp as t
|
|
@@ -102,3 +104,53 @@ def test_invalid_spec_k_drafts_rejected_before_native_call():
|
|
|
102
104
|
_build_run_params("transcribe", None, None, "none", False, -2)
|
|
103
105
|
with pytest.raises(t.InvalidArgument, match="spec_k_drafts"):
|
|
104
106
|
_build_run_params("transcribe", None, None, "none", False, "many")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_pnc_and_itn_modes_map_to_native_run_params():
|
|
110
|
+
from transcribe_cpp import _build_run_params, _generated
|
|
111
|
+
|
|
112
|
+
modes = {
|
|
113
|
+
"default": (
|
|
114
|
+
_generated.TRANSCRIBE_PNC_MODE_DEFAULT,
|
|
115
|
+
_generated.TRANSCRIBE_ITN_MODE_DEFAULT,
|
|
116
|
+
),
|
|
117
|
+
"off": (
|
|
118
|
+
_generated.TRANSCRIBE_PNC_MODE_OFF,
|
|
119
|
+
_generated.TRANSCRIBE_ITN_MODE_OFF,
|
|
120
|
+
),
|
|
121
|
+
"on": (
|
|
122
|
+
_generated.TRANSCRIBE_PNC_MODE_ON,
|
|
123
|
+
_generated.TRANSCRIBE_ITN_MODE_ON,
|
|
124
|
+
),
|
|
125
|
+
}
|
|
126
|
+
for mode, (pnc, itn) in modes.items():
|
|
127
|
+
params = _build_run_params(
|
|
128
|
+
"transcribe", None, None, "none", False, -1, pnc=mode, itn=mode
|
|
129
|
+
)
|
|
130
|
+
assert params.pnc == pnc
|
|
131
|
+
assert params.itn == itn
|
|
132
|
+
|
|
133
|
+
for name in ("pnc", "itn"):
|
|
134
|
+
with pytest.raises(t.InvalidArgument, match=name):
|
|
135
|
+
_build_run_params(
|
|
136
|
+
"transcribe", None, None, "none", False, -1, **{name: "maybe"}
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_public_run_surfaces_cover_every_generic_option():
|
|
141
|
+
common = {
|
|
142
|
+
"task", "language", "target_language", "timestamps", "pnc", "itn",
|
|
143
|
+
"diarize", "keep_special_tags", "family",
|
|
144
|
+
}
|
|
145
|
+
expected = {
|
|
146
|
+
t.Session.run: common | {"spec_k_drafts"},
|
|
147
|
+
t.Session.run_batch: common | {"spec_k_drafts"},
|
|
148
|
+
# Speculative decoding is explicitly offline-only.
|
|
149
|
+
t.Session.stream: common,
|
|
150
|
+
t.transcribe: common | {"spec_k_drafts"},
|
|
151
|
+
}
|
|
152
|
+
for callable_, required in expected.items():
|
|
153
|
+
parameters = inspect.signature(callable_).parameters
|
|
154
|
+
assert required <= parameters.keys()
|
|
155
|
+
assert "Pnc" in t.__all__
|
|
156
|
+
assert "Itn" in t.__all__
|
|
@@ -29,6 +29,7 @@ def test_streaming_real(streaming_model_path, audio_pcm):
|
|
|
29
29
|
stream.feed(audio_pcm[i : i + 16000])
|
|
30
30
|
update = stream.finalize()
|
|
31
31
|
committed = stream.text().committed
|
|
32
|
+
snapshot = stream.snapshot()
|
|
32
33
|
revision, state = stream.revision, stream.state
|
|
33
34
|
last_status = stream.last_status
|
|
34
35
|
assert update.is_final, update
|
|
@@ -36,6 +37,11 @@ def test_streaming_real(streaming_model_path, audio_pcm):
|
|
|
36
37
|
assert revision >= 1
|
|
37
38
|
assert last_status is None, last_status
|
|
38
39
|
assert "country" in committed.lower(), committed
|
|
40
|
+
assert snapshot.text
|
|
41
|
+
assert isinstance(snapshot.language, str)
|
|
42
|
+
assert snapshot.segments
|
|
43
|
+
assert isinstance(snapshot.words, tuple)
|
|
44
|
+
assert isinstance(snapshot.tokens, tuple)
|
|
39
45
|
|
|
40
46
|
|
|
41
47
|
def test_streaming_with_language_hint(prompted_streaming_model_path, audio_pcm):
|
|
@@ -122,6 +128,8 @@ def test_stream_use_after_reset_rejected(streaming_model_path, audio_pcm):
|
|
|
122
128
|
stream.feed(audio_pcm[:16000])
|
|
123
129
|
with pytest.raises(t.TranscribeError, match="reset"):
|
|
124
130
|
stream.text()
|
|
131
|
+
with pytest.raises(t.TranscribeError, match="reset"):
|
|
132
|
+
stream.snapshot()
|
|
125
133
|
|
|
126
134
|
|
|
127
135
|
def test_stream_reset_idempotent_and_session_reusable(
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Model-gated generic punctuation/capitalization and ITN controls."""
|
|
2
|
+
|
|
3
|
+
import transcribe_cpp as t
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_pnc_changes_canary_prompt(pnc_model_path, audio_pcm):
|
|
7
|
+
with t.Model(pnc_model_path, backend="cpu") as model, model.session() as session:
|
|
8
|
+
assert model.supports("pnc")
|
|
9
|
+
default = session.run(audio_pcm, language="en", pnc="default").text
|
|
10
|
+
enabled = session.run(audio_pcm, language="en", pnc="on").text
|
|
11
|
+
disabled = session.run(audio_pcm, language="en", pnc="off").text
|
|
12
|
+
|
|
13
|
+
assert default == enabled
|
|
14
|
+
assert disabled != enabled
|
|
15
|
+
assert disabled == disabled.lower()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_itn_changes_sensevoice_text_normalization(itn_model_path, audio_pcm):
|
|
19
|
+
with t.Model(itn_model_path, backend="cpu") as model, model.session() as session:
|
|
20
|
+
assert model.supports("itn")
|
|
21
|
+
default = session.run(audio_pcm, language="en", itn="default")
|
|
22
|
+
disabled = session.run(audio_pcm, language="en", itn="off")
|
|
23
|
+
enabled = session.run(audio_pcm, language="en", itn="on")
|
|
24
|
+
|
|
25
|
+
assert (default.text, default.raw_text) == (disabled.text, disabled.raw_text)
|
|
26
|
+
assert enabled.text != disabled.text
|
|
27
|
+
assert "<|woitn|>" in disabled.raw_text
|
|
28
|
+
assert "<|withitn|>" in enabled.raw_text
|
|
@@ -386,7 +386,7 @@ wheels = [
|
|
|
386
386
|
|
|
387
387
|
[[package]]
|
|
388
388
|
name = "transcribe-cpp"
|
|
389
|
-
version = "0.2.
|
|
389
|
+
version = "0.2.2"
|
|
390
390
|
source = { editable = "." }
|
|
391
391
|
|
|
392
392
|
[package.optional-dependencies]
|
|
@@ -402,8 +402,8 @@ test = [
|
|
|
402
402
|
requires-dist = [
|
|
403
403
|
{ name = "numpy", marker = "extra == 'test'" },
|
|
404
404
|
{ name = "pytest", marker = "extra == 'test'", specifier = ">=7" },
|
|
405
|
-
{ name = "transcribe-cpp-native", specifier = "==0.2.
|
|
406
|
-
{ name = "transcribe-cpp-native-cu12", marker = "extra == 'cu12'", specifier = "==0.2.
|
|
405
|
+
{ name = "transcribe-cpp-native", specifier = "==0.2.2.*" },
|
|
406
|
+
{ name = "transcribe-cpp-native-cu12", marker = "extra == 'cu12'", specifier = "==0.2.2.*" },
|
|
407
407
|
]
|
|
408
408
|
|
|
409
409
|
[[package]]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|