Local CLI for extracting subtitles and aligned timestamps from audio and video.
Project description
echoalign-asr-mlx
easr is a local Apple Silicon CLI that turns audio and video files into
subtitle files (.srt, .vtt) and timestamp-aligned JSON.
Use it when you want local transcription, readable subtitles, and machine-friendly alignment data without running a server.
Current scope:
- runtime target: macOS on Apple Silicon
- backend: MLX with Qwen3 ASR and Qwen3 ForcedAligner
- output: SRT, WebVTT, and JSON
- not included yet: translation, speaker diarization, Linux/Windows support
What You Get
For each supported media file, easr writes:
<name>.srtfor subtitle players and editors<name>.vttfor web video workflows<name>.jsonfor downstream tools that need segments, tokens, timestamps, language metadata, and provider metadata<name>.metrics.jsonwhen--verboseis enabled
easr accepts files, directories, and glob patterns. Directory scans are
non-recursive by default, and recursive processing is opt-in with --recursive.
Requirements
- macOS on Apple Silicon
- Python
>=3.14,<3.15 ffmpegandffprobeavailable onPATHuvif you run from a source checkout- network access on first run so the models can be downloaded from Hugging Face
Install the media tools with Homebrew:
brew install ffmpeg
Default provider models:
Installation
Install from a published Python package:
python3.14 -m pip install "echoalign-asr-mlx[mlx]"
easr --help
Run from a source checkout:
uv sync --extra mlx
uv run --python 3.14 --extra mlx easr --help
If you use the source checkout flow, prefix examples in this README with:
uv run --python 3.14 --extra mlx easr ...
Quick Start
Transcribe one file:
easr ./demo.mp4
Write outputs to a custom directory:
easr ./demo.mp4 --output-dir ./subtitles
Process a directory:
easr ./media
Process a directory recursively:
easr ./media --recursive
Process a glob pattern:
easr "./media/**/*.mp4" --recursive
Export token-level subtitle and JSON views:
easr ./demo.mp4 --granularity token
Show detailed progress and write metrics:
easr ./demo.mp4 --verbose
Supported Formats
Audio:
wavmp3m4aflacaac
Video:
mp4movm4vmkvwebm
Output Layout
Default output directory name: outputs.
When the input is a single file, outputs are written next to that file:
/project/media/demo.mp4
/project/media/outputs/demo.srt
/project/media/outputs/demo.vtt
/project/media/outputs/demo.json
When the input is a directory or the current directory, outputs are written under that input root:
/project/media/
a.mp4
nested/b.wav
/project/media/outputs/
a.srt
a.vtt
a.json
nested/b.srt
nested/b.vtt
nested/b.json
Use --output-dir to choose another output root.
JSON Output
The JSON export keeps the readable transcript and the alignment data used to create subtitle views.
Common top-level fields:
source_pathprovider_namedetected_languagesegmentssource_mediagranularityitems
Each segment includes text, start/end timestamps, language metadata, optional
speaker metadata, and token timing when available. source_media includes the
prepared audio path, VAD metadata, and provider diagnostics such as processing
strategy, duration, window counts, quality pass counts, and window diagnostics.
CLI Options
| Option | Meaning |
|---|---|
inputs |
File, directory, or glob pattern. Defaults to the current directory. |
--recursive |
Recursively scan directory inputs. |
--output-dir PATH |
Override the default output directory root. |
--granularity sentence |
Use segment boundaries for subtitle entries and JSON items. This is the default. |
--granularity token |
Use token timing for subtitle entries and JSON items. |
--no-vad |
Disable voice activity detection preprocessing. |
--verbose |
Print detailed progress and write <name>.metrics.json. |
--version |
Show the installed package version. |
--help |
Show CLI help. |
VAD Preprocessing
Voice activity detection is enabled by default. easr scans the prepared audio,
finds likely speech ranges, groups them into padded chunks, and asks the
provider to process only those ranges. Final subtitle timestamps remain on the
original media timeline.
Disable VAD when you want full-duration provider processing:
easr ./demo.mp4 --no-vad
If VAD fails, easr falls back to full-duration processing. If VAD succeeds and
finds no speech, easr writes successful empty subtitle outputs.
Shell Completion
Fish shell users can generate or install completions:
easr completion fish
easr completion install fish
The install command writes:
~/.config/fish/completions/easr.fish
Existing completion files at that path are overwritten.
Runtime Behavior
- exit code
0: all discovered files processed successfully - exit code
1: no supported input was found, environment preflight failed, or at least one file failed in a batch - batch files are processed one by one
- failures are reported per file to stderr
- other files continue processing after a per-file failure
- the first run may be slower because model files are downloaded and cached
Troubleshooting
Missing ffmpeg or ffprobe
Install the media tools and make sure they are visible from the shell running
easr:
brew install ffmpeg
which ffmpeg
which ffprobe
MLX or Metal preflight failed
Check that you are on Apple Silicon, using the expected Python environment, and installed the MLX runtime extra:
python3.14 -m pip install "echoalign-asr-mlx[mlx]"
For a source checkout:
uv sync --extra mlx
uv run --python 3.14 --extra mlx easr --help
First run is slow
This is expected when the Qwen3 model files are downloaded and the local cache is warmed. Later runs should be faster.
Current Limitations
- Translation is not implemented.
- Speaker diarization is not implemented.
- Subtitle segmentation quality depends on model and alignment behavior.
- The public CLI does not expose provider selection.
Developer Documentation
Development setup, test commands, build instructions, and release notes live in docs/development.md.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file echoalign_asr_mlx-0.5.0.tar.gz.
File metadata
- Download URL: echoalign_asr_mlx-0.5.0.tar.gz
- Upload date:
- Size: 846.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3681c423ccba5ed1c451e35d06476b5dd11cead8723f319b505cf1f8efb8a7f0
|
|
| MD5 |
a97f33849a06ecc3854e59c5ff02b613
|
|
| BLAKE2b-256 |
8bc3007b3a89649ba76d003e5e1fdc2783cbea8a39cb91c58c14e13c8a151ce5
|
Provenance
The following attestation bundles were made for echoalign_asr_mlx-0.5.0.tar.gz:
Publisher:
publish-pypi.yml on morehardy/ASR
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
echoalign_asr_mlx-0.5.0.tar.gz -
Subject digest:
3681c423ccba5ed1c451e35d06476b5dd11cead8723f319b505cf1f8efb8a7f0 - Sigstore transparency entry: 1631682608
- Sigstore integration time:
-
Permalink:
morehardy/ASR@b77713fee8d013531c7bf87ee1c9a397d7fcf861 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/morehardy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@b77713fee8d013531c7bf87ee1c9a397d7fcf861 -
Trigger Event:
release
-
Statement type:
File details
Details for the file echoalign_asr_mlx-0.5.0-py3-none-any.whl.
File metadata
- Download URL: echoalign_asr_mlx-0.5.0-py3-none-any.whl
- Upload date:
- Size: 45.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42481b44ab6bc34a56b1ce6e3a27d9940d04aa3e729fd46177445382af228b5a
|
|
| MD5 |
43f39dffbdd1f501aed46470914b292d
|
|
| BLAKE2b-256 |
5aa20d34f2a85ba56ffebf4f133f67e866217e841655cc503886c44cd196bf74
|
Provenance
The following attestation bundles were made for echoalign_asr_mlx-0.5.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on morehardy/ASR
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
echoalign_asr_mlx-0.5.0-py3-none-any.whl -
Subject digest:
42481b44ab6bc34a56b1ce6e3a27d9940d04aa3e729fd46177445382af228b5a - Sigstore transparency entry: 1631682663
- Sigstore integration time:
-
Permalink:
morehardy/ASR@b77713fee8d013531c7bf87ee1c9a397d7fcf861 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/morehardy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@b77713fee8d013531c7bf87ee1c9a397d7fcf861 -
Trigger Event:
release
-
Statement type: