Files
realtime_voice_bot/README.md

6.0 KiB

realtime_voice_bot

출력장치로 재생되는 소리를 파일 저장 없이 바로 받아서 faster-whisper로 STT 테스트를 하고, 필요하면 Ollama LLM과 연결된 통합 테스트와 LLM CLI 테스트를 할 수 있는 최소 프로토타입입니다.

현재 문서는 Windows PC에서 실행하는 기준으로 적었습니다.

현재 범위

  • Node.js + TypeScript 메인 프로세스
  • 출력 오디오 실시간 캡처
  • 메모리 버퍼 기반 간단한 저지연 발화 분리
  • 미리 로드한 faster-whisper 워커에 PCM 직접 전달
  • 디스크에 WAV 저장 없이 바로 전사
  • STT 전용 테스트
  • STT 결과에 대해 답변 가치 판단 후 필요할 때만 LLM 답변하는 통합 테스트
  • 로컬 Ollama LLM 에이전트 CLI 테스트
  • 무료 로컬 MeloTTS 기반 음성 출력 테스트

빠른 시작

bun install
bun run setup
copy .env.example .env

장치 목록 확인:

bun run devices

실행:

bun run test:stt

STT + LLM 통합 테스트:

bun run test:sttllm

LLM 단독 테스트:

bun run test:llm

TTS 단독 테스트:

bun run test:tts -- "안녕하세요. 로컬 티티에스 테스트입니다."

환경 변수

  • AUDIO_SOURCE
    • bun run devices 에서 보이는 ffmpeg dshow 오디오 장치 이름
    • 보통 Stereo Mix, 오디오 인터페이스 loopback 채널, 가상 케이블 입력 같은 이름을 넣습니다
  • DOCKER_BIN
    • 비워두면 자동 탐색
    • VSCode가 오래 떠 있어서 docker PATH를 못 잡을 때만 설정
    • 예: C:\Program Files\Docker\Docker\resources\bin\docker.exe
  • DEBUG
    • true면 상세 로그 출력
    • false면 전사 결과만 출력
  • WHISPER_MODEL
    • 기본값 large-v3-turbo
  • OLLAMA_BASE_URL
    • 기본값 http://127.0.0.1:11434
  • OLLAMA_MODEL
    • 기본값 qwen3:8b
  • TTS_ENABLED
    • 기본값 true
  • TTS_IMAGE
    • 기본값 realtime-voice-bot-melotts:v0.1.2
  • TTS_LANGUAGE
    • 기본값 KR
  • TTS_SPEAKER
    • 기본값 KR
  • TTS_DEVICE
    • 기본값 cpu
    • Docker GPU passthrough를 쓸 때만 cuda로 바꿉니다
  • TTS_SPEED
    • 기본값 1
  • OLLAMA_KEEP_ALIVE
    • 기본값 5m
  • MAX_CONVERSATION_TURNS
    • 기본값 6
    • 최근 대화 몇 턴까지 LLM 문맥으로 넘길지 정합니다
  • WHISPER_LANGUAGE
    • 기본값 ko
  • WHISPER_DEVICE
    • auto, cuda, cpu
  • WHISPER_COMPUTE_TYPE
    • auto, float16, int8_float16, int8, float32
  • WHISPER_BEAM_SIZE
    • 기본값 2
  • SEGMENT_END_FRAMES
    • 기본값 24
    • 끝을 조금 더 늦게 잘라서 문장이 잘게 끊기는 현상을 줄입니다
  • SEGMENT_MAX_SPEECH_SAMPLES
    • 기본값 160000
    • 너무 긴 구간은 강제로 끊어서 지연이 과하게 커지는 걸 막습니다

메모

  • 이 버전은 STT, STT+LLM, LLM 테스트를 따로 제공합니다.
  • test:sttllm에서 TTS가 켜져 있으면 답변을 스피커로 읽어줍니다.
  • test:sttllm에서는 자기 음성을 다시 전사하지 않도록 TTS 재생 중에는 캡처를 잠시 멈춥니다.
  • LLM 프롬프트는 prompts/*.md 에 분리되어 있습니다.
  • 최소 지연을 위해 파일 저장은 하지 않습니다.
  • VAD는 현재 모델 기반이 아니라 진폭 기반 단순 분리입니다.
  • Windows에서는 보통 출력 루프백이 가능한 장치나 Stereo Mix, 오디오 인터페이스 loopback 채널을 AUDIO_SOURCE로 잡아야 합니다.
  • 단순히 스피커 이름을 넣는 구조가 아니라, 루프백/캡처 가능한 입력 장치 이름을 넣어야 합니다.
  • ffmpeg가 PATH에 잡혀 있어야 합니다.
  • TTS는 Windows에서 Docker Desktop이 필요합니다. MeloTTS 공식 문서도 Windows/macOS에서는 Docker 실행을 권장합니다.
  • cmd 기준으로 .envcopy .env.example .env로 만들면 됩니다.

Windows 테스트 순서

  1. bun install
  2. bun run setup:stt
  3. copy .env.example .env
  4. bun run devices
  5. .env에서 AUDIO_SOURCE=에 루프백 장치 이름 입력
  6. bun run test:stt
  7. 유튜브, 디스코드 통화, 동영상 같은 소리를 재생해서 전사만 확인

Windows STT+LLM 통합 테스트 순서

  1. bun run setup:llm
  2. bun run setup:tts
  3. bun run test:sttllm
  4. 유튜브, 디스코드 통화, 동영상 같은 소리를 재생해서 전사와 답변, 음성 출력 확인

Windows LLM 테스트 순서

  1. bun run setup:llm
  2. bun run test:llm
  3. 콘솔에 직접 문장을 입력하고 답변 확인
  4. /reset 으로 문맥 초기화, /exit 로 종료

Windows TTS 테스트 순서

  1. Docker Desktop 실행
  2. bun run setup:tts
  3. bun run test:tts -- "안녕하세요. 로컬 티티에스 테스트입니다."

현재 test:llm 에이전트 도구:

  • 현재 시간 조회
  • 현재 런타임 설정 조회
  • 주요 bun 명령 목록 조회
  • 간단한 산술식 계산
  • 웹 검색
  • URL 본문 읽기

동작 원칙:

  • 일반 대화는 로컬 LLM만 답변
  • 최신 정보, 뉴스, 사실 확인, 검색 요청일 때만 웹 도구 사용
  • test:sttllm 에서는 먼저 "대답할 가치가 있는 텍스트인지" 판정한 뒤 필요할 때만 답변
  • 웹 검색이 실제로 시작되면 결과 전에 검색해볼게요. 같은 진행 메시지를 먼저 출력
  • 답변에 한글 외 다른 문자군이 섞이면 한국어만으로 한 번 더 교정

현재 프롬프트 파일:

  • prompts/assistant.md
  • prompts/reply-gate.md
  • prompts/rewrite-korean.md

Windows용 .env 예시

LOCAL_AI_PYTHON=python
AUDIO_SOURCE=
DEBUG=false
TTS_ENABLED=true
TTS_IMAGE=realtime-voice-bot-melotts:v0.1.2
TTS_LANGUAGE=KR
TTS_SPEAKER=KR
TTS_DEVICE=cpu
TTS_SPEED=1
TTS_CACHE_DIR=.local-ai/tts-cache
TTS_OUTPUT_DIR=.local-ai/tts-output
OLLAMA_BASE_URL=http://127.0.0.1:11434
OLLAMA_MODEL=qwen3:8b
OLLAMA_KEEP_ALIVE=5m
MAX_CONVERSATION_TURNS=6
WHISPER_MODEL=large-v3-turbo
WHISPER_LANGUAGE=ko
WHISPER_DEVICE=auto
WHISPER_COMPUTE_TYPE=auto
WHISPER_BEAM_SIZE=2
SEGMENT_END_FRAMES=24
SEGMENT_MAX_SPEECH_SAMPLES=160000
DEBUG_TRANSCRIPTS=true
LOG_LEVEL=info