Skip to content

Repository files navigation

SmuggyTranscriber

A dead-simple desktop app that turns an audio file into text. Pick a file, click Transcribe, then Copy or Save as .txt. Auto-detects the language (Hindi, English, Hinglish, and more), with an optional language selector.

Two ways to transcribe, switchable at any time from the main screen:

Engine Needs Speed & accuracy
Groq · cloud (whisper-large-v3) A free API key and an internet connection Fastest, most accurate
Local · on this device (faster-whisper) Nothing — no key, no internet Slower, a little less accurate

Local transcription runs entirely on your own computer: your audio never leaves the machine, and there's no file-size limit. It's also the only way to use the app without signing up for anything.

SmuggyTranscriber welcome screen


For users (Windows)

  1. Download SmuggyTranscriber.exe from the Releases page.
  2. Double-click it.
    • Windows may show a SmartScreen warning because the app isn't code-signed. Click More info → Run anyway. (It's safe — it's just unsigned.)
  3. The first time, it asks how you want to transcribe:
    • Use a Groq API key — it walks you through getting a free one (see below). Your key is stored privately on your own machine; it's never shared or uploaded anywhere but to Groq.
    • Transcribe on this device — no key, no sign-up. The first run downloads the speech model (about 148 MB for the default base), then it works offline forever.
  4. Click Choose audio file…, pick the Language (or leave on Auto), and click Transcribe.
  5. Use Copy or Save as .txt for the result.

No file-size limit. Large files are compressed and split automatically for Groq (which rejects uploads over 25 MB); the local engine sends nothing anywhere, so it has no limit at all. Supported formats include .mp3, .wav, .m4a, .ogg, .webm, .mp4, .flac.

Choosing a local model

When the local engine is selected, a second dropdown picks the model size. Bigger is more accurate but slower and a larger one-time download. Models are stored per-user (%LOCALAPPDATA% on Windows, ~/Library/Application Support on macOS), never inside the app.

Model Download Notes
tiny 78 MB Fastest, roughest
base 148 MB Default — good balance
small 486 MB Noticeably better, ~3× slower
medium 1.5 GB Best local quality, slow on CPU

Downloading a model needs an internet connection once. If you're offline and haven't downloaded one yet, the app says so rather than failing silently.

Hindi → Hinglish conversion needs a Groq key even on the local engine, because the romanisation step runs on Groq's llama-3.1-8b-instant. Without a key that toggle is disabled; everything else works. You can add a key later via API key in the top-right of the main screen.

Getting your free Groq API key

Optional — skip this entirely if you're happy with local transcription. The app shows these same steps when you pick the Groq route. Head to console.groq.com and:

1. Sign in (or create a free account).

Sign in to the Groq Console

2. Open API Keys, then click Create API Key.

Open the API Keys page

3. Give it any name and click Submit.

Create an API key

4. Copy the key — it starts with gsk_ and is shown only once. Paste it into the app and click Save & Continue.

Copy the new API key


For developers

Run it

python -m venv venv
venv\Scripts\activate          # Windows
# source venv/bin/activate     # macOS/Linux

pip install -r requirements.txt
python app.py

For dev convenience, the app also reads GROQ_API_KEY from a .env file (copy .env.example to .env), so you don't have to paste a key each run. A real, saved key always takes precedence over the env var.

Self-checks

core.py runs its own assertions — no test framework, no fixtures:

python core.py              # split planning, engine ids, the PyAV stub
python core.py some.mp3     # ...plus real splitting and audio windowing

CI runs the first form on both runners before packaging.

Command-line version

transcribe.py is a tiny CLI that transcribes a hardcoded file. It shares its logic with the app via core.py:

python transcribe.py    # transcribes ReelAudio-39184.mp3 -> transcription.txt

Project layout

File Purpose
core.py GUI-free logic: key validation, Groq + local transcription (self-checking)
settings.py Per-user key, engine and model choice via QSettings
theme.py Green-on-black design language: palette, fonts, Qt stylesheet
app.py PySide6 GUI (onboarding, drop-zone, transcribing, result)
transcribe.py CLI, imports from core.py
updater.py Self-update from GitHub Releases, in packaged builds only (self-checking)
verify_bundle.py CI check that a built artifact really contains the local engine
assets/ Bundled fonts, app icon (.ico/.icns), logo, setup screenshots

How the apps are built

A GitHub Actions workflow (.github/workflows/build.yml) packages the app with PyInstaller (--onefile --windowed --name SmuggyTranscriber) on two runners in parallel:

  • Windows (windows-latest) → SmuggyTranscriber.exe
  • macOS (macos-latest) → SmuggyTranscriber.app, zipped with ditto into SmuggyTranscriber-macos.zip

The local engine adds faster-whisper and CTranslate2 to the bundle (macOS goes from ~76 MB to ~86 MB zipped). PyAV and onnxruntime are deliberately excluded — faster-whisper imports them but we never reach either, and PyAV alone bundles a whole second copy of FFmpeg. Model weights are never bundled; they download on first use. See the comments in the workflow before changing those flags.

On every push to main each build is uploaded as a workflow artifact (SmuggyTranscriber-windows / SmuggyTranscriber-macos). Pushing a v* tag (e.g. git tag v1.0 && git push --tags) also attaches both to a GitHub Release for users to download. No Windows or Mac machine is needed to build — the runners do it.

The macOS .app is unsigned, so the first launch needs right-click → Open (or System Settings → Privacy & Security → Open Anyway) to get past Gatekeeper — the Mac equivalent of the Windows SmartScreen prompt.

How the apps update themselves

Every launch, a packaged build asks GitHub for the latest release (updater.py). If its tag is newer than the VERSION baked into the running app, it offers Update now / Later; "Update now" downloads that release's asset, moves the old app aside as .old, drops the new one in its place and relaunches. The .old is deleted on the next launch. A dev checkout never does any of this — it updates with git. Failures are logged and never shown, so being offline or rate-limited just means no prompt.

Cutting a release: bump VERSION in the same commit as the tag. The app compares the release tag against its own VERSION, so tagging v1.3.0 while VERSION still says 1.2.0 ships a build that tells every user there's an update, forever, and re-downloads itself on every launch. Both CI jobs fail the build on a mismatch rather than let that reach a release.

Because the download is programmatic it carries no quarantine flag, so an updated app skips the Gatekeeper dance above — that only applies to the first copy, downloaded by hand.

About

Dead-simple desktop app to transcribe audio with Groq Whisper (PySide6, ships as a Windows .exe)

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages