Turn recordings into text — privately, on your own computer.
Meetings, interviews, lectures and live speech. No internet, no account, no upload.
- Nothing leaves your computer. EasyScribe works fully offline. Your audio and transcripts stay on your disk. There are no accounts, no analytics and no update checks.
- Transcribe any recording. Audio or video, one file or many at a time.
- Transcribe as you talk. Record from your microphone and watch the words appear.
- Know who said what. EasyScribe can find the different speakers, and you can give them names.
- Fast on most PCs. It uses your graphics card (NVIDIA, AMD or Intel) when it can, and your processor when it cannot.
- One file, no setup wizard. Download one
.exe, double-click it, and start. No admin rights needed.
Drag your files onto the window, or select Choose files. Then tick the options you want and select Transcribe.
Each colour means one thing everywhere in the app: teal for files, coral for recording, amber for speakers, blue for timestamps and green for done.
You see the status of each file and the current step. You can stop at any time. If one file fails, the others continue.
When it is done, open the transcript or the folder with one click. Each transcript is a plain .txt file next to its recording (or in a folder you choose).
In Transcribe files, tick Name the speakers to find who is talking. (After a recording, use Find speakers; see below.) When the speakers are found, a panel opens in the main window. Play a short sample of each voice and type a name. The names go into the transcript.
Select Record and choose your microphone. Then choose what you want:
- Best quality transcript after recording (the default). EasyScribe records only. When you stop, it makes the transcript at once with the more accurate engine, with times. Then select Find speakers to name the speakers. EasyScribe first shows a rough estimate of how long it takes, and you can stop at any time. The names go into a copy,
<name> (speakers).txt; the first transcript is kept. - Show words as I speak. The words appear as you speak. This is quicker but less accurate.
Both choices save the recording in Documents\EasyScribe. To use a different folder, select Change folder under Save recordings to; EasyScribe remembers it. Select Start recording. The small bar next to the timer shows that the microphone hears you.
When the transcript is ready, you can name the files and find the speakers:
After a live recording, you can still get the best result: select Make best quality transcript. This runs the saved recording through the more accurate engine, with times. Then you can select Find speakers. Your live transcript is kept, and the new one is saved as a separate (best quality).txt file.
If your computer stops during a recording, EasyScribe offers to recover the audio the next time it opens.
After a result, the Name box shows the file's current name. Change it or add to it, then select Rename (or press Enter). You can also ignore it: nothing changes unless you select Rename. A recording and its transcripts are renamed together (Team meeting.wav, Team meeting.txt, Team meeting (speakers).txt). In Transcribe files, only the new transcript is renamed; your original file is not changed.
Select Privacy at the bottom of the window to see what EasyScribe stores and where.
- Download
EasyScribe-<version>.exefrom the Releases page. - Put it in a folder of your choice. A local folder or a USB stick are both good.
- Double-click it. A small Getting ready window shows while the
.exeunpacks itself. The first time, Windows also checks the large downloaded file before it starts, so the window can take up to a minute to show. To make this fast, unblock the file first (see the note below). - Choose where to put EasyScribe (or keep the default) and select Install. This takes about 30 seconds and adds Desktop and Start Menu shortcuts.
- Next time, open EasyScribe from the shortcut. It starts in about one second.
Windows SmartScreen: EasyScribe is not code-signed yet, so Windows may show a warning the first time. Select More info → Run anyway.
Tip: Before the first start, right-click the
.exe, select Properties, select Unblock, then OK. Or in PowerShell:Unblock-File .\EasyScribe-<version>.exe. Then Windows does not show the warning, and Getting ready shows at once. Only do this for a file that you downloaded from this project's Releases page.
Close EasyScribe, then double-click the new .exe. It finds your older version and asks first. Select Update and open to update it in place, or Browse to install in a different folder. Your recordings and logs are kept. If something goes wrong during the update, the previous version is restored.
If EasyScribe 3.1.0 or later is installed, you can download the much smaller EasyScribe-update-vX.exe instead. It keeps the speech models already on your computer, after checking that they are unchanged. It finds your install from its shortcut, or you select Browse and choose your EasyScribe folder. If it says it needs the full download, nothing was changed: use the full .exe.
EasyScribe is portable. It does not use the registry and does not need admin rights. To move it, copy the .exe and the EasyScribe folder next to it.
| Option | Example output |
|---|---|
| Plain text | Hello, this is the first sentence. And here is another. |
| Add timestamps | [00:00:14] at the start of each block of speech |
| Name the speakers | [Alice] / [Bob] at each change of speaker |
With both options:
[00:00:01] [Alice]
Hello, this is the first sentence.
[00:00:14] [Bob]
After a pause, the next block starts here.
Supported files: mp4, mkv, mov, avi, webm, mp3, wav, m4a, flac, ogg, opus, aac.
| Problem | What to do |
|---|---|
SmartScreen blocks the .exe |
Select More info → Run anyway, or unblock the file first (Properties → Unblock). The app is not signed yet. |
| Nothing shows for up to a minute after the first double-click | Windows checks the large downloaded file first. Wait, or unblock the file first (Properties → Unblock). |
The update .exe says it needs the full download |
A model or ffmpeg file in your install is missing or different, or the release changed one. Download the full .exe. |
| "Close EasyScribe" message during an update | EasyScribe is still open. Close it, then select Update and open again. |
| "Model files missing" when it starts | Run the .exe again. The first install may have been stopped. |
| Name the speakers is grey | The speaker models are missing. Run the .exe again. |
| No microphones in the list | Check your microphone in the Windows sound settings. |
Antivirus flags the .exe |
Some antivirus tools flag PyInstaller apps by mistake. Add an exclusion. |
| Transcription is slow | Without a supported graphics card, EasyScribe uses the processor. Long files take longer. Show details shows which graphics card or processor is used. |
The sections below are for developers and IT staff.
| Task | Engine | Device |
|---|---|---|
| File transcription | whisper.cpp whisper-cli, large-v3-turbo q5_0, beam size 5 |
Vulkan GPU (any vendor), else CPU |
| File transcription (fallback) | sherpa-onnx Whisper large-v3-turbo int8, VAD + greedy | CPU |
| Live transcription | sherpa-onnx, Silero VAD chunks | CPU |
| Speaker diarization | sherpa-onnx: pyannote segmentation-3.0 + WeSpeaker ResNet34-LM | CPU |
The device that whisper.cpp actually used is read from its own stderr and shown in the log: the engine (Vulkan or CPU), the GPU's name, and the CPU's name with the threads used. It is never assumed from build flags. sherpa-onnx 1.13.2 has no Vulkan provider, so the sherpa-onnx tasks stay on CPU (see CLAUDE.md, Rule 7).
Audio is decoded with the bundled ffmpeg to 16 kHz mono. Live recordings write raw PCM plus a JSON sidecar, so recovery.py can rebuild a WAV after a crash.
EasyScribe never sends data off the computer. How this is enforced:
- All models are local. They load from absolute paths in the install folder. There are no HuggingFace Hub downloads.
- Network access is blocked in the process.
src/offline_guard.pyruns first inmain.py, before any other import. It refuses every socket connection and DNS lookup that is not to loopback, disables proxies (NO_PROXY=*) and sets the usual opt-out variables (HF_HUB_OFFLINE,DO_NOT_TRACK, ...). A blocked attempt is logged. - ffmpeg and ffprobe read local files only. They run with
-protocol_whitelist file, so a playlist or concat file cannot make them fetch a URL. - No network code.
tests/test_offline_guard.pyfails if a module insrc/orlauncher/imports a network library (urllib,http,requests,webbrowser, ...). - Temporary audio is deleted. Converted WAV files and whisper.cpp output are removed after each file, at startup and at exit.
| Data | Location | Kept until |
|---|---|---|
| Transcripts | Next to each recording, or the folder you choose | You delete them |
| Recordings | Documents\EasyScribe, or the folder you choose |
You delete them |
| Technical logs | logs/ in the install folder. File names and progress only, never transcript text |
The last 10 are kept |
To remove all data, delete your transcripts and the EasyScribe folder.
EasyScribe-<version>.exe (launcher.exe, PyInstaller one-file)
└── app.bundle (zip: EasyScribe.exe + _internal/ + models/ + whispercpp/ + ffmpeg/ + licenses/)
The launcher extracts app.bundle once, into an EasyScribe\ folder:
EasyScribe\
EasyScribe.exe
.easyscribe-install.json <- install marker (version, shortcuts)
_internal\ <- PyInstaller runtime (DLLs, .pyd files, assets)
models\
whisper\ <- sherpa-onnx Whisper large-v3-turbo int8
diarization\ <- segmentation.onnx, embedding.onnx
silero_vad.onnx
whispercpp\ <- whisper-cli.exe, ggml-large-v3-turbo-q5_0.bin, *.dll
ffmpeg\ <- ffmpeg.exe, ffprobe.exe
LICENSE.txt <- EasyScribe license (MIT)
THIRD-PARTY-NOTICES.txt <- included components, their licenses and source
licenses\ <- license texts (assets/collect_licenses.py)
recordings\ <- recordings in progress (crash recovery) and settings.json (user data)
logs\ <- rotating log files (user data)
temp\ <- temporary WAV files (auto-cleaned)
Updates. The launcher compares the version in the install marker with its own version:
- Same or newer install: it opens the installed
EasyScribe.exedirectly. It never downgrades. - Older install: it shows the installer window and waits. Only when the user selects Update and open does it move the app files to
.easyscribe-old\, extract the new files, then delete the backup. On any failure, the backup is moved back.recordings\andlogs\are never moved. If a file is locked (the app is open), the update stops and the user is told to close EasyScribe. - If an update is interrupted (power loss), the next start restores the backup first.
- The update
.exehas a bundle withoutmodels\,ffmpeg\and the whisper.cpp model (assets/make_update_bundle.py). It lists their SHA-256 in.easyscribe-update.json. The launcher checks the installed copies before it changes anything, then keeps them (a kept file inside a replaced folder is hard-linked from the backup). It cannot do a new install.
Start-up splash. The PyInstaller one-file bootloader unpacks app.bundle (about 1.5 GB) to %TEMP% before any Python code runs. This can take a minute. A PyInstaller Splash (assets/splash.png) shows at once during that time; the launcher closes it when its own window opens.
Why not a "no-extract" single exe? whisper-cli, ffmpeg and the models (about 1.5 GB) must be real files on disk. A one-file app that unpacks to %TEMP% at each start would copy 1.5 GB every time. Extract-once keeps start-up at about one second and still needs no installer, registry or admin rights.
src/
main.py Entry point: offline guard, logging, orphan recovery, GUI
offline_guard.py Blocks all non-loopback network access (imported first)
config.py Paths, constants and APP_VERSION
common.py Shared helpers (CancelledError, ...)
logger.py Rotating log file setup
ffmpeg_wrapper.py Subprocess ffmpeg/ffprobe with cancellation polling
transcriber.py File transcription (whisper.cpp if bundled, else sherpa-onnx)
whispercpp_wrapper.py Subprocess whisper-cli: beam search, Vulkan/CPU device log
diarizer.py sherpa-onnx speaker diarization
mic_recorder.py sounddevice capture + crash-safe PCM writer
live_transcriber.py Silero VAD loop + OfflineRecognizer for live mode
recovery.py Orphaned .pcm scanner and WAV recovery
gui.py CustomTkinter UI with threaded workers
rename.py Renames a recording and its transcripts together (the Name box)
transitions.py Windows only: fade out and in when the screen changes
win_paint.py Windows only: paints window backgrounds at once (no black blocks)
launcher/
launcher.py Extract-once installer and version-aware updater
launcher.spec PyInstaller one-file spec for the launcher
assets/
EasyScribe.ico/.png App icon (both .exe files, all windows, shortcuts)
make_icon.py Regenerates the icon from the logo design (needs Pillow)
splash.png "Getting ready" window shown while the .exe unpacks
make_splash.py Regenerates splash.png (needs Pillow and customtkinter)
version_resource.py Windows file-version info for both specs, from APP_VERSION
make_update_bundle.py Builds the bundle for the small EasyScribe-update-vX.exe
tests/ Fast offline checks; run all with `python tests/run_all.py`
Releases are built by GitHub Actions: Actions → Build and Publish Release, with the tag v + APP_VERSION. The workflow:
- Installs the pinned Python dependencies from
requirements.txtand runs the unit tests. - Downloads the models and ffmpeg.
- Builds
whisper-cliwith-DGGML_VULKAN=ONand checks that it starts. - Runs PyInstaller for the app and validates the result (
tests/validate_build.py). - Assembles the app folder, validates it again and checks that the bundled
whisper-clistarts. - Packs
app.bundleinto the launcher and publishes the release.
The version is set in one place: APP_VERSION in src/config.py. Keep VERSION in launcher/launcher.py the same; tests/test_version.py checks this.
| Requirement (build machine) | Notes |
|---|---|
| Windows 10/11 64-bit | Build and target platform |
| Python 3.11 | Used by CI |
| Internet access | Only during the build, to get models and tools |
Before you change packaging, read CLAUDE.md. It lists the rules learned from earlier build failures.
This project is released under the MIT License.
The app includes third-party programs and models. Each one keeps its own license:
- FFmpeg (GPL v3). The source and a written offer are in
licenses/THIRD-PARTY-NOTICES.txt. - whisper.cpp, ONNX Runtime, PortAudio, the Whisper weights, Silero VAD and pyannote segmentation (MIT).
- sherpa-onnx (Apache 2.0).
- The WeSpeaker ResNet34-LM speaker model (CC BY 4.0, trained on VoxCeleb).
See licenses/THIRD-PARTY-NOTICES.txt and the texts in licenses/. The build copies them, with the Python and Python package licenses, into the app folder (assets/collect_licenses.py).








