브라우저에서 텍스트를 보내면, 로컬 LLM이 응답하고, Live2D 캐릭터의 3imi가 표정을 바꾸며 음성으로 답변하는 애플리케이션을 만들었습니다. Open-LLM-VTuber를 기반으로 Ollama 연결, 음성 합성(TTS), Live2D 모델 표시 및 제어를 결합했습니다.
사용된 환경은 Windows 11 Home, Intel Core Ultra 7 265K, RAM 32 GB, GeForce RTX 5070 Ti입니다. GPU 메모리 보고 용량은 16,303 MiB입니다.
| 용도 | 사용 기술 | 선택 이유 |
|---|
| 대화 앱 | Open-LLM-VTuber (Python 서버 및 브라우저 UI) | 대화/음성/Live2D를 연결하는 구조를 재활용하여, 캐릭터와 각 엔진 설정에 집중할 수 있음 |
| ... | | |
브라우저 채팅창
│ WebSocket (텍스트 입력)
▼
...
대화 및 입모양(립싱크) 동작 확인에는 VOICEVOX나 AivisSpeech 같은 기존 TTS를 사용했습니다. Qwen3-TTS VoiceDesign은 음질과 GPU 부하를 테스트하기 위한 단독 프로토타입입니다. 대화 앱에 통합된 것은 아직 확인되지 않았습니다.
conf.yaml 파일에서는 대화 에이전트에 basic_memory_agent를, LLM 제공자(provider)에는 ollama_llm을 지정합니다. ollama_llm의 base_url은 http://127.0.0.1:11434/v1이며, model은 Ollama에서 로드하는 모델 이름입니다. 구현에서는 시작 시 모델 사전 읽기를 /api/chat로, 대화 생성을 OpenAI 호환의 /v1/chat/completions를 사용합니다.
응답은 스트리밍(streaming)으로 받아 정규 표현식(regex)을 이용해 문장 단위로 분리하여 TTS에 전달합니다. 대화 프롬프트에서는 평소 답변 길이를 짧게 하도록 지정했습니다. 전체 답변이 다 나오기 전에, 먼저 확정된 문장의 합성을 시작할 수 있습니다.
일반적인 음성 설정은 tts_model: voicevox_tts입니다. VOICEVOX CORE를 Python에서 호출하여 CPU로 읽어주기를 합성합니다. 冥鳴ひまり의 스타일 ID 14를 사용하여, 표정에 따라 말하는 속도, 억양, 구두점 간격을 변경합니다. 전환용 AivisSpeech 설정에서는 앱의 OpenAI 호환 TTS 클라이언트로부터 127.0.0.1:10201을 거쳐, 127.0.0.1:10101에 있는 AivisSpeech 엔진에 연결합니다.
LLM 응답에 포함된 표정 태그는 읽어주기용 텍스트에서 제외하고, 표정 액션으로 처리합니다. 문장이 분리되어 도착하더라도 표정이 세밀하게 바뀌지 않도록, 첫 발화에 대응하는 표정을 턴(turn) 내에서 유지합니다. 예를 들어 기쁨을 Smile로 할당하여, 표정과 읽어주기의 억양을 같은 발화에 맞춥니다.
분할한 PSD를 PSD2Live로 조정하고, .model3.json과 모델/텍스처/표정/모션 각 파일을 출력했습니다. 앱의 model_dict.json에는 모델 URL, 대기 모션 그룹 이름, 감정과 표정 이름 대응 관계를 등록합니다. conf.yaml에서 live2d_model_name으로 해당 등록명을 선택하면 브라우저에 모델이 표시됩니다.
서버는 음성을 20 ms 간격으로 분할하여 RMS(음량의 기준) 값을 측정하고, 구간별 값을 정규화합니다. 브라우저에는 음성 데이터와 음량 배열, 표정 액션을 동일한 WebSocket 메시지로 보내고, 재생 위치에 맞춰 입 벌림(ParamMouthOpenY)을 움직입니다. 이 방법을 사용하면 TTS를 전환해도 생성된 음성을 이용해 입모양을 구현할 수 있습니다.
| 기능 | 개발 시 확인 사항 |
|---|
| 텍스트 대화와 음성 | 브라우저 입력에 Ollama가 응답하고, 기존 TTS로 읽어주며 입모양을 구현함 |
| ... | |
결과는 각각의 개발 시점 구성에 따라 다릅니다. 30분 테스트는 수동 입력을 포함한 브라우저 테스트입니다. Qwen3-TTS를 연결한 대화, 영어로 진행되는 일련의 대화, 마이크/카메라 입력을 사용한 대화, 방송 댓글 자동 수집, 장시간 무인 송출은 확인되지 않았습니다.
AivisSpeech를 사용한 앱 개선 전후에 동일한 4가지 종류의 입력을 각각 2회 보내, 전송부터 브라우저 음성 재생 시작까지 시간을 측정했습니다. 8회씩 중앙값은 4.69초 → 3.11초였습니다. 이는 LLM 응답 생성부터 브라우저에서의 재생까지를 포함한 비교입니다.
Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign
텍스트로 음색 지시를 전달할 수 있어 테스트했습니다. 참조 오디오를 사용하지 않고, 3가지 목소리를 일본어/영어의 5개 상황에서 시험하여 총 30개의 WAV 파일을 생성했습니다. 프로토타입 환경은 CUDA 12.8, BF16, SDPA입니다.
이 프로토타입 스크립트를 통해 Qwen3-TTS로 일본어 음성을 합성하는 동안, Ollama의 Qwen3.5-9B Q8_0으로 짧은 시험 입력을 보냈습니다.
| 지표 | 실측값 |
|---|
| 시스템 전체 VRAM 사용량 (관측 최대) | 15,838 / 16,303 MiB (약 97.1%) |
| ... | |
| VRAM은 약 0.75초 간격으로 샘플링된 조건에서의 한 번의 결과입니다. 10초 분량의 음성을 전체 생성하는 데는 약 16.6초가 걸렸으며, VRAM 여유분은 465 MiB였습니다. 앱에 통합했을 경우 발화 시작까지의 시간은 측정하지 않았습니다. | |
Qwen3-TTS 통합 — TTS 어댑터를 연결하고, 전송부터 재생 시작까지의 지연 시간과 VRAM 사용량을 측정합니다. 장문 및 일/영 전환을 통해 음색도 확인했습니다.
스트리밍 입력 연결 — YouTube 등의 댓글 획득과 마이크/카메라 입력을 개별적으로 검증하여, 입력부터 답변 및 Live2D 표시까지의 과정을 거칩니다.
연속 운영 검증 — OBS를 사용하여 실제 스트리밍 구성에서 발화 중복, 끼임(interruption), 끊김 후 복귀, 장시간 리소스 사용량을 확인했습니다.