- ASR (Automatic Speech Recognition) - Raw algorithm listening to audio, identifying words.
- STT (Speech-to-Text) - Wraps ASR with punctuation, speaker identification, formatting.
- Captioning - STT output synchronized with timeline for video (e.g., SRT).
- File input: file → ffmpeg decode → chunked f32 stream → TDT inference → detokenization → subtitle regrouping (DP) → SRT output
- URL input: URL → yt-dlp download → ffmpeg decode → chunked f32 stream → TDT inference → SRT output
Use pixi run for all commands. Read pixi.toml for available tasks, features, and environments.
melops/src/ort.rs::init() tries providers in order: CUDA → TensorRT → OpenVINO → DirectML → CoreML → CPU.
Three cache directories (.cache/melops/):
- models/ - Downloaded ONNX models from HuggingFace Hub (via
hf-hub) - transcriptions/ - Cached segments keyed by audio content hash (via
cacache) - ort/ - OpenVINO compilation cache (IR files, faster reloads)
Cache strategy (--cache-strategy): auto (default), use (error if missing), force (recompute).
Three distinct concerns:
- CLI State - Raw clap arguments
- Validated State - Type-safe configurations
- Application State - Runtime objects that can fail
pub fn run(command: CapCommand) -> Result<()> {
let config = CapConfig::try_from(command.args)?; // CLI → Validated
let cache = Cache::load(CacheConfig::from(command.cache_args))?; // Validated → App
let model = config.model.load()?;
caption(&config, &model, &mut cache)
}Validate early before expensive operations. Each domain function has single responsibility with dependencies passed in. Cache owns refresh flags — no separate refresh parameters.
- NeMo vocab: 8192 tokens (IDs 0–8191); decoder output: 8198 logits = 8192 vocab + 1 blank + 5 duration
blank_id = vocab_size = 8192— no<blk>string token in tokenizer.json or vocab.txt- Decoder filters blanks during greedy search; detokenizer never receives blank tokens
Never add dependencies manually. Use cargo add, cargo update.
pixi run cargo add pyo3@0.27
pixi run cargo update -p pyo3Single line, sorted: std traits alphabetically, then 3rd party alphabetically.
#[derive(Clone, Debug, Default, IntoPyObject)] // ✓ Clone, Debug, Default (std) → IntoPyObject (pyo3)#[test]
#[ignore = "network I/O"]
fn downloads_from_youtube() { }Use eyre in libraries; color-eyre in binaries/tests for colored output.
- stdout: data output only (SRT subtitles, JSON results)
- stderr: diagnostics, progress, timing (via
tracing)
tracing::debug!(current = i, total, "processing chunk");
tracing::info!(%duration, "model loaded");
tracing::info!(path = ?audio_path.display(), "transcribing audio");Use % for Display, ? for Debug. Debug format for paths enables IDE clickability (wraps in quotes).
pub struct Args {
#[pyo3(item("ffmpeg"))] // Maps to Python key "ffmpeg"
pub key: Vec<String>,
}Angular convention. Scale matches change size.
Format: <type>(<scope>): <subject> — header ≤50 chars, body wrap at 72, imperative mood.
Types: feat, fix, refactor, style, docs, test, chore
Scopes: cli, dl, parakeet
Explain why over what — reason for change, behavior users notice, problem being solved.
pixi run -e openvino cargo test --workspace
pixi run -e openvino cargo clippy --fix --workspace --allow-dirty
pixi run -e openvino cargo clippy --workspace