watch_sceen_ai

디스코드에서 음성으로 대화하는 AI. 최종 목표는 화면공유(Go Live)까지 실시간으로 보면서 대화하는 것이지만, 지금은 화면공유(눈)를 잠시 미뤄두고 음성 대화 루프 STT → 두뇌 → TTS부터 완성하는 단계다.

  • 실행 위치: 이 리눅스 호스트(.9, RTX 5050 8GB / ffmpeg / node v22 있음)
  • 현재 상태: 음성 루프 뼈대 동작 — 파이프라인이 눈 없이(화면공유 없이) 돌아간다 (python -m wsai --voice). STT/TTS/두뇌는 아직 mock이며, 실제 엔진 연결이 다음 목표.
  • 보류 중: 화면공유 수신(눈). E2EE 합류 관문은 이미 통과해 두었고(아래 8장), 음성 루프가 자리 잡으면 다시 붙인다.

1. 설계 원칙

  1. 지연이 전부다. 음성 대화형이라 "정확하지만 느린" 답은 실패다. 전 구간을 스트리밍으로 잇고, 목표는 사용자가 말 끝낸 뒤 첫 소리까지 ~1.5초 이내.
  2. 싼 것부터, 필요할 때만 비싸게. 로컬(GPU)에서 처리할 수 있는 건 로컬에서, 정말 필요한 것만 클라우드로 올린다.
  3. 부품은 교체 가능해야 한다. 귀/두뇌/입(그리고 나중의 눈)이 전부 wsai/interfaces.py의 Protocol이라, 어느 하나가 바뀌어도 나머지는 그대로 돌아간다. 실제로 눈(source/vision)은 선택 사항이라, 없으면 파이프라인이 음성 루프만 돌린다.

2. 전체 구조

두 개의 async 루프가 있고, 지금은 대화 루프만 켜서 쓴다. 인지(눈) 루프는 나중에 붙인다.

[대화 루프]  SpeechToText ──Utterance──▶  Brain(LLM) ──▶ TextToSpeech
             (귀)                          (두뇌)          (입)
                                             ▲
                                             │ (화면 맥락: 지금은 비어 있음)
[인지 루프]  FrameSource ─▶ VisionBackend ─┘   ← 보류 (source/vision = None)
             (눈)
  • 대화 루프: 사용자 발화 → 두뇌(대화이력 + 있으면 최신 화면 맥락) → 음성 응답.
  • 인지 루프: source/vision이 없으면 통째로 건너뛴다. 눈을 붙이면 최신 화면 맥락을 채워 넣어, 두뇌가 "지금 화면"을 참고할 수 있게 된다.
  • 두 루프는 비동기로 독립. 눈이 생겨도 대화 루프는 프레임 하나하나를 기다리지 않고 "가장 최근에 이해된 화면"만 읽는다.

데이터 타입/인터페이스는 wsai/interfaces.py에 정의돼 있다: Frame, ScreenObservation, Utterance, Reply / FrameSource, VisionBackend, SpeechToText, TextToSpeech, Brain, TextChannel.


3. 귀 / 두뇌 / 입 — 지금 만드는 음성 루프

귀 (STT)

  • faster-whisper 스트리밍/부분 전사. 마이크는 sounddevice.
  • 발화 종료 판정(endpointing)으로 사용자가 말을 멈춘 시점을 빠르게 잡는다.

두뇌 (Brain)

  • Claude(OAuth, Haiku 계열)로 대화 응답 생성. 저비용·빠른 모델을 기본으로 한다.
  • 입력은 "대화이력 + (있으면) 최신 화면 맥락 1건"만 넣어 토큰을 작게 유지한다.
  • 눈이 없는 지금은 화면 맥락이 비어 있고, 두뇌는 그 사실을 솔직히 말한다.

입 (TTS)

  • MeloTTS 등(이 호스트에 기존 자산 있음). 문장 단위로 스트리밍 재생.
  • 인터럽트: 사용자가 말하기 시작하면 재생 중인 TTS를 즉시 멈춘다(barge-in).

지연 예산(목표)

사용자 발화 종료 → 첫 소리까지:

구간 목표
STT 종료 판정(endpointing) ~200 ms
Brain 첫 토큰 ~500 ms
TTS 첫 문장 합성·재생 시작 ~400 ms
여유 ~400 ms
합계 ~1.5 s

4. 눈 — 화면공유 수신 (보류, 나중에)

최종 목표엔 화면공유가 들어가지만, 지금은 의도적으로 미뤄둔 부분이다. 아래는 나중에 다시 붙일 때를 위한 기록이다. 두 트랙을 병행할 계획이었다.

트랙 A (주력) — 화면공유 스트림 직접 수신

스크린샷·브라우저 캡처가 아니라, 실제 화면공유 스트림 자체를 클라이언트처럼 수신한다. 공식 봇 API는 비디오 수신을 막으므로 유저 토큰(셀프봇) 으로 프로토콜 레벨에서 비디오 RTP를 받는다(전용 버너 계정만 사용). 파이프: join → Go Live "watch" 구독 → 암호화 RTP 수신 → DAVE(MLS E2EE) 복호 → 전송암호 복호 → VP8/H264 depayload → ffmpeg 디코드 → 프레임. DAVE는 @snazzah/davey(Rust NAPI), 수신은 discord.js-selfbot 계열.

솔직한 리스크: 완성형 라이브러리가 없어 직접 조립해야 하고, 셀프봇은 ToS 회색지대라 계정 밴 위험이 있다(→ 버너 전용). 그래서 음성 루프를 먼저 세우는 지금 순서가 안전하다.

트랙 B (폴백/개발용) — 로컬 렌더 화면 캡처

디스코드 클라이언트가 화면공유를 보고 있는 화면을 로컬에서 캡처한다. 트랙 A가 막힐 때의 안전판이자 개발용 실용 소스. poc/의 Xvfb 실험과 wsai/backends/capture_mss.py가 여기 해당.

두 트랙 모두 결과물은 동일한 Frame 스트림이라, 눈을 붙일 때 나머지는 손대지 않는다.


5. 실행

이 호스트에는 python 별칭이 없으므로 워크스페이스 venv를 쓴다(.venv/bin/python).

.venv/bin/python -m wsai --voice    # 눈 없는 음성 루프 데모 (STT→두뇌→TTS, 지금 초점)
.venv/bin/python -m wsai            # mock 데모 (눈 포함 전체 흐름, 몇 프레임 돌고 종료)
.venv/bin/python -m wsai --env      # WSAI_* 환경변수로 백엔드 조립
.venv/bin/python -m pip install pytest && .venv/bin/python -m pytest -q   # 스모크 테스트
  • WSAI_SOURCE=none WSAI_VISION=none 으로도 눈 없이(음성 루프만) 조립할 수 있다.
  • 백엔드별 추가 설치는 requirements.txt 주석 참고(faster-whisper, mss/pillow, anthropic 등).

6. 파일 / 디렉터리

경로 역할
wsai/interfaces.py 데이터 타입 + 컴포넌트 Protocol
wsai/pipeline.py 오케스트레이터(대화 루프 + 선택적 인지 루프)
wsai/state.py 최신 화면 맥락 공유 저장소(눈이 생기면 사용)
wsai/config.py / factory.py 설정 → 백엔드 조립. voice() = 눈 없는 음성 프리셋
wsai/backends/mock.py 무의존성 mock 전 계열
wsai/backends/capture_mss.py 로컬 화면 캡처(트랙 B, 보류)
wsai/backends/claude.py Claude 비전 + 두뇌
dave/gate.mjs DAVE/MLS E2EE 합류 관문 검증(통과 증거, 눈 재개 시 재사용)
poc/ Xvfb+Chromium 캡처 실험(트랙 B 참고)
PLAN.md 단계별 착수 계획
tests/test_pipeline.py 파이프라인 스모크 테스트

7. 구현 순서 (검증 가능한 체크포인트)

음성 루프 먼저, 눈은 나중에.

  • 파이프라인 스켈레톤 — mock 모드로 전 흐름 동작.
  • 눈 없는 음성 루프. source/vision 없이 STT→Brain→TTS만 돌아간다(--voice). · 검증: python -m wsai --voice가 화면 없이 발화마다 응답을 낸다(테스트 포함).
  • V1 · 진짜 TTS(입). MeloTTS로 두뇌 응답을 실제 음성으로 합성. · 검증: 응답 텍스트가 .wav로 합성돼 들린다.
  • V2 · 진짜 STT(귀). faster-whisper로 오디오를 텍스트로 전사. · 검증: 오디오 파일/마이크 입력이 텍스트로 나온다.
  • V3 · 진짜 두뇌. Claude OAuth(Haiku)로 대화 응답 생성. · 검증: 실제 발화에 자연스러운 답이 나온다.
  • V4 · 음성 왕복 + barge-in. STT→Brain→TTS 스트리밍, 말 끊기, 지연 예산 측정. · 검증: 말로 묻고 말로 답을 듣는다, 첫 소리까지 ~1.5s 근처.
  • (나중) 눈 재개. 트랙 A/B로 화면공유 수신 → 화면 맥락을 두뇌에 연결.

8. 결정이 필요한 것 (사용자 확인 대기)

실제 STT/TTS 엔진을 붙이기 전에 정해야 할 것들:

  • GPU 사용 동의 — RTX 5050으로 STT/TTS를 돌리면 빠르다(규칙상 GPU는 먼저 확인 필요).
  • 파이썬 버전 — 이 venv는 3.14인데 faster-whisper·MeloTTS는 3.11대가 안전하다. 호스트에 이미 MeloTTS용 3.11 자산이 있어, 별도 3.11 venv + subprocess 연결을 제안.
  • 엔진 선택 — STT는 faster-whisper, TTS는 MeloTTS(한국어) 기본안.
  • 두뇌 — Claude OAuth(Haiku 계열)로 연결(지금 코드는 API키 기반이라 OAuth 전환 필요).
Description
No description provided
Readme 389 KiB
Languages
Python 78.6%
JavaScript 19.7%
Dockerfile 0.9%
HTML 0.4%
Shell 0.4%