diff --git a/authors/telemark_digital_publisher.md b/authors/telemark_digital_publisher.md new file mode 100644 index 00000000..cfbb5f38 --- /dev/null +++ b/authors/telemark_digital_publisher.md @@ -0,0 +1,12 @@ +Author: Telemark Digital Publisher Title: Technical Publisher Description: +Telemark Digital Publisher builds and documents practical developer workflows +for automation, AI tooling, and reproducible open-source projects, with a focus +on clear setup paths, testable examples, and careful disclosure of tool-assisted +work. Author Image: +![telemarkdigital-publisher](https://github.com/telemarkdigital-publisher.png) +Author LinkedIn: Author Twitter: Company Name: Telemark Digital Company +Description: Technical publishing and automation studio for practical +developer tooling. Company Logo Dark: +![telemarkdigital-publisher](https://github.com/telemarkdigital-publisher.png) +Company Logo White: +![telemarkdigital-publisher](https://github.com/telemarkdigital-publisher.png) diff --git a/definitions/20260816_definition_local_speech_to_text.md b/definitions/20260816_definition_local_speech_to_text.md new file mode 100644 index 00000000..1fff2136 --- /dev/null +++ b/definitions/20260816_definition_local_speech_to_text.md @@ -0,0 +1,26 @@ +--- +title: 'Local Speech-to-Text' +description: 'Speech recognition that runs on local hardware instead of sending audio to a hosted API.' +date: 2026-08-16 +author: 'Telemark Digital Publisher' +--- + +# Local Speech-to-Text + +## Definition + +Local speech-to-text is an audio transcription workflow where the speech +recognition model runs on a developer's own machine, workstation, or +containerized environment instead of uploading audio to a hosted transcription +API. The model turns spoken language in an audio or video file into text while +the input media stays inside the local environment. + +## Context and Usage + +Local speech-to-text is useful when developers need repeatable tests, offline +workflows, predictable costs, or stronger control over source audio. In a +[development environment]() +such as a Daytona workspace, teams can install a local transcription engine, +pin its dependencies, and run the same command against meeting recordings, demo +videos, lectures, podcasts, or support-call exports without adding hosted API +credentials to the project. diff --git a/guides/20260816_offline_transcription_with_sapat_and_daytona.md b/guides/20260816_offline_transcription_with_sapat_and_daytona.md new file mode 100644 index 00000000..dcf877b5 --- /dev/null +++ b/guides/20260816_offline_transcription_with_sapat_and_daytona.md @@ -0,0 +1,335 @@ +--- +title: 'Offline Transcription with Sapat and Daytona' +description: 'Run a local faster-whisper transcription workflow for video files inside a reproducible Daytona workspace.' +date: 2026-08-16 +author: 'Telemark Digital Publisher' +tags: ['python', 'daytona', 'speech-to-text', 'ai'] +--- + +# Offline Transcription with Sapat and Daytona + +# Introduction + +Speech-to-text looks simple from the outside: give a tool a video file, get a +transcript back. The hidden work is in the environment. A useful transcription +workflow needs `ffmpeg`, Python dependencies, model files, repeatable command +flags, and a place to test changes without filling your laptop with one-off +packages. That is exactly where a +[Daytona workspace]() +helps. + +This guide walks through a local, offline-first transcription setup using +[Sapat](https://github.com/nkkko/sapat), a multi-provider speech-to-text CLI. +The workflow uses the proposed Sapat +[faster-whisper provider](https://github.com/nibzard/sapat/pull/76) so audio can +stay inside the workspace instead of being uploaded to a hosted transcription +API. You will create the workspace, install the local provider, transcribe a +video, tune the Whisper settings, and validate the output in a way another +developer can repeat. + +![Offline transcription workflow](assets/20260816_offline_transcription_sapat_daytona_architecture.svg) + +## TL;DR + +- Create a Daytona workspace from Sapat so Python, `ffmpeg`, and project files + live in a reproducible development environment. +- Use Sapat's local `faster_whisper` provider when you want + [local speech-to-text]() + without hosted API keys. +- Start with the `small` model on CPU using `int8` compute, then tune model + size, beam size, language, VAD, and prompts for your source material. +- Keep test media small, do not commit private recordings, and document the + exact command that produced each transcript. + +## What Sapat Adds to Whisper + +Whisper-style transcription engines are powerful, but their raw setup can feel +scattered. You might run one command to extract audio, another to call a model, +another to clean up temporary files, and another to save the transcript where +the rest of your project expects it. Sapat wraps those steps behind one CLI. + +The current Sapat project already supports several hosted and local providers, +including Azure OpenAI, Groq, OpenAI-compatible endpoints, WhisperX, +whisper.cpp, Vosk, and Moonshine. The faster-whisper provider adds another local +path. It uses the Python package +[faster-whisper](https://pypi.org/project/faster-whisper/), which exposes a +`WhisperModel` class and runs Whisper inference through CTranslate2. In +practice, that gives developers a provider that can run on CPU with int8 +quantization or on GPU with larger models when hardware is available. + +The important difference is control. Hosted transcription APIs are convenient, +but they require credentials and may create usage costs. A local provider lets +you keep sensitive audio inside the workspace, pin the dependency stack, and run +the same transcript command during local testing, review, and documentation. + +## Prerequisites + +You need a few pieces before starting: + +- A working Daytona installation. +- Docker available to Daytona. +- Basic familiarity with + [Python]() and + [Git](). +- A short test video or audio file that you are allowed to process. + +For the cleanest first run, use a short MP4 or WAV sample under one minute. +Keep real customer calls, internal meetings, medical recordings, and financial +data out of the tutorial. You can validate the workflow with a synthetic clip +or a public-domain sample before moving to private media. + +## Step 1: Create a Daytona Workspace + +Start from the Sapat repository. If the faster-whisper provider has already +landed in Sapat, use the upstream project: + +```bash +daytona create https://github.com/nkkko/sapat --code +``` + +If you are testing the provider before merge, create the workspace from the +companion branch instead: + +```bash +daytona create https://github.com/telemarkdigital-publisher/sapat --code +``` + +Once the workspace opens, confirm the repository is available: + +```bash +pwd +ls +python --version +``` + +You should see Sapat's `README.md`, `pyproject.toml`, `sapat` package directory, +and `tests` directory. If your workspace starts in another directory, move into +the cloned repository before continuing. + +## Step 2: Install Sapat with faster-whisper + +Create a virtual environment inside the workspace and install Sapat in editable +mode. The editable install is useful while you test provider changes because the +CLI sees your local source files immediately. + +```bash +python -m venv .venv +source .venv/bin/activate +python -m pip install --upgrade pip +python -m pip install -e '.[faster-whisper,dev]' +``` + +On Windows-based workspaces, activate with: + +```powershell +.\.venv\Scripts\Activate.ps1 +python -m pip install --upgrade pip +python -m pip install -e '.[faster-whisper,dev]' +``` + +The `faster-whisper` extra installs the local inference engine. The `dev` extra +installs test tooling so you can run the provider tests before trusting the +workflow. + +## Step 3: Configure Local Inference + +The faster-whisper provider does not need hosted API keys. It does accept +environment variables for model runtime behavior: + +| Variable | Suggested first value | Purpose | +| --- | --- | --- | +| `FASTER_WHISPER_DEVICE` | `cpu` | Runs on CPU first for portability. Use `cuda` only when the workspace has GPU access. | +| `FASTER_WHISPER_COMPUTE_TYPE` | `int8` | Keeps CPU memory and compute requirements lower. | +| `FASTER_WHISPER_DOWNLOAD_ROOT` | `.models/faster-whisper` | Stores downloaded models in a project-local cache. | +| `FASTER_WHISPER_VAD_FILTER` | `false` | Turns voice activity detection on only when silence trimming is useful. | +| `FASTER_WHISPER_WORD_TIMESTAMPS` | `false` | Enables word-level timing only when needed. | + +Create or update your `.env` file: + +```bash +cp .env.example .env +printf '\nFASTER_WHISPER_DEVICE=cpu\n' >> .env +printf 'FASTER_WHISPER_COMPUTE_TYPE=int8\n' >> .env +printf 'FASTER_WHISPER_DOWNLOAD_ROOT=.models/faster-whisper\n' >> .env +``` + +Model files may download on the first run. That is not a hosted transcription +call, but it is still network activity. In production teams, pre-warm the model +cache in your workspace image or CI environment so runs are faster and more +predictable. + +## Step 4: Add a Test Video + +Place your test file in a local `samples` directory: + +```bash +mkdir -p samples transcripts +cp ~/Downloads/demo-video.mp4 samples/demo-video.mp4 +``` + +If you do not have a test video yet, generate a small synthetic audio file with +your usual media tooling or use a public sample you are licensed to process. Do +not commit the source recording unless it is intentionally public. Add local +media paths to `.gitignore` when needed: + +```bash +printf '\nsamples/*.mp4\nsamples/*.wav\ntranscripts/*.txt\n.models/\n' >> .gitignore +``` + +That keeps the reproducible commands in the repository while leaving private +audio, generated transcript files, and model caches out of version control. + +## Step 5: Run the Transcription + +Run Sapat with the local provider: + +```bash +sapat samples/demo-video.mp4 \ + --provider faster_whisper \ + --model small \ + --language en \ + --quality H +``` + +Sapat handles the media conversion step, calls the selected provider, and writes +a `.txt` transcript next to the input file. The first run may take longer +because faster-whisper downloads the selected model. Later runs reuse the cache. + +For a multilingual clip, either pass the expected language code or let Whisper +detect it: + +```bash +sapat samples/interview.mp4 \ + --provider faster_whisper \ + --model medium \ + --language es \ + --transcription-prompt "Names: Daytona, Sapat, faster-whisper" +``` + +The prompt is not a chat prompt. It is an initial transcription hint. Use it for +product names, speaker names, acronyms, or technical vocabulary that the model +might otherwise spell incorrectly. + +## Step 6: Tune Whisper Settings + +Start small and increase complexity only when the transcript needs it: + +- Use `--model tiny` or `--model base` for smoke tests. +- Use `--model small` for a better balance between speed and quality on CPU. +- Use `--model medium` or larger when accuracy matters more than runtime. +- Set `FASTER_WHISPER_BEAM_SIZE=1` for faster drafts and `5` for a steadier + final transcript. +- Set `FASTER_WHISPER_VAD_FILTER=true` when long silent sections waste time. +- Set `FASTER_WHISPER_WORD_TIMESTAMPS=true` only if downstream tooling needs + word-level timing. + +If you see repeated phrases or hallucinated endings, try a smaller beam size, +turn off conditioning between windows, and include a short initial prompt: + +```bash +printf 'FASTER_WHISPER_CONDITION_ON_PREVIOUS_TEXT=false\n' >> .env +sapat samples/demo-video.mp4 \ + --provider faster_whisper \ + --model small \ + --language en \ + --transcription-prompt "Short product demo about Sapat in Daytona." +``` + +The goal is not to chase every possible model flag. The goal is to keep your +workflow reproducible: command, model, environment variables, input file, and +output transcript should all be easy to explain. + +## Step 7: Validate the Workflow + +Before sharing the setup with teammates, run the local provider test group: + +```bash +python -m pytest tests/providers/test_group_d.py -q +``` + +For the companion provider patch, the focused validation passed with: + +```text +38 passed +``` + +The full Sapat test suite also passed locally: + +```text +182 passed +``` + +After tests pass, inspect the transcript manually. Automated tests prove the +provider calls the right code paths, but humans still need to check names, +domain terms, timestamps, and whether the transcript is suitable for its next +use. A practical review checklist is: + +- Does the transcript preserve speaker names and product names? +- Are obvious false starts or repeated phrases acceptable for your use case? +- Did the command use the intended model and language? +- Is the source media excluded from commits when it should remain private? +- Can a teammate reproduce the same run from the README or guide? + +## Common Issues and Troubleshooting + +**Problem:** The provider is not listed by Sapat. + +**Solution:** Confirm the optional package is installed in the active virtual +environment: + +```bash +python -m pip show faster-whisper +python -c "from faster_whisper import WhisperModel; print(WhisperModel)" +``` + +If the import fails, reinstall the extra: + +```bash +python -m pip install -e '.[faster-whisper]' +``` + +**Problem:** The first transcription run is slow. + +**Solution:** The model is likely downloading or warming up. Set +`FASTER_WHISPER_DOWNLOAD_ROOT` to a stable workspace path and reuse that path +between runs. For demos, start with `tiny`, `base`, or `small`. + +**Problem:** CPU transcription runs out of memory. + +**Solution:** Use `FASTER_WHISPER_COMPUTE_TYPE=int8`, choose a smaller model, +and process shorter clips. If your Daytona workspace has GPU support, use +`FASTER_WHISPER_DEVICE=cuda` and a compute type appropriate for that hardware. + +**Problem:** Words are mostly right, but product names are wrong. + +**Solution:** Pass a short `--transcription-prompt` with names, acronyms, and +specialized terms. Keep it factual and compact. + +**Problem:** Private audio appeared in a commit. + +**Solution:** Remove the file from the commit, add media paths to `.gitignore`, +and rotate any exposed data if the recording contained sensitive information. +For safer collaboration, keep only commands, fixtures, tests, and synthetic +samples in the repository. + +## Conclusion + +Sapat gives you one CLI for a multi-provider transcription workflow. Daytona +gives that workflow a reproducible place to run. Adding faster-whisper to the +mix creates a strong local option for developers who want Whisper-quality +transcripts without sending source media to a hosted API. + +The practical pattern is simple: create the workspace, install the local +provider, configure CPU-friendly defaults, run a small sample, then document the +exact command and validation results. Once that foundation works, you can scale +the same approach to meeting notes, demo videos, lecture archives, podcast +drafts, or any other workflow where transcription quality and environment +repeatability both matter. + +## References + +- [Sapat repository](https://github.com/nkkko/sapat) +- [Companion faster-whisper provider PR](https://github.com/nibzard/sapat/pull/76) +- [faster-whisper on PyPI](https://pypi.org/project/faster-whisper/) +- [faster-whisper source on GitHub](https://github.com/SYSTRAN/faster-whisper) +- [Daytona documentation](https://www.daytona.io/docs/) diff --git a/guides/assets/20260816_offline_transcription_sapat_daytona_architecture.svg b/guides/assets/20260816_offline_transcription_sapat_daytona_architecture.svg new file mode 100644 index 00000000..453bb500 --- /dev/null +++ b/guides/assets/20260816_offline_transcription_sapat_daytona_architecture.svg @@ -0,0 +1,38 @@ + + Offline transcription workflow with Daytona and Sapat + A diagram showing video input, Daytona workspace, Sapat preprocessing, faster-whisper local inference, transcript output, and validation. + + + Offline transcription in a Daytona workspace + Audio stays local while the provider, model, and validation are pinned in one reproducible setup. + + + Video or audio + MP4, WAV, MP3 + + Daytona + Workspace + + Sapat + Preprocess + + faster-whisper + Local model + + Transcript output + Text file plus test evidence + + + + + + + + + + + + + + No hosted STT call is required for the faster-whisper path. The only network use is dependency/model download during setup, which can be pinned or cached. +