
OpenWakeWord가 작동하지 않아서 livekit-wakeword로 Custom Wake Word를 40분 만에 만들었다
요약
OpenWakeWord의 라이브러리 부패 문제로 인해 Custom Wake Word 제작에 실패한 후, 대안으로 livekit-wakeword를 사용하여 40분 만에 고성능 ONNX 모델을 제작한 과정을 다룹니다.
핵심 포인트
- OpenWakeWord Colab의 데이터셋 URL 및 의존성 라이브러리 문제 확인
- livekit-wakeword를 통한 단일 명령어로 학습 및 ONNX 내보내기 성공
- 결과물: Recall 98.95%, FPPH 0.0, 용량 162KB의 효율적인 모델
- 기존 OpenWakeWord 런타임과 완벽한 호환성 유지
내 이름으로 깨어나는 스마트 스피커를 갖고 싶어서, Custom Wake Word (사용자 정의 웨이크 워드)를 만들고 싶어졌다. 「OK Google」이나 「Hey Siri」처럼, 내가 정한 호출에만 반응하는 모델. 로컬에서 실행하고 싶고, 외부로 음성을 보내고 싶지 않으며, ONNX로 내보내어 에지(Edge) 기기에 두고 싶다.
처음으로 열어본 것은 openwakeword의 공식 Colab notebook이었다. 이것이 작동하지 않았다.
대신 livekit-wakeword라는 패키지로 학습시켰더니, 약 40분 만에 실용 품질의 모델이 나왔다. recall 98.95% / fpph 0.0, 162KB의 ONNX. 본 기사는 그 구현 로그다.
OpenWakeWord 공식 절차에서 막히다
openwakeword의 공식 Colab을 위에서부터 실행해 나가니, cell 9에서 404 에러가 반환되었다.
wget https://huggingface.co/datasets/agkphysics/AudioSet/resolve/main/bal_train00.tar
→ HTTP 404
HuggingFace 측에서 agkphysics/AudioSet이 parquet 형식으로 이행되면서, bal_train00.tar부터 bal_train10.tar까지 전부 삭제되어 있었다. 스킵하고 다음으로 진행하니, 이번에는 torch_audiomentations==0.11.0이 삭제된 API (torchaudio.set_audio_backend("soundfile"))를 호출하여 중단되었다. 더 진행하니, piper-sample-generator 리포지토리가 flat 구성에서 piper_sample_generator/ 패키지로 변경되어 ImportError가 발생했다.
3연속의 문제로 4시간이 사라졌다.
notebook 자체가 1~2년 방치되어 tensorflow-cpu==2.8.1, onnx_tf==1.10.0, HuggingFace의 데이터셋 URL 구조, 의존 라이브러리의 API 등 모든 것이 조금씩 부패해 있었다. bit rot(데이터 부패)이라고 하는 현상이다.
Colab 내장 Gemini에게 수정을 부탁해 보았지만, 「수정했습니다」를 누를 때마다 대개 잘 작동하던 부분까지 함께 되돌아가며 망가져 갔다. 같은 세대의 참조 지식으로 공사를 하고 있기 때문에, 망가지는 부분이 늘어나는 방향으로만 진행된다. 도중에 누르는 것을 그만두었다.
대안을 조사했다
수리를 포기하고 다른 도구를 찾았다. 요구 사항은 다음과 같다.
- 로컬 실행이 가능할 것
- ONNX로 출력 가능할 것 (
openwakeword런타임과의 호환성이 필요함) - 실용 품질일 것 (recall 70% / fpph ≤ 1이 최소 기준)
- 2026년 시점에서 유지보수되고 있을 것
2026년 5월 시점에서의 후보 비교.
| 후보 | 상태 | 채택 판단 |
|---|---|---|
| openwakeword 공식 Notebook | bit rot (1-2년 방치 / 의존 라이브러리 전부 부패) | 불채택 |
| livekit-wakeword | 2026년 신흥 / openwakeword 호환 ONNX 출력 / 1개 명령어로 학습 / 현역 유지보수 | 채택 |
livekit-wakeword는 LiveKit (실시간 음성 AI의 OSS 인프라) 에코시스템의 일부로 정비된 패키지로, 감사하게도 기존의 openwakeword 런타임에 그대로 흘려보낼 수 있는 ONNX를 출력한다. 학습 데이터 조달 (ACAV100M / MUSAN / RIR)과 TTS 합성 (Piper) 그리고 augment(증강)와 train(학습) 및 export(내보내기)까지를 1개 명령어로 통과할 수 있는 설계로, CLI 한 줄만 실행하면 돌아간다. 일본어 기사는 거의 찾을 수 없었지만, 리포지토리와 README는 충분히 읽을 수 있었다.
이를 채택했다.
livekit-wakeword로 학습시키기
학습 환경은 다음과 같다.
- GPU: RTX 5060 Ti (VRAM 16GB)
- OS: Windows 11
- Python: 3.11.9 (venv)
- torch: CUDA 12.8 대응 버전
- 설치:
pip install livekit-wakeword==0.2.0
다른 머신에서는 Tailscale을 통해 SSH로 직접 연결하여 실행했다.
학습 데이터는 livekit-wakeword의 기본 흐름에 따라 수집했다.
- ACAV100M features (16GB pre-computed / HuggingFace
binhpham/livekit_wakeword_features) - FluidInference/musan의 774개 배경 소음 (background noise) wav
- davidscripka MIT RIR (실내 임펄스 응답, room impulse responses)
- Piper VITS (en-us-libritts-high)로 TTS 합성한 positive 10,000 + test 2,000
config (YAML)의 핵심은 target_phrases와 tts_backend뿐이며, 나머지는 defaults로 동작한다.
target_phrases: ["hey assistant"]
tts_backend: piper_vits
voices: [en-us-libritts-high]
...
CLI는 이대로 실행한다.
# generate → augment → train → export 를 순서대로
livekit-wakeword generate --config config.yaml
livekit-wakeword augment --config config.yaml
...
train은 단계(phase)를 나누어 (50,000 + 5,000 + 5,000 steps / LR 1e-4 → 1e-5 → 1e-6) 총 3회 실행했다.
소요 시간
순수 가동 시간의 내역은 다음과 같다.
| 단계 | 소요 시간 |
|---|---|
| setup (Piper VITS + ACAV100M + RIR + backgrounds DL) | 8분 |
| ... | 합계 48분 |
병목 구간(bottleneck)은 generate (TTS 합성)와 train 1st phase였다. train은 RTX 5060 Ti에서 51-65 step/s 속도가 나왔다.
결과
eval JSON 결과는 다음과 같이 도출되었다.
{
"recall": 0.9895,
"accuracy": 0.99475,
...
}
- recall: 98.95% (optimal threshold 0.05에서 99.95%)
- fpph (시간당 오탐지율, False Positive Per Hour): 0.0 (17.82시간의 validation 동안 오검출 제로)
- accuracy: 99.475%
계획 기준은 recall 70% / fpph ≤ 1이었으므로, 내부 eval(평가)로서는 완전히 기준치를 상회하는 수치였다.
ONNX 사이즈는 162KB이다. 이를 openwakeword 런타임(추론 측)에 전달하면, 그대로 불러와서 wake word 판정으로 동작한다. 데몬(daemon)에 통합하여 마이크의 오디오 청크(chunk)를 던져주면, score가 optimal_threshold (0.05) 이상일 때 트리거되는 방식이다.
단, 내부 eval 결과가 너무 완벽할 때는 validation 세트가 train 세트와 유사한 경우가 많다. 실제로 마이크를 향해 "Hey, assistant"라고 말해보니 내부 수치만큼 안정적이지 않은 상황도 있었다. 내부 eval은 학습 목적에 대한 달성도를 측정하는 지표이며, 실용 환경에서 잘 작동하는지는 별도의 검증이 필요하다. 발음 편향(pronunciation bias) 문제와 본인 녹음 데이터의 포함 여부에 대해서는 다음 버전 (v4)에서 별도로 다룰 예정이다.
왜 livekit-wakeword가 좋았는가
openwakeword 공식 Notebook과 livekit-wakeword를 실제로 나란히 놓고 사용해 보았을 때의 차이점은 다음과 같다.
| 관점 | openwakeword 공식 Notebook | livekit-wakeword |
|---|---|---|
| 배포 형태 | Colab notebook (cell 단위) | Python 패키지 + CLI |
| ... | livekit-wakeword generate로 자동 취득 | |
| 학습~export | cell을 순서대로 클릭 + 환경 차이로 인해 막힘 | CLI 한 줄로 통과 |
| 출력 ONNX | openwakeword 런타임 (Runtime) 호환 | openwakeword 런타임 (Runtime) 호환 (동일) |
| 문서 | Notebook 내 주석 중심 | README + CLI help |
요컨대, 학습부터 export까지의 일련의 흐름이 CLI로 긴밀하게 닫혀 있다는 점이 효과적이었다. Notebook 중심의 배포는 cell 단위로 막히기 쉽지만, CLI라면 막히는 지점을 특정하기 쉽고 유지보수 측에서도 따라가기 용이하다. 호환성 (ONNX 출력 대상)은 openwakeword에 맞추고 있으므로, 추론(Inference) 측의 자산은 그대로 사용할 수 있다.
요약
- 2026년 5월 시점에서 독자적인 Wake Word를 만든다면,
livekit-wakeword가 최단 경로다. openwakeword공식 Notebook은 의존 라이브러리의 bit rot (기술적 노후화)이 진행되어 있어, 그대로 사용하기는 어렵다.- RTX 5060 Ti 환경에서는 실용 품질의 모델을 약 48분 (순수 가동 시간) 만에 학습할 수 있었다. 내부 평가(eval) 결과는 recall 98.95% / fpph 0.0이었다. ONNX 파일 크기는 162KB였다.
본 기사는 라이터 AI가 다른 환경의 빌드(build) 로그, 평가(eval) JSON, 실행 명령 기록을 재구성하여 작성한 1차 지식 메모이다. 명령어와 수치는 실제 프로젝트의 것이며, 해석의 편향은 집필 AI의 주관에 따른 것이다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn ML의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기