s2t 0.1.0.post1.dev2__tar.gz → 0.1.1__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.
Files changed (28) hide show
  1. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/.gitignore +2 -0
  2. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/Makefile +10 -2
  3. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/PKG-INFO +1 -1
  4. s2t-0.1.1/docs/SESSION_STATE.md +35 -0
  5. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t/cli.py +2 -0
  6. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t/whisper_engine.py +22 -1
  7. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t.egg-info/PKG-INFO +1 -1
  8. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t.egg-info/SOURCES.txt +1 -0
  9. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/.pre-commit-config.yaml +0 -0
  10. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/AGENTS.md +0 -0
  11. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/CONTRIBUTING.md +0 -0
  12. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/MANIFEST.in +0 -0
  13. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/README.md +0 -0
  14. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/docs/RELEASING.md +0 -0
  15. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/pyproject.toml +0 -0
  16. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/scripts/bench_transcribe.py +0 -0
  17. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/setup.cfg +0 -0
  18. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t/__init__.py +0 -0
  19. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t/config.py +0 -0
  20. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t/outputs.py +0 -0
  21. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t/py.typed +0 -0
  22. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t/recorder.py +0 -0
  23. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t/types.py +0 -0
  24. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t/utils.py +0 -0
  25. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t.egg-info/dependency_links.txt +0 -0
  26. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t.egg-info/entry_points.txt +0 -0
  27. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t.egg-info/requires.txt +0 -0
  28. {s2t-0.1.0.post1.dev2 → s2t-0.1.1}/src/s2t.egg-info/top_level.txt +0 -0
@@ -33,3 +33,5 @@ runs/
33
33
  output/
34
34
  out/
35
35
  data/
36
+
37
+ .env.twine.example
@@ -66,18 +66,26 @@ publish: guard-venv build
66
66
  $(PYTHON) -c 'import importlib.util,sys; sys.exit(0) if importlib.util.find_spec("twine") else sys.exit(1)' || $(PIP) install twine ; \
67
67
  [ -f .env.twine ] && set -a && . ./.env.twine && set +a || true; \
68
68
  if [ "$$ALLOW_CUSTOM_TWINE_USERNAME" = "1" ]; then TWINE_USERNAME="$${TWINE_USERNAME:-__token__}"; else TWINE_USERNAME="__token__"; fi; \
69
+ # Prefer prod-specific secrets first
70
+ if [ -n "$$TWINE_PROD_PASSWORD_CMD" ] && [ -z "$$TWINE_PASSWORD" ]; then TWINE_PASSWORD="$$(sh -c "$$TWINE_PROD_PASSWORD_CMD" | head -n1 | tr -d '\r\n')"; fi; \
71
+ if [ -n "$$PASS_PROD_TWINE_ENTRY" ] && [ -z "$$TWINE_PASSWORD" ]; then TWINE_PASSWORD="$$(pass show "$$PASS_PROD_TWINE_ENTRY" | head -n1 | tr -d '\r\n')"; fi; \
72
+ # Fallback to generic secrets
69
73
  if [ -n "$$TWINE_PASSWORD_CMD" ] && [ -z "$$TWINE_PASSWORD" ]; then TWINE_PASSWORD="$$(sh -c "$$TWINE_PASSWORD_CMD" | head -n1 | tr -d '\r\n')"; fi; \
70
74
  if [ -n "$$PASS_TWINE_ENTRY" ] && [ -z "$$TWINE_PASSWORD" ]; then TWINE_PASSWORD="$$(pass show "$$PASS_TWINE_ENTRY" | head -n1 | tr -d '\r\n')"; fi; \
71
- if [ -z "$$TWINE_PASSWORD" ]; then echo "Error: TWINE_PASSWORD is empty. Provide via .env.twine, TWINE_PASSWORD_CMD, or PASS_TWINE_ENTRY." >&2; exit 2; fi; \
75
+ if [ -z "$$TWINE_PASSWORD" ]; then echo "Error: TWINE_PASSWORD is empty. Provide via .env.twine, TWINE_*_PASSWORD_CMD, or PASS_*_TWINE_ENTRY." >&2; exit 2; fi; \
72
76
  env TWINE_USERNAME="$$TWINE_USERNAME" TWINE_PASSWORD="$$TWINE_PASSWORD" twine upload --non-interactive $$TWINE_EXTRA_FLAGS dist/*
73
77
 
74
78
  publish-test: guard-venv build
75
79
  $(PYTHON) -c 'import importlib.util,sys; sys.exit(0) if importlib.util.find_spec("twine") else sys.exit(1)' || $(PIP) install twine ; \
76
80
  [ -f .env.twine ] && set -a && . ./.env.twine && set +a || true; \
77
81
  if [ "$$ALLOW_CUSTOM_TWINE_USERNAME" = "1" ]; then TWINE_USERNAME="$${TWINE_USERNAME:-__token__}"; else TWINE_USERNAME="__token__"; fi; \
82
+ # Prefer test-specific secrets first
83
+ if [ -n "$$TWINE_TEST_PASSWORD_CMD" ] && [ -z "$$TWINE_PASSWORD" ]; then TWINE_PASSWORD="$$(sh -c "$$TWINE_TEST_PASSWORD_CMD" | head -n1 | tr -d '\r\n')"; fi; \
84
+ if [ -n "$$PASS_TEST_TWINE_ENTRY" ] && [ -z "$$TWINE_PASSWORD" ]; then TWINE_PASSWORD="$$(pass show "$$PASS_TEST_TWINE_ENTRY" | head -n1 | tr -d '\r\n')"; fi; \
85
+ # Fallback to generic secrets
78
86
  if [ -n "$$TWINE_PASSWORD_CMD" ] && [ -z "$$TWINE_PASSWORD" ]; then TWINE_PASSWORD="$$(sh -c "$$TWINE_PASSWORD_CMD" | head -n1 | tr -d '\r\n')"; fi; \
79
87
  if [ -n "$$PASS_TWINE_ENTRY" ] && [ -z "$$TWINE_PASSWORD" ]; then TWINE_PASSWORD="$$(pass show "$$PASS_TWINE_ENTRY" | head -n1 | tr -d '\r\n')"; fi; \
80
- if [ -z "$$TWINE_PASSWORD" ]; then echo "Error: TWINE_PASSWORD is empty. Provide via .env.twine, TWINE_PASSWORD_CMD, or PASS_TWINE_ENTRY." >&2; exit 2; fi; \
88
+ if [ -z "$$TWINE_PASSWORD" ]; then echo "Error: TWINE_PASSWORD is empty. Provide via .env.twine, TWINE_*_PASSWORD_CMD, or PASS_*_TWINE_ENTRY." >&2; exit 2; fi; \
81
89
  env TWINE_USERNAME="$$TWINE_USERNAME" TWINE_PASSWORD="$$TWINE_PASSWORD" twine upload --non-interactive --repository testpypi $$TWINE_EXTRA_FLAGS dist/*
82
90
 
83
91
  record: guard-venv
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: s2t
3
- Version: 0.1.0.post1.dev2
3
+ Version: 0.1.1
4
4
  Summary: Speech to Text (s2t): Record audio, run Whisper, export formats, and copy transcript to clipboard.
5
5
  Author: Maintainers
6
6
  License-Expression: LicenseRef-Proprietary
@@ -0,0 +1,35 @@
1
+ # Session State
2
+
3
+ Stand: Deployment vorbereiten, Paket ist baubar und typgeprüft. Upload zu TestPyPI steht aus.
4
+
5
+ ## Änderungen dieser Session (Kurzfassung)
6
+ - Formatter auf nur Ruff umgestellt (Black entfernt); Makefile `format`/`lint` fixen automatisch.
7
+ - mypy-Fehler streng behoben (TypedDicts in `src/s2t/types.py`).
8
+ - Drittanbieter-Stubs nach `stubs/` verschoben (`sounddevice`, `soundfile`, `pyperclip`, `whisper`).
9
+ - Paket als "typed" markiert (`src/s2t/py.typed`) und Stubs via `MANIFEST.in` vom sdist ausgeschlossen.
10
+ - pyproject: Ruff-Konfig aktualisiert, Lizenzfeld auf SPDX-Form (`LicenseRef-Proprietary`).
11
+ - Doku: README verschlankt; `CONTRIBUTING.md`, `docs/RELEASING.md` hinzugefügt. Linux Systemlibs-Hinweis ergänzt.
12
+ - Build geprüft: `make build` erzeugt gültiges Wheel + sdist; `twine check dist/*` ist grün.
13
+
14
+ ## Offene Schritte (für TestPyPI/PyPI)
15
+ 1) TestPyPI-Creds bereitstellen (eine der Optionen):
16
+ - `.env.twine` im Projekt (gitignored) mit:
17
+ - `TWINE_USERNAME=__token__`
18
+ - `TWINE_PASSWORD=dein_testpypi_api_token`
19
+ - oder `~/.pypirc` konfigurieren (testpypi Sektion).
20
+ 2) Upload anstoßen:
21
+ - `make publish-test`
22
+ 3) Installation validieren in frischem venv:
23
+ - `python -m venv .venv-test && source .venv-test/bin/activate`
24
+ - `pip install --index-url https://test.pypi.org/simple --extra-index-url https://pypi.org/simple s2t`
25
+ - Smoke: `s2t -h`, optional `s2t -L`
26
+ 4) Wenn ok: PyPI-Upload
27
+ - `make publish` (mit PyPI-Token analog zu TestPyPI)
28
+
29
+ ## Hinweise
30
+ - Linux: ggf. `libportaudio2` und `libsndfile1` installieren; ffmpeg optional für MP3.
31
+ - Keine Secrets im Repo: `.env.twine` ist per `.gitignore` ausgeschlossen.
32
+
33
+ ## Wiedereinstieg
34
+ - Falls `.env.twine` schon existiert: direkt `make publish-test` ausführen.
35
+ - Danach Installation wie oben testen; bei Erfolg `make publish`.
@@ -256,6 +256,8 @@ def run_session(opts: SessionOptions) -> int:
256
256
  else:
257
257
  print("—" * 60)
258
258
  print("Transcript (clipboard text):")
259
+ # Visual separator before the actual transcript text
260
+ print("=" * 60)
259
261
  print(text_final.rstrip("\n"))
260
262
 
261
263
  if opts.profile:
@@ -75,10 +75,31 @@ class WhisperEngine:
75
75
  frames: int,
76
76
  initial_prompt: str | None = None,
77
77
  ) -> TranscriptionResult:
78
+ # Load audio without ffmpeg by reading via soundfile and passing a numpy array
79
+ # to Whisper. We ensure mono float32 at 16 kHz as expected by Whisper's API.
78
80
  task = "translate" if self.translate else "transcribe"
81
+ import numpy as np
82
+
83
+ try:
84
+ import soundfile as sf
85
+ except Exception as e:
86
+ raise RuntimeError("soundfile is required to read recorded audio.") from e
87
+
88
+ from .utils import resample_linear
89
+
90
+ # Read audio from file (supports WAV/FLAC via libsndfile), convert to mono
91
+ data, sr = sf.read(str(audio_path), dtype="float32", always_2d=True)
92
+ # data shape: (n_frames, n_channels). Convert to mono by averaging if needed
93
+ if data.ndim == 2 and data.shape[1] > 1:
94
+ mono = data.mean(axis=1)
95
+ else:
96
+ mono = data.reshape(-1)
97
+ # Resample to 16k expected by Whisper when passing arrays
98
+ mono_16k: np.ndarray = resample_linear(mono, int(sr), 16000)
99
+
79
100
  t0 = time.perf_counter()
80
101
  res: dict[str, Any] = model.transcribe(
81
- str(audio_path),
102
+ mono_16k,
82
103
  task=task,
83
104
  language=self.language,
84
105
  fp16=False,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: s2t
3
- Version: 0.1.0.post1.dev2
3
+ Version: 0.1.1
4
4
  Summary: Speech to Text (s2t): Record audio, run Whisper, export formats, and copy transcript to clipboard.
5
5
  Author: Maintainers
6
6
  License-Expression: LicenseRef-Proprietary
@@ -7,6 +7,7 @@ Makefile
7
7
  README.md
8
8
  pyproject.toml
9
9
  docs/RELEASING.md
10
+ docs/SESSION_STATE.md
10
11
  scripts/bench_transcribe.py
11
12
  src/s2t/__init__.py
12
13
  src/s2t/cli.py
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