로컬 음성 인식·합성

최종 업데이트

LFM3-Audio-2B: 1GB로 듣고 말하는 음성 모델

받아쓰기와 합성을 한 모델로 해요

LFM3-Audio-2B는 음성과 텍스트를 한 모델로 다뤄요. 받아쓰기, 합성, 번역, 음성 대화가 모두 되고 GGUF1가 1.05GB예요. 인과 인코더 덕분에 말하는 동안 계산해 첫 토큰2이 50ms까지 내려가요.

실행 조건과 핵심 내용
  • GGUF가 1.05GB, 인코더가 0.34GB예요.
  • 한국어를 포함한 18개 언어를 다뤄요.
  • 말하는 동안 계산해 첫 토큰이 50ms까지 내려가요.
  • 받아쓰기 정확도는 전용 모델보다 낮아요.

듣고 말하는 2B

LFM3-Audio-2B는 입력이 텍스트나 16kHz 음성이고, 출력이 텍스트나 24kHz 음성이에요. 둘을 섞어 낼 수도 있어서, 답을 소리로 하면서 화면에는 글자로 남길 수 있어요.

자체 오디오 인코더와 LiquidCodec 토크나이저를 써요. 인코더가 완전 인과 구조라서 말하는 동안에도 미리 계산할 수 있고, 이게 지연을 줄이는 핵심이에요.

음성은 80ms가 12토큰으로 압축돼요. 32K 문맥을 음성으로만 채우면 3분 40초 남짓이라, 긴 회의는 구간을 나눠 넣어요.

모델 개요
모델 항목설정 값
입력텍스트, 16kHz 음성
출력텍스트, 24kHz 음성
문맥32K 토큰
음성 언어한국어 포함 18개
라이선스LFM Open License v1.0

파일과 메모리

GGUF는 Q4_0 1.05GB, Q4_K_M 1.1GB, Q8_0 1.85GB예요. 여기에 오디오 인코더인 mmproj가 Q8_0 기준 0.34GB 붙어요.

메모리는 4비트 파일과 인코더를 합쳐 1.4GB 남짓이에요. 8GB 맥에서 모델을 띄워 두고 브라우저를 같이 열어도 남아요.

파이썬에서 Transformers로 올리면 bf163 가중치가 4GB예요. 1.4GB는 GGUF와 인코더를 llama.cpp로 올릴 때의 숫자라서, 두 경로를 섞으면 메모리 계산이 어긋나요.

내려받을 파일
파일 이름파일 크기함께 받을 인코더
Q4_01.05GBmmproj Q8_0 0.34GB
Q4_K_M1.1GBmmproj Q8_0 0.34GB
Q8_01.85GBmmproj Q8_0 0.34GB

받아쓰기

시스템 프롬프트4에 Perform ASR in Korean.처럼 언어를 적으면 그 언어로 받아써요. 언어를 비우고 Perform ASR.만 쓰면 모델이 추론해요.

실시간 받아쓰기는 아직 영어만 돼요. 0.96초 청크로 잘라 넣으면 말하는 동안 글자가 나오고, 30초가 넘어가면 문맥을 새로 열어요.

녹음 파일을 한 번에 넣는 방식과 실시간 스트림 방식은 코드가 달라요. 실시간 쪽은 상태를 다음 호출로 넘기면서 조각마다 결과를 받아요.

받아쓰기 코드
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)
원탁 위에 노트북과 마이크, 노트가 놓인 회의 공간
회의를 녹음해 두면 받아쓰기는 한 번에 끝낼 수 있어요. 실시간이 필요하면 언어 제약을 먼저 확인해요.

합성

합성은 시스템 프롬프트에 언어와 성별을 적고, 어시스턴트 턴을 <|audio_start|>로 채워요. Perform TTS in American English using a female voice. 같은 형태예요.

샘플링은 audio_temperature 1.0, audio_top_k 128, 반복 페널티 1.1, 창 4096을 써요. 텍스트만 필요하면 suppress_mixed와 suppress_audio_out을 켜요.

합성 코드
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)
두 음성 트랙이 표시된 화면과 오디오 인터페이스, 헤드폰
합성 품질은 표보다 귀로 갈려요. 같은 문장을 원본과 번갈아 들어 보세요.

지연

인과 인코더가 말하는 동안 프리필5을 해서, 말이 끝난 뒤 기다리는 시간이 줄어요. 첫 토큰은 50ms까지 내려가요.

LiquidCodec은 M4 Max CPU6 한 스레드에서 실시간의 87배로 음성을 만들어요. 80ms를 12토큰으로 압축하고 토큰을 나란히 예측해서, 생성과 재생이 겹쳐요.

음성으로 대화하고 도구를 불러요

말로 물으면 텍스트와 음성을 같이 돌려줘요. 스트리밍이라 문장이 끝나기 전에 소리가 나오기 시작해요.

말한 요청을 도구 호출7로 바꿀 수도 있어요. 조명을 꺼 달라는 말이 구조화된 호출이 되고, 결과를 다시 말로 읽어 줘요.

도구 결과가 길면 그만큼 읽어 줘야 해요. 답을 짧게 유도하는 시스템 프롬프트가 지연에 바로 영향을 줘요.

도구를 붙일 때는 시스템 프롬프트에 Respond with function calls, and interleaved text and audio.를 넣고 도구 목록을 이어 붙여요. 이때는 어시스턴트 턴을 비워 두고 모델이 호출과 음성 중 무엇으로 시작할지 고르게 해요.

선반 위에 맥 미니와 헤드폰, 외장 드라이브, 서류 폴더가 정리되어 놓인 그림
모델 1GB와 인코더 0.34GB면 작은 맥에서도 음성 파이프라인이 돌아요.

무엇에 약한가

받아쓰기 정확도만 보면 전용 모델이 나아요. 영어 WER 6.23%는 Voxtral Mini 3B의 5.51%보다 높아요.

도구 호출 58.50은 Gemma 4 E4B의 72.40보다 낮고, 오디오 이해 50.60은 Qwen2.5-Omni 3B의 54.41보다 낮아요.

대신 VoiceBench 73.13과 합성 품질 3.83은 비교 모델보다 높아요. 한 모델로 듣고 말하는 흐름을 만들 때 값이 나와요.

좌우로 밀어 표 전체를 비교하세요.

모델 카드에 공개된 비교
측정 지표LFM3-Audio 2BQwen2.5-Omni 3BVoxtral Mini 3B
영어 받아쓰기 WER6.23%6.30%5.51%
합성 품질 UTMOSv23.833.42—
VoiceBench73.1366.3765.78
오디오 이해 MMAR50.6054.4150.10

용어 각주

  1. GGUF — 모델 정보를 담는 파일 형식으로 llama.cpp 계열 도구에서 널리 사용됩니다.

    본문으로 돌아가기
  2. 토큰 — 모델이 입력이나 출력을 나누어 처리하는 단위입니다.

    본문으로 돌아가기
  3. BF16 — 모델 수치를 저장하고 계산하는 16비트 부동소수점 형식입니다. FP32와 같은 폭의 지수부를 써 넓은 값 범위를 표현합니다.

    본문으로 돌아가기
  4. 프롬프트 — 모델에 보내는 입력문입니다. 생성 모델에서는 만들 결과를 설명하는 문장이 되어 출력의 구성과 내용을 크게 좌우합니다.

    본문으로 돌아가기
  5. 프리필 — LLM이 입력 프롬프트를 읽고 각 토큰의 내부 표현을 계산하는 단계입니다. 입력이 길수록 처리할 토큰이 많아집니다.

    본문으로 돌아가기
  6. CPU — 운영체제와 일반 프로그램 명령을 실행하고, AI에서는 전처리·데이터 이동 등 범용 연산을 맡는 중앙 처리 장치입니다.

    본문으로 돌아가기
  7. 도구 호출 — 모델이 파일 읽기·검색·명령 실행 같은 외부 기능의 이름과 인자를 요청하는 형식입니다. 요청을 실제로 실행할지는 에이전트 런타임과 권한 설정이 결정합니다.

    본문으로 돌아가기

자주 묻는 질문

이 글에서 가장 먼저 확인할 것은 무엇인가요?
LFM3-Audio-2B는 음성과 텍스트를 한 모델로 다뤄요. 받아쓰기, 합성, 번역, 음성 대화가 모두 되고 GGUF가 1.05GB예요. 인과 인코더 덕분에 말하는 동안 계산해 첫 토큰이 50ms까지 내려가요.
필요한 메모리는 어느 정도인가요?
메모리는 4비트 파일과 인코더를 합쳐 1.4GB 남짓이에요. 8GB 맥에서 모델을 띄워 두고 브라우저를 같이 열어도 남아요.