Local speech recognition & synthesis

LFM3-Audio-2B: a 1 GB model that listens and speaks

One model for transcribing and speaking

LFM3-Audio-2B handles speech and text in one model: transcribe, synthesise, translate and hold a voice conversation, from a 1.05 GB GGUF1. Its causal encoder computes while you speak, bringing the first token2 down to 50 ms.

Requirements and key details
  • The GGUF is 1.05 GB and the encoder 0.34 GB.
  • It covers 18 languages including Korean.
  • It computes while you speak, reaching a 50 ms first token.
  • Transcription accuracy trails dedicated models.

A 2B model that listens and speaks

Input is text or 16 kHz audio; output is text or 24 kHz speech, and the two can interleave, so an answer can be spoken while the text stays on screen.

It ships an in-house audio encoder and the LiquidCodec tokenizer. The encoder is fully causal, so it can prefill3 while you are still speaking, which is where the low latency comes from.

Speech compresses 80 ms into 12 tokens, so filling 32K with audio alone lasts a little over three minutes and longer meetings need splitting.

Model at a glance
Model aspectSetting
InputText, 16 kHz audio
OutputText, 24 kHz audio
Context32K tokens
Speech languages18 including Korean
LicenceLFM Open License v1.0

Files and memory

The GGUF files are 1.05 GB at Q4_0, 1.1 GB at Q4_K_M and 1.85 GB at Q8_0, plus the mmproj audio encoder at 0.34 GB for Q8_0.

The 4-bit file and the encoder together come to about 1.4 GB, which leaves headroom on an 8 GB Mac with a browser open.

Loading it in Python through Transformers pulls 4 GB of bf164 weights; the 1.4 GB figure belongs to the GGUF plus encoder path, so mixing the two paths breaks the memory estimate.

Which file to download
File nameFile sizeEncoder alongside
Q4_01.05GBmmproj Q8_0 0.34GB
Q4_K_M1.1GBmmproj Q8_0 0.34GB
Q8_01.85GBmmproj Q8_0 0.34GB

Transcription

Name the language in the system prompt5, as in Perform ASR in Korean., and it transcribes in that language; write only Perform ASR. and the model infers it.

Live transcription is English-only for now: feed it 0.96 s chunks and text appears while the speaker talks, and past 30 seconds you reopen the text context.

Batch file transcription and the live stream use different code: the live path passes state into the next call and takes a result per chunk.

Transcription code
from transformers import AutoModelForMultimodalLM, AutoProcessor

model_id = "LiquidAI/LFM3-Audio-2B"
model = AutoModelForMultimodalLM.from_pretrained(
    model_id, trust_remote_code=True).eval()
processor = AutoProcessor.from_pretrained(
    model_id, trust_remote_code=True)

conversation = [
    {"role": "system", "content": "Perform ASR in Korean."},
    {"role": "user", "content": [{"type": "audio", "audio": "meeting.wav"}]},
]
inputs = processor.apply_chat_template(
    conversation, add_generation_prompt=True,
    tokenize=True, return_dict=True, return_tensors="pt")
out = model.generate(**inputs, max_new_tokens=1024,
    suppress_mixed=True, suppress_audio_out=True,
    return_dict_in_generate=True)
text = processor.decode(
    out.sequences[0, inputs["input_ids"].shape[1]:],
    skip_special_tokens=True)
print(text)
A meeting table with a laptop, microphone, and notebooks
Recording the meeting means transcribing it in one pass; if you need it live, check the language limit first.

TTS

Synthesise by naming the language and voice in the system prompt and pre-filling the assistant turn with <|audio_start|>, as in Perform TTS in American English using a female voice..

Sampling uses audio_temperature 1.0, audio_top_k 128, repetition penalty 1.1 and a 4096 window; for text-only output turn on suppress_mixed and suppress_audio_out.

Synthesis code
import soundfile as sf

codec = processor.audio_tokenizer.eval()

conversation = [
    {"role": "system", "content": "Perform TTS in Korean using a female voice."},
    {"role": "user", "content": "오늘 회의는 세 시에 시작합니다."},
    {"role": "assistant", "content": "<|audio_start|>"},
]
inputs = processor.apply_chat_template(
    conversation, continue_final_message=True,
    tokenize=True, return_dict=True, return_tensors="pt")
out = model.generate(**inputs, max_new_tokens=256,
    audio_temperature=1.0, audio_top_k=128,
    audio_repetition_penalty=1.1, audio_repetition_window=4096,
    return_dict_in_generate=True)
waveform = codec.decode(
    out.audio_codes[:1, :, :out.audio_lengths[0]]).audio_values[0]
sf.write("tts.wav", waveform.float().cpu().numpy(), 24_000)
A screen displaying two audio tracks beside an audio interface and headphones
Synthesis quality separates by ear more than by table, so alternate the same sentence against your own recording.

Latency

The causal encoder prefills while you speak, cutting the wait after you stop; the first token can arrive in as little as 50 ms.

LiquidCodec turns tokens into speech at about 87 times real time on a single M4 Max CPU6 thread. Because 80 ms compresses into 12 tokens predicted in parallel, generation and playback overlap.

Talk to it and let it call tools

Ask out loud and it returns text and speech together, streaming so audio starts before the sentence ends.

A spoken request can become a tool call7: asking to turn off a light produces a structured call, and the result is read back as speech.

A long tool result means more speech to generate, so a system prompt that keeps answers short pays off directly in latency.

To wire tools in, put Respond with function calls, and interleaved text and audio. in the system prompt and append the tool list; leave the assistant turn empty so the model picks between a call and speech.

A shelf holding a Mac mini, headphones, an external drive and document folders
A 1 GB model plus a 0.34 GB encoder runs a speech pipeline on a small Mac.

Where it falls short

For transcription alone, dedicated models lead: English WER is 6.23 percent against 5.51 for Voxtral Mini 3B.

Tool calling at 58.50 trails Gemma 4 E4B at 72.40, and audio understanding at 50.60 trails Qwen2.5-Omni 3B at 54.41.

What it wins is VoiceBench at 73.13 and synthesis quality at 3.83, which is where the value sits: one model carrying both listening and speaking.

Scroll sideways to compare all columns.

The comparison published on the model card
MeasureLFM3-Audio 2BQwen2.5-Omni 3BVoxtral Mini 3B
English ASR WER6.23%6.30%5.51%
TTS quality UTMOSv23.833.42—
VoiceBench73.1366.3765.78
Audio understanding MMAR50.6054.4150.10

Terminology notes

  1. GGUF — A file format for model data, widely used by llama.cpp-based tools.

    Back to the text
  2. Token — A unit into which a model divides input or output for processing.

    Back to the text
  3. Prefill — The stage where an LLM reads the input prompt and computes representations for its tokens. Longer prompts contain more tokens to process.

    Back to the text
  4. BF16 — A 16-bit floating-point format for model values. Its exponent has the same width as FP32, giving it a similarly wide value range.

    Back to the text
  5. Prompt — The input text sent to a model. For generative models it describes the desired result and strongly shapes the output.

    Back to the text
  6. CPU — The central processor that runs the operating system and general-purpose instructions; in AI workloads it also handles tasks such as preprocessing and data movement.

    Back to the text
  7. Tool call — A structured request from a model for an external function such as reading a file, searching, or running a command. The agent runtime and its permission settings decide whether the request is actually executed.

    Back to the text

Frequently asked questions

What should you check first in this article?
LFM3-Audio-2B handles speech and text in one model: transcribe, synthesise, translate and hold a voice conversation, from a 1.05 GB GGUF. Its causal encoder computes while you speak, bringing the first token down to 50 ms.
How much memory does it need?
The 4-bit file and the encoder together come to about 1.4 GB, which leaves headroom on an 8 GB Mac with a browser open.