- Rust 94.2%
- WGSL 2.3%
- Shell 1.6%
- Batchfile 1.2%
- Nix 0.7%
| resources | ||
| src | ||
| .AGENTS.md | ||
| .envrc | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| config.toml | ||
| flake.lock | ||
| flake.nix | ||
| install.bat | ||
| install.sh | ||
| README.md | ||
Naql
Audio transcription and translation tool that produces SRT subtitle files from audio/video input.
For Non-Developers and Windows Users
⚙️ How It Works
Give naql an audio or video file and it produces subtitle files (.srt) you can load in any video player. It listens for speech, writes down what was said, and can translate into other languages.
- Open the file — naql reads your audio or video and prepares it for processing.
- Find speech — it skips over silence and only keeps the parts where someone is talking.
- Transcribe — it writes down what was said, with timestamps for each line. This step runs on your PC — no internet needed.
- Summarise — it reads the whole transcript and writes a short summary so later steps stay consistent with names and terms.
- Correct — it fixes grammar, spelling, and punctuation while keeping the timing intact.
- Translate (optional) — it translates the subtitles into one or more languages you choose.
- Save — it saves
.srtsubtitle files next to your original file.
🔌 Installation (Windows)
Run install.bat as Administrator.
🎮 Quick Start
Double click naql.exe.
👨💻 For Developers
📁 Project Structure
naql.rs/
├── README.md # This file
├── install.sh # Installer script - installs OpenBLAS
├── Cargo.toml # Package manifest and dependencies
├── Cargo.lock # Locked dependency versions - DONT TOUCH
├── config.toml # Default configuration (generated by --generate-conf)
├── flake.nix # Nix flake for the dev environment
├── flake.lock # Locked Nix inputs
├── dependencies/
│ ├── ffmpeg/ # FFmpeg binaries (Windows bundling)
│ ├── openblas/ # OpenBLAS DLLs (Windows bundling)
│ └── qwen/ # Qwen3-ASR-1.7B model files (auto-downloaded)
│ ├── merges.txt
│ ├── model-00001-of-00002.safetensors
│ ├── model-00002-of-00002.safetensors
│ └── vocab.json
└── src/
├── main.rs # CLI entry point, argument parsing, pipeline orchestration
├── lib.rs # Crate root, re-exports all modules
├── dependencies.rs # [1] Downloads missing model files from HuggingFace
├── config.rs # [2] Configuration struct, TOML I/O, default values
├── audio.rs # [3] Audio decoding, resampling, and mono conversion (FFmpeg)
├── vad.rs # [4] Voice Activity Detection using the Earshot model
├── asr.rs # [5] Runs Qwen3-ASR on speech segments (transcribe_file)
├── llm.rs # [6] LLM calls for summarisation, correction, and translation
├── subtitles.rs # [7] SRT generation with balanced line-breaking, RTL detection, orphan fixing
└── fs.rs # [8] File discovery, SRT reading, timestamp parsing
⚙️ How It Works
- Audio Decoding — Reads audio/video files (MP4, MKV, MP3, WAV, FLAC, OGG, M4A, WebM) and converts them to 16 kHz mono PCM using FFmpeg.
- Voice Activity Detection — Uses the Earshot VAD model to find speech segments and skip silence, with configurable threshold and padding.
- Speech Recognition — Transcribes each speech segment with Qwen3-ASR-1.7B (loaded from local model files, no network required for this step).
- Summary — Sends the full transcript to an LLM to generate a summary and key-concept list. This context is used in the next steps to keep terminology consistent.
- Correction — The LLM fixes grammar, spelling, and punctuation in each segment while preserving timestamps.
- Translation (optional) — The LLM translates the corrected segments into one or more target languages.
- SRT Output — Writes
.srtsubtitle files next to the input file (or to a custom output directory). Subtitles are automatically formatted with balanced line-breaking, RTL language detection, and orphan-word prevention.
Each step after VAD requires the previous one, but the pipeline can be entered after step 5 using --corrected-srt to skip audio decoding, VAD, transcription, and correction. It still runs summarisation (for context) and any requested translations.
🔌 Installation
Prerequisites:
- Rust and Cargo (2024 edition)
- Access to an OpenAI-compatible LLM API.
git clone <repo-url> && cd naql.rs
cargo build --release
The Qwen3-ASR-1.7B model files are automatically downloaded from HuggingFace on first run. They are saved to dependencies/qwen/ by default (configurable via --model). To download manually, grab these files from Qwen/Qwen3-ASR-1.7B:
merges.txtmodel-00001-of-00002.safetensorsmodel-00002-of-00002.safetensorsvocab.json
🎮 Quick Start
# Transcribe an Arabic audio file
cargo run --release -- -i audio.mp4 -l ar
# Transcribe and translate to English and French
cargo run --release -- -i audio.mp4 -l ar -t en -t fr
# Skip transcription, just translate an existing corrected SRT
cargo run --release -- --corrected-srt audio.ar.srt -i audio.mp4 -t en
# Generate a config file with defaults
cargo run --release -- --generate-conf
This produces SRT files like audio.ar.srt, audio.en.srt, audio.fr.srt alongside the input.
Command-Line Options
| Flag | Default | Description |
|---|---|---|
-i, --input |
input/ |
Path to an audio/video file or directory |
-m, --model |
dependencies/qwen |
Path to the Qwen-ASR model directory |
-l, --language |
en |
Source language code (e.g. en, ar, zh, fr) |
-t, --target-lang |
(none) | Target language(s) for translation; can be specified multiple times |
-o, --output |
(input dir) | Output directory for SRT files |
-c, --config |
config.toml |
Path to a config TOML file |
--base-url |
https://nano-gpt.com/api/v1 |
OpenAI-compatible LLM API endpoint |
--llm-model |
google/gemma-4-26b-a4b-it |
LLM model name |
--api-key |
$NANOGPT_API_KEY |
API key (prefix with $ to read from an env var) |
--corrected-srt |
(none) | Path to an existing corrected SRT; skips transcription and correction |
--threshold |
0.5 |
VAD speech probability threshold (0.0–1.0) |
--min-speech-ms |
300 |
Minimum speech segment duration in milliseconds |
--min-silence-ms |
200 |
Minimum silence duration to split segments in milliseconds |
--speech-pad-ms |
50 |
Padding around detected speech in milliseconds |
--generate-conf |
— | Write a config.toml with defaults and exit |
Configuration
Run naql --generate-conf to create a config.toml with all defaults. Most CLI flags override the corresponding config value. The config file also lets you customise the LLM prompts used for summarisation, correction, and translation. Prompts support {{summary}} and {{transcription}} placeholders; if those placeholders are absent the text is simply appended. The translation prompt additionally supports the {lang} placeholder, which is replaced with the target language name.
API keys can reference environment variables with a $ prefix (e.g. $MY_API_KEY).