hayamimi: GPU와 클라우드 없이 CPU만으로 실시간 다국어 자막을 만드는 음성 인식 도구

hayamimi 소개

회의나 방송을 실시간으로 받아 적어야 하는 상황에서 지금 선택할 수 있는 길은 대체로 두 가지입니다. 하나는 클라우드 음성 인식(Speech Recognition, ASR) API를 붙여 분당 요금을 내는 것이고, 다른 하나는 Whisper 계열 모델을 로컬에 올려 GPU에서 실행하는 것입니다. 두 번째 길에서 GPU를 뺄 수 없다는 점이 문제가 됩니다. 노트북과 사무용 데스크톱에는 대개 쓸 만한 GPU가 없고, 그렇다고 CPU에서 Whisper를 실행하면 실시간에 못 미쳐 자막이 말보다 늦게 따라옵니다. 발화가 끝나고 한참 지나서 글자가 표시되는 자막은 회의 중계나 방송 송출에는 쓸 수 없습니다.

이번에 소개할 hayamimi는 이 제약을 모델 한 개의 성능으로 해결하는 대신, 발화마다 언어를 판별해 그 언어 전용 모델로 보내는 라우팅으로 우회하는 프로젝트입니다. 모든 모델은 INT8로 양자화(Quantization)된 ONNX 형태이고 sherpa-onnx 런타임(Runtime)에서 실행되므로, PyTorch도 CUDA도 설치하지 않습니다. 저장소 이름인 早耳(하야미미)는 일본어로 소식을 빨리 듣는 사람을 뜻하는데, 개발자는 이를 설계 목표로 삼았다고 설명하고 있습니다. 말하는 중에 임시 자막이 먼저 표시되고, 말을 멈춘 뒤 약 100밀리초 후에 확정 자막이 확정되는 동작이 그 목표의 구체적인 형태입니다.

hayamimi를 사용하기 위해서는 파이썬 3.10 이상과 ffmpeg만 준비하면 되고, 모델 가중치는 저장소에 들어 있지 않아 설치 스크립트가 원 배포처에서 내려받습니다. 개발과 테스트는 Windows 11에서 이뤄졌고 macOS와 Linux는 런타임이 모두 크로스 플랫폼이라 동작할 것으로 보지만 종단 간 CI 검증은 아직 없다고 개발자가 밝혔습니다. 이번 게시물에서는 언어별 라우팅 구조와 두 번 훑기 방식, 그리고 개발자가 같은 음성으로 whisper-large-v3-turbo와 직접 맞붙여 공개한 수치를 정리합니다.

hayamimi와 기존 방식 비교

개발자는 docs/COMPARISON.md에서 신뢰도가 다른 두 종류의 비교를 분리해 두었습니다. 하나는 같은 음성과 같은 채점 함수로 같은 CPU에서 맞붙여 본 직접 대조이고, 다른 하나는 각 벤더의 공표값을 나란히 놓은 참고 자료입니다. 이 중 직접 대조는 faster-whisper로 INT8 CPU 추론(Inference)한 whisper-large-v3-turbo를 상대로 했고, turbo 쪽에는 정답 언어를 미리 알려 주었습니다. 반대로 hayamimi는 언어를 스스로 판별하므로, 정확도 면에서는 turbo에게 유리한 조건입니다. 오류율은 영어만 단어 오류율(Word Error Rate, WER)이고 나머지는 문자 오류율(Character Error Rate, CER)이며, RTF(Real-Time Factor)는 음성 길이 대비 처리 시간의 비율이라 1보다 작을 때만 실시간을 따라잡습니다. 아래는 그 결과이며 각 행에서 더 나은 값을 볼드로 표시한 원문 표기를 그대로 옮겼습니다:

언어 클립 hayamimi 오류율 hayamimi RTF turbo 오류율 turbo RTF
ja 15 CER 7.5% 0.071 CER 13.75% 1.392
en 15 WER 2.3% 0.109 WER 2.16% 1.383
zh 12 CER 5.3% 0.102 CER 4.0% 1.107
ko 12 CER 8.1% 0.062 CER 6.8% 1.063
yue 12 CER 6.1% 0.061 CER 15.5% 1.034

위 표를 통해 속도와 정확도를 나눠서 볼 수 있습니다. 속도는 다섯 언어 모두 hayamimi가 11배에서 19배 빠르고, 측정에 쓴 Ryzen 5 5600에서 turbo는 전 언어 RTF가 1을 넘어 실시간에 도달하지 못했습니다. 정확도는 언어마다 결과가 다릅니다. 일본어와 광동어는 hayamimi가 오류율을 절반 이하로 낮췄지만, 영어와 중국어, 한국어에서는 turbo가 0.1에서 1.3포인트 앞섭니다. 한국어만 떼어 보면 8.1%와 6.8%로 turbo가 앞서므로, 한국어 음성을 주로 다룰 계획이라면 이 수치를 먼저 확인하셔야 합니다. 다만 위의 조건 비대칭을 감안하면 정확도 차이는 그 범위 안에 있고, "CPU에서 실시간으로 동작한다"는 제약을 걸면 turbo는 애초에 후보에서 빠집니다.

로컬에서 실시간 음성 인식을 푸는 다른 접근으로는 Whisper 계열 모델을 스트리밍 파이프라인으로 감싸는 방법이 있습니다. PyTorchKR에도 소개 글이 있는 WhisperLiveKit이 그 계열입니다. hayamimi는 반대 방향으로, 모델을 언어별로 나누는 복잡도를 감수하면서 GPU 의존을 없앴습니다.

hayamimi는 누구에게 맞는가

일본어나 광동어 음성을 CPU만 있는 기기에서 실시간으로 받아 적어야 하는 팀에게 hayamimi가 가장 잘 맞습니다. 두 언어는 직접 대조에서 오류율이 turbo의 절반 이하이고, 모델 상주 메모리가 2GB 아래로 유지되어 방송용 PC나 사무용 데스크톱에서도 실행할 수 있습니다. OBS 브라우저 소스로 바로 연결할 수 있는 오버레이가 함께 들어 있다는 점도 실시간 송출에는 실질적인 이점입니다.

반대로 한 문장 안에서 한국어와 영어를 섞어 쓰는 회의를 받아 적어야 하는 팀에게는 hayamimi가 적절한 선택지가 아닙니다. 라우터가 발화 하나에 언어 하나를 배정하는 구조라, 문장 내부에서 언어가 바뀌면 소수 언어 쪽이 뭉개지거나 빠진다고 개발자가 명시해 두었습니다. 통역처럼 문장 단위로 언어가 교대되는 상황은 잘 처리되지만 단어 단위 혼용은 처리되지 않습니다. 한국어 정확도 자체를 최우선으로 두거나 GPU를 이미 확보한 환경이라면, 위 표에서 앞선 turbo 계열을 그대로 쓰는 편이 낫습니다.

hayamimi의 언어별 라우팅 구조

위 도식은 개발자가 저장소의 demo/ 디렉토리에 넣어 둔 일본어 요약 자료로, 구간 검출부터 마무리까지의 5단계를 한 장에 담고 있습니다. 다만 도식에 적힌 일본어 오류율 5.8%는 개발자가 2026년 9월 1일에 3.8%로 재측정하기 전의 값이므로, 아래 표의 수치를 기준으로 읽으시면 됩니다.

hayamimi의 파이프라인은 발화 구간을 잘라내는 단계에서 시작합니다. Silero VAD가 음성 구간 검출(Voice Activity Detection, VAD)로 발화 구간을 찾고, 무음이 0.35초 이어지면 발화가 끝난 것으로 판정하며, 앞머리가 잘리지 않도록 0.8초를 미리 확보합니다. 이어서 whisper-tiny가 발화 앞부분 약 4초에 대해 언어 판별(Language Identification, LID)을 수행하는데, 이 판별은 구간이 아직 수신되는 중에 함께 실행됩니다. 문자 종류를 함께 보는 중재 단계가 뒤에 이어지고, 세션의 첫 발화는 언어를 확정하기 전에 SenseVoice로 한 번 더 확인합니다.

판별된 언어 태그에 따라 전용 모델이 선택됩니다. 각 경로와 개발자가 공개한 측정치는 다음과 같습니다:

언어 클립 LID 정확도 담당 모델 평균 오류율 평균 RTF
ja 15 15/15 ReazonSpeech 3.8% 0.090
en 15 15/15 Parakeet v3 2.3% 0.102
zh 12 12/12 Paraformer-zh 6.6% 0.084
ko 12 12/12 SenseVoice 8.1% 0.060
yue 12 12/12 SenseVoice 6.1% 0.043

일본어는 Reazon Human Interaction Lab의 ReazonSpeech Zipformer 모델이, 영어와 24개 유럽 언어는 NVIDIA Parakeet TDT v3가, 한국어와 광동어는 Alibaba DAMO Academy의 SenseVoice small이 맡습니다. 중국어는 Paraformer-zh가 담당하고, 위 다섯 경로에 걸리지 않는 나머지는 Meta AI Omnilingual ASR로 넘어가 약 1,600개 언어를 처리합니다. 중국어 오류율 6.6% 중 약 1.3포인트는 숫자 표기 방식의 불일치라고 개발자가 따로 적어 두었습니다. 파이프라인이 아라비아 숫자로 적는 자리를 일부 정답 텍스트가 한자로 적어 둔 경우인데, 이는 인식 실패가 아니라 채점 규약의 차이입니다.

모델을 다섯 갈래로 늘리면 메모리가 문제가 됩니다. hayamimi는 모델을 처음 쓸 때 지연 로딩하고, 일본어 이외의 모델은 가장 오래 쓰지 않은 것부터 내보내는 LRU(Least Recently Used) 캐시로 관리합니다. 기본값인 --max-resident 3에서 상주 메모리가 2GB 아래로 유지되고, --max-resident 2로 줄이면 1.35GB까지 내려갑니다. 세션이 여러 언어를 오가도 상주량이 언어 수에 비례해 늘지 않는 이유가 여기에 있습니다.

hayamimi의 자막 품질을 끌어올리는 장치

말하는 중에 표시되는 임시 자막과 확정 자막은 서로 다른 경로에서 나옵니다. 임시 자막은 약 0.5초마다 갱신되는 초안이고, 확정 자막은 일본어 기준으로 발화가 끝난 뒤 평균 약 100밀리초 후에 나옵니다. 모든 기능을 켠 5개 언어 연속 테스트에서는 확정 지연이 평균 약 236밀리초, 최대 552밀리초로 측정됐습니다.

여기에 무음 2초가 지나면 최근 발화들을 묶어 다시 디코딩하는 두 번 훑기(Two-pass refinement) 가 실행됩니다. 실시간성을 위해 한 번에 처리한 결과를 나중에 정확도 우선으로 다시 계산하는 방식이고, 일본어 실방송 음성에서 CER이 15.5%에서 12.0%로 내려갔습니다. 일본어 확정 자막에는 BERT 기반 구두점 복원이 추가로 적용되는데, 이 변환 모델은 같은 계열 프로젝트인 Mojicast가 변환해 둔 것을 그대로 씁니다. 대시보드는 한 번에 처리한 결과와 다시 계산한 결과를 왼쪽과 오른쪽 열에 나란히 보여줍니다.

화자 라벨은 --speakers로 켜며, 실시간 경로에서는 Alibaba DAMO Academy의 3D-Speaker CAM++ 임베딩을 최근접 중심점에 맞춰 S1, S2 같은 라벨을 붙입니다. 두 번 훑기 시점에는 pyannote segmentation-3.0으로 발화 묶음을 다시 분리하고, 그 결과 나온 지역 군집을 세션 전체의 S 라벨에 다시 대응시킵니다. AMI 회의 5건(총 50분)에서 화자 분리 오류율(Diarization Error Rate, DER)이 평균 25.7%에서 13.9%로 내려갔지만, 정답 화자 수가 회의당 4명인데 hayamimi의 추정은 4명에서 8명 사이로 여전히 많이 잡힙니다. 그래서 개발자는 이 기능을 화자 수의 근거가 아니라 발화 순서 라벨링으로 읽어야 한다고 안내하고 있습니다. 처음 등장한 화자를 S5?처럼 잠정 표기로 두고 다시 나타날 때만 확정하는 장치도 이 과대 추정을 화면에서 덜어내기 위한 것입니다.

번역은 --translate로 켜고 일본어 문장을 대상 언어로 옮깁니다. 영어는 전용 FuguMT 모듈이 담당하고, 그 밖의 언어는 M2M-100의 대상 코드를 받아 처리하는데 품질이 측정된 것은 중국어와 한국어, 스페인어뿐입니다. 개발자는 번역 품질에 조정으로 넘을 수 없는 한계가 있다고 밝히면서, 특히 일본어에서 중국어와 한국어로 옮길 때 숫자 값이 안정적으로 보존되지 않는다는 점을 문서에 남겨 두었습니다. 금액이나 수치가 중요한 자리에서는 이 기능에 기대지 않는 편이 안전합니다.

고유명사 처리에는 함정이 하나 있습니다. --hotwords로 고유명사 쪽으로 디코딩을 유도할 수 있는데, 일본어 경로에서는 이 옵션이 아무 효과를 내지 못합니다. ReazonSpeech의 tokens.txt가 바이트 단위 BPE라서 hayamimi가 쓰는 인코딩 방식으로는 핫워드를 표현할 수 없고, sherpa-onnx는 이를 경고만 내고 정상 종료합니다. hayamimi는 시작 시점에 인코딩에 실패한 핫워드 개수를 알려 주며, 일본어 고유명사는 --replace로 사후 치환하도록 안내합니다.

hayamimi 설치와 사용

설치는 가상환경을 만들고 의존성과 모델을 내려받는 순서로 진행합니다. 개발자가 안내하는 명령은 다음과 같습니다:

python -m venv .venv

# Windows
.venv\Scripts\pip install -r requirements.txt
.venv\Scripts\python scripts\download_models.py

# macOS / Linux
.venv/bin/pip install -r requirements.txt
.venv/bin/python scripts/download_models.py

scripts/download_models.py가 내려받는 모델은 약 3.1GB이고, --minimal을 붙이면 일본어와 영어만 쓰는 약 1.1GB 구성으로 줄어듭니다. 그다음 마이크 입력을 받아 실시간 인식을 시작하고, 대시보드와 OBS 오버레이까지 띄우려면 --serve를 붙입니다:

# 마이크 입력으로 실시간 인식
.venv/bin/python scripts/realtime_transcribe.py

# 대시보드와 OBS 오버레이까지 함께
.venv/bin/python scripts/realtime_transcribe.py --serve

--serve를 붙이면 세 가지 화면이 열립니다. http://localhost:8833/dashboard 는 임시 자막과 확정 자막, 언어 배지, 화자 칩, 줄별 지연을 함께 보여주는 대시보드이고, http://localhost:8833/ 는 OBS 브라우저 소스로 넣는 오버레이입니다. 오버레이는 확정 줄과 진행 중인 줄이 별도 행으로 나뉘어 있어 ?show=final 또는 ?show=partial을 붙이면 한쪽만 렌더링할 수 있고, 그래서 두 줄을 각각 다른 OBS 소스로 배치할 수 있습니다. http://localhost:8833/transcript 는 기록을 스크롤로 훑는 화면입니다.

마이크 대신 네트워크로 오디오를 받는 경로도 있습니다. --input ws를 주면 WebSocket 수신 지점이 열려 휴대폰이나 stackchan 계열 ESP32 보드가 LAN으로 마이크 오디오를 흘려보낼 수 있습니다. 클라이언트는 /ingest에 접속해 JSON 텍스트 프레임 하나({"sr": 16000, "format": "pcm_s16le", "channels": 1})를 보낸 뒤 원본 PCM을 이진 프레임으로 이어 보내면 되고, 서버는 16kHz가 아닌 오디오를 재표본화합니다. 오디오를 보내는 클라이언트는 한 번에 하나만 받습니다.

여기서 보안 설정을 확인하셔야 합니다. --input ws는 기본적으로 127.0.0.1에만 바인딩되므로 같은 기기에서만 접속할 수 있고, --ws-host 0.0.0.0으로 열어야 LAN 클라이언트를 받습니다. /ingest에는 인증이 없으므로 신뢰할 수 있는 네트워크에서만 열어야 합니다. 바인딩된 주소는 어느 쪽이든 시작 시 표준 오류로 출력됩니다.

파이프라인을 다른 앱에 내장하는 경우도 고려되어 있습니다. scripts/realtime_transcribe.pyRoutedASRbuild_vad, run_stream은 임포트해서 쓸 수 있고, 모델 경로가 없을 때 sherpa-onnx의 C++ 계층이 exit()를 호출하는 대신 잡을 수 있는 asr_engine.ModelUnavailable 예외를 던집니다. run_streamthreading.Event를 취소 토큰으로 받아, 자체 스레드에서 파이프라인을 실행하는 호스트 앱이 KeyboardInterrupt에 의존하지 않고 깔끔히 멈출 수 있습니다.

hayamimi의 라이선스

hayamimi의 소스 코드는 MIT 라이선스로 공개되어 있어 개인 및 상업적 목적으로 자유롭게 사용할 수 있습니다.

단, 모델 가중치는 저장소에 포함되어 있지 않고 설치 시점에 원 배포처에서 내려받으며 각자의 라이선스를 따릅니다. 특히 --translate en이 쓰는 일본어에서 영어로 옮기는 번역 모델(mojicast-fugumt-ja-en-ct2)은 CC BY-SA 4.0으로, 이 가중치를 재배포하려면 출처 표기를 유지하고 재배포물도 같은 라이선스로 공개해야 합니다. 모델별 조건은 저장소의 THIRD_PARTY_NOTICES.md에 표로 정리되어 있으므로, 배포를 계획하고 있다면 설치 전에 이 파일을 먼저 확인하셔야 합니다.

:github: hayamimi 프로젝트 GitHub 저장소

더 읽어보기




이 글은 GPT 모델로 정리한 초안을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 댓글로 알려주시기를 부탁드립니다. :hugs:

이 도구를 직접 설치해 사용해보셨다면, :pytorch:파이토치 한국 사용자 모임:south_korea: 회원들을 위해 경험이나 팁을 댓글로 남겨주세요! :folded_hands: