An implementation of the Parakeet models - Nvidia's ASR(Automatic Speech Recognition) models - for Apple Silicon using MLX.
[!NOTE] Make sure you have
ffmpeginstalled on your system first, otherwise CLI won't work properly.
Using uv - recommended way:
uv add parakeet-mlx -U
Or, for the CLI:
uv tool install parakeet-mlx -U
Using pip:
pip install parakeet-mlx -U
parakeet-mlx <audio_files> [OPTIONS]
audio_files: One or more audio files to transcribe (WAV, MP3, etc.)--model (default: mlx-community/parakeet-tdt-0.6b-v3, env: PARAKEET_MODEL)
--output-dir (default: current directory)
--output-format (default: srt, env: PARAKEET_OUTPUT_FORMAT)
--output-template (default: {filename}, env: PARAKEET_OUTPUT_TEMPLATE)
{parent}, {filename}, {index}, {date} is supported.--highlight-words (default: False)
--verbose / -v (default: False)
--decoding (default: greedy, env: PARAKEET_DECODING)
greedy or beam)beam is only available at TDT models for now--chunk-duration (default: 120 seconds, env: PARAKEET_CHUNK_DURATION)
0 to disable chunking--overlap-duration (default: 15 seconds, env: PARAKEET_OVERLAP_DURATION)
--beam-size (default: 5, env: PARAKEET_BEAM_SIZE)
--length-penalty (default: 0.013, env: PARAKEET_LENGTH_PENALTY)
--patience (default: 3.5, env: PARAKEET_PATIENCE)
--duration-reward (default: 0.67, env: PARAKEET_DURATION_REWARD)
--max-words (default: None, env: PARAKEET_MAX_WORDS)
--silence-gap (default: None, env: PARAKEET_SILENCE_GAP)
--max-duration (default: None, env: PARAKEET_MAX_DURATION)
--fp32 / --bf16 (default: bf16, env: PARAKEET_FP32 - boolean)
--full-attention / --local-attention (default: full-attention, env: PARAKEET_LOCAL_ATTENTION - boolean)
--local-attention-context-size (default: 256, env: PARAKEET_LOCAL_ATTENTION_CTX)
--cache-dir (default: None, env: PARAKEET_CACHE_DIR)
HF_HOME or HF_HUB_CACHE which is essentially $HF_HOME/hub)# Basic transcription
parakeet-mlx audio.mp3
# Multiple files with word-level timestamps of VTT subtitle
parakeet-mlx *.mp3 --output-format vtt --highlight-words
# Generate all output formats
parakeet-mlx audio.mp3 --output-format all
Transcribe a file:
from parakeet_mlx import from_pretrained
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
result = model.transcribe("audio_file.wav")
print(result.text)
Check timestamps:
from parakeet_mlx import from_pretrained
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
result = model.transcribe("audio_file.wav")
print(result.sentences)
# [AlignedSentence(text="Hello World.", start=1.01, end=2.04, duration=1.03, tokens=[...])]
Do chunking:
from parakeet_mlx import from_pretrained
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
result = model.transcribe("audio_file.wav", chunk_duration=60 * 2.0, overlap_duration=15.0)
print(result.sentences)
Do beam decoding:
from parakeet_mlx import from_pretrained, DecodingConfig, Beam
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
config = DecodingConfig(
decoding = decoding(
beam_size=5, length_penalty=0.013, patience=3.5, duration_reward=0.67
# Refer to CLI options for each parameters
)
)
result = model.transcribe("audio_file.wav", decoding_config=config)
print(result.sentences)
Use local attention:
from parakeet_mlx import from_pretrained
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
model.encoder.set_attention_model(
"rel_pos_local_attn", # Follows NeMo's naming convention
(256, 256),
)
result = model.transcribe("audio_file.wav")
print(result.sentences)
Specifiy the sentence split options:
from parakeet_mlx import from_pretrained, DecodingConfig, SentenceConfig
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
config = DecodingConfig(
sentence = SentenceConfig(
# Refer to CLI Options to see what those options does
max_words=30, silence_gap=5.0, max_duration=40.0
)
)
result = model.transcribe("audio_file.wav", decoding_config=config)
print(result.sentences)
Using from_pretrained downloads a model from Hugging Face and stores the downloaded model in HF's cache folder. You can specify the cache folder by passing it cache_dir args. It can return one of those Parakeet variants such as: ParakeetTDT, ParakeetRNNT, ParakeetCTC, or ParakeetTDTCTC. For general use cases, the BaseParakeet abstraction often suffices. However, if you want to call variant-specific functions like .decode() and want linters not to complain, typing.cast can be used.
AlignedResult: Top-level result containing the full text and sentences
text: Full transcribed textsentences: List of AlignedSentenceAlignedSentence: Sentence-level alignments with start/end times
text: Sentence textstart: Start time in secondsend: End time in secondsduration: Between start and end.tokens: List of AlignedTokenAlignedToken: Word/token-level alignments with precise timestamps
text: Token textstart: Start time in secondsend: End time in secondsduration: Between start and end.For real-time transcription, use the transcribe_stream method which creates a streaming context:
from parakeet_mlx import from_pretrained
from parakeet_mlx.audio import load_audio
import numpy as np
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
# Create a streaming context
with model.transcribe_stream(
context_size=(256, 256), # (left_context, right_context) frames
) as transcriber:
# Simulate real-time audio chunks
audio_data = load_audio("audio_file.wav", model.preprocessor_config.sample_rate)
chunk_size = model.preprocessor_config.sample_rate # 1 second chunks
for i in range(0, len(audio_data), chunk_size):
chunk = audio_data[i:i+chunk_size]
transcriber.add_audio(chunk)
# Access current transcription
result = transcriber.result
print(f"Current text: {result.text}")
# Access finalized and draft tokens
# transcriber.finalized_tokens
# transcriber.draft_tokens
context_size: Tuple of (left_context, right_context) for attention windows
depth: Number of encoder layers that preserve exact computation across chunks
keep_original_attention: Whether to keep original attention mechanism
To transcribe log-mel spectrum directly, you can do the following:
import mlx.core as mx
from parakeet_mlx.audio import get_logmel, load_audio
from parakeet_mlx import DecodingConfig
# Load and preprocess audio manually
audio = load_audio("audio.wav", model.preprocessor_config.sample_rate)
mel = get_logmel(audio, model.preprocessor_config)
# Generate transcription with alignments
# Accepts both [batch, sequence, feat] and [sequence, feat]
# `alignments` is list of AlignedResult. (no matter if you fed batch dimension or not!)
alignments = model.generate(mel, decoding_config=DecodingConfig())
transcribe_stream)Apache 2.0
Python
100.0%
An implementation of the Parakeet models - Nvidia's ASR(Automatic Speech Recognition) models - for Apple Silicon using MLX.
[!NOTE] Make sure you have
ffmpeginstalled on your system first, otherwise CLI won't work properly.
Using uv - recommended way:
uv add parakeet-mlx -U
Or, for the CLI:
uv tool install parakeet-mlx -U
Using pip:
pip install parakeet-mlx -U
parakeet-mlx <audio_files> [OPTIONS]
audio_files: One or more audio files to transcribe (WAV, MP3, etc.)--model (default: mlx-community/parakeet-tdt-0.6b-v3, env: PARAKEET_MODEL)
--output-dir (default: current directory)
--output-format (default: srt, env: PARAKEET_OUTPUT_FORMAT)
--output-template (default: {filename}, env: PARAKEET_OUTPUT_TEMPLATE)
{parent}, {filename}, {index}, {date} is supported.--highlight-words (default: False)
--verbose / -v (default: False)
--decoding (default: greedy, env: PARAKEET_DECODING)
greedy or beam)beam is only available at TDT models for now--chunk-duration (default: 120 seconds, env: PARAKEET_CHUNK_DURATION)
0 to disable chunking--overlap-duration (default: 15 seconds, env: PARAKEET_OVERLAP_DURATION)
--beam-size (default: 5, env: PARAKEET_BEAM_SIZE)
--length-penalty (default: 0.013, env: PARAKEET_LENGTH_PENALTY)
--patience (default: 3.5, env: PARAKEET_PATIENCE)
--duration-reward (default: 0.67, env: PARAKEET_DURATION_REWARD)
--max-words (default: None, env: PARAKEET_MAX_WORDS)
--silence-gap (default: None, env: PARAKEET_SILENCE_GAP)
--max-duration (default: None, env: PARAKEET_MAX_DURATION)
--fp32 / --bf16 (default: bf16, env: PARAKEET_FP32 - boolean)
--full-attention / --local-attention (default: full-attention, env: PARAKEET_LOCAL_ATTENTION - boolean)
--local-attention-context-size (default: 256, env: PARAKEET_LOCAL_ATTENTION_CTX)
--cache-dir (default: None, env: PARAKEET_CACHE_DIR)
HF_HOME or HF_HUB_CACHE which is essentially $HF_HOME/hub)# Basic transcription
parakeet-mlx audio.mp3
# Multiple files with word-level timestamps of VTT subtitle
parakeet-mlx *.mp3 --output-format vtt --highlight-words
# Generate all output formats
parakeet-mlx audio.mp3 --output-format all
Transcribe a file:
from parakeet_mlx import from_pretrained
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
result = model.transcribe("audio_file.wav")
print(result.text)
Check timestamps:
from parakeet_mlx import from_pretrained
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
result = model.transcribe("audio_file.wav")
print(result.sentences)
# [AlignedSentence(text="Hello World.", start=1.01, end=2.04, duration=1.03, tokens=[...])]
Do chunking:
from parakeet_mlx import from_pretrained
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
result = model.transcribe("audio_file.wav", chunk_duration=60 * 2.0, overlap_duration=15.0)
print(result.sentences)
Do beam decoding:
from parakeet_mlx import from_pretrained, DecodingConfig, Beam
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
config = DecodingConfig(
decoding = decoding(
beam_size=5, length_penalty=0.013, patience=3.5, duration_reward=0.67
# Refer to CLI options for each parameters
)
)
result = model.transcribe("audio_file.wav", decoding_config=config)
print(result.sentences)
Use local attention:
from parakeet_mlx import from_pretrained
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
model.encoder.set_attention_model(
"rel_pos_local_attn", # Follows NeMo's naming convention
(256, 256),
)
result = model.transcribe("audio_file.wav")
print(result.sentences)
Specifiy the sentence split options:
from parakeet_mlx import from_pretrained, DecodingConfig, SentenceConfig
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
config = DecodingConfig(
sentence = SentenceConfig(
# Refer to CLI Options to see what those options does
max_words=30, silence_gap=5.0, max_duration=40.0
)
)
result = model.transcribe("audio_file.wav", decoding_config=config)
print(result.sentences)
Using from_pretrained downloads a model from Hugging Face and stores the downloaded model in HF's cache folder. You can specify the cache folder by passing it cache_dir args. It can return one of those Parakeet variants such as: ParakeetTDT, ParakeetRNNT, ParakeetCTC, or ParakeetTDTCTC. For general use cases, the BaseParakeet abstraction often suffices. However, if you want to call variant-specific functions like .decode() and want linters not to complain, typing.cast can be used.
AlignedResult: Top-level result containing the full text and sentences
text: Full transcribed textsentences: List of AlignedSentenceAlignedSentence: Sentence-level alignments with start/end times
text: Sentence textstart: Start time in secondsend: End time in secondsduration: Between start and end.tokens: List of AlignedTokenAlignedToken: Word/token-level alignments with precise timestamps
text: Token textstart: Start time in secondsend: End time in secondsduration: Between start and end.For real-time transcription, use the transcribe_stream method which creates a streaming context:
from parakeet_mlx import from_pretrained
from parakeet_mlx.audio import load_audio
import numpy as np
model = from_pretrained("mlx-community/parakeet-tdt-0.6b-v3")
# Create a streaming context
with model.transcribe_stream(
context_size=(256, 256), # (left_context, right_context) frames
) as transcriber:
# Simulate real-time audio chunks
audio_data = load_audio("audio_file.wav", model.preprocessor_config.sample_rate)
chunk_size = model.preprocessor_config.sample_rate # 1 second chunks
for i in range(0, len(audio_data), chunk_size):
chunk = audio_data[i:i+chunk_size]
transcriber.add_audio(chunk)
# Access current transcription
result = transcriber.result
print(f"Current text: {result.text}")
# Access finalized and draft tokens
# transcriber.finalized_tokens
# transcriber.draft_tokens
context_size: Tuple of (left_context, right_context) for attention windows
depth: Number of encoder layers that preserve exact computation across chunks
keep_original_attention: Whether to keep original attention mechanism
To transcribe log-mel spectrum directly, you can do the following:
import mlx.core as mx
from parakeet_mlx.audio import get_logmel, load_audio
from parakeet_mlx import DecodingConfig
# Load and preprocess audio manually
audio = load_audio("audio.wav", model.preprocessor_config.sample_rate)
mel = get_logmel(audio, model.preprocessor_config)
# Generate transcription with alignments
# Accepts both [batch, sequence, feat] and [sequence, feat]
# `alignments` is list of AlignedResult. (no matter if you fed batch dimension or not!)
alignments = model.generate(mel, decoding_config=DecodingConfig())
transcribe_stream)Apache 2.0
Python
100.0%