Discord 음성 채널에서 텍스트를 읽어주는 TTS(Text-to-Speech) 봇입니다.
디스코드에서 TTS 봇들을 사용하는 이유는 주로 마이크를 사용하지 못하지만 음성 채널에서 소통하기 위해 사용됩니다. 기존에 사용하던 TTS 봇들은 서버 이슈나 사용자 몰림으로 인해 갑자기 사용이 불가능해지는 경우가 자주 있었습니다. 이 문제를 해결하기 위해 직접 운영하는 서버 기반의 TTS 봇을 개발했습니다.
외부 API에만 의존하지 않고 로컬 TTS 엔진을 함께 운영해, 외부 서비스 장애가 발생하더라도 항상 사용할 수 있는 것을 목표로 합니다.
- 음성 채널에서 TTS를 자주 사용하는 Discord 서버
- 기존 TTS 봇의 잦은 장애로 불편을 겪는 사용자
- 다양한 목소리와 언어를 지원하는 TTS가 필요한 서버
| 엔진 | 언어 | 방식 | 특징 |
|---|---|---|---|
| edge-tts | 한국어 | MS 서버 (비공식) | 가장 빠름, 거의 실시간, 자연스러운 발음 |
| MeloTTS | 한국어 | 로컬 추론 | 완전 오프라인, 외부 장애 무관 |
| Kokoro | 영어/한국어 | 로컬 추론 | IPA 변환으로 한국어 지원, 다양한 영어 목소리 |
edge-tts가 기본 엔진으로 사용되며, 로컬 엔진(MeloTTS, Kokoro)은 외부 API 장애 시 대안으로 활용할 수 있습니다.
/채널설정으로 지정한 채널에 메시지를 입력하면 자동으로 TTS를 재생합니다. 봇이 음성 채널에 없으면 자동으로 입장합니다.
사용자별로 목소리를 설정할 수 있습니다. 설정은 서버 간에 공유되며 재시작 후에도 유지됩니다.
- 큐 모드 OFF (기본): 새 메시지가 오면 현재 재생을 중단하고 즉시 재생합니다.
- 큐 모드 ON: 현재 재생이 완료된 후 순서대로 재생합니다. 여러 사람이 동시에 입력해도 순서가 보장됩니다.
- 자모(
ㅋㅋ,ㄹㅇ등) → 한글 이름으로 변환 - 영어 약어(
tts,gg등) → 알파벳 한 글자씩 읽기 - 영어 일반 단어(
hello,control등) → 그대로 발음 - 숫자 → 한글 숫자로 변환
- 링크, 이미지, 멘션만 있는 메시지 → 자동 무시
- 채널에 아무도 없으면 자동 퇴장
- TTS 생성 실패 시 이모지 반응으로 피드백
- 이미 다른 음성 채널에서 봇 사용 중이면 가져가기 불가
| 명령어 | 설명 |
|---|---|
/입장 |
현재 입장해 있는 음성 채널에 봇 입장 |
/퇴장 |
봇 음성 채널에서 퇴장 및 큐 초기화 |
/채널설정 |
현재 텍스트 채널을 TTS 채널로 설정 |
/목소리 |
목소리 변경 |
/내목소리 |
현재 설정된 목소리 확인 |
/tts [텍스트] |
입력한 텍스트를 TTS로 재생 |
/큐모드 |
큐 모드 ON/OFF 전환 |
/스킵 |
현재 재생 중인 TTS 스킵 |
| 키 | 설명 |
|---|---|
ko-SunHi |
🇰🇷 선희 - 한국어 여성 (기본값) |
ko-InJoon |
🇰🇷 인준 - 한국어 남성 |
ko-Hyunsu |
🇰🇷 현수 - 한국어 남성 |
| 키 | 설명 |
|---|---|
ko-local |
🇰🇷 로컬 - 한국어 로컬 |
| 키 | 설명 |
|---|---|
af_heart |
🇺🇸 Heart - 미국 영어 여성 |
af_bella |
🇺🇸 Bella - 미국 영어 여성 |
af_nicole |
🇺🇸 Nicole - 미국 영어 여성 |
af_sarah |
🇺🇸 Sarah - 미국 영어 여성 |
am_adam |
🇺🇸 Adam - 미국 영어 남성 |
am_michael |
🇺🇸 Michael - 미국 영어 남성 |
am_fenrir |
🇺🇸 Fenrir - 미국 영어 남성 |
am_puck |
🇺🇸 Puck - 미국 영어 남성 |
bf_emma |
🇬🇧 Emma - 영국 영어 여성 |
bf_isabella |
🇬🇧 Isabella - 영국 영어 여성 |
bm_george |
🇬🇧 George - 영국 영어 남성 |
bm_lewis |
🇬🇧 Lewis - 영국 영어 남성 |
Discord 봇 (Node.js)
├── edge-tts-universal (MS 서버 스트리밍)
├── HTTP POST → MeloTTS Flask 서버 (127.0.0.1:5050)
└── HTTP POST → Kokoro Flask 서버 (127.0.0.1:5051)
Discord 봇과 TTS 엔진 서버를 분리해 각 엔진을 독립적으로 관리합니다. Flask 서버는 localhost에서만 통신하며, 오디오 데이터를 메모리 버퍼로 반환해 디스크 I/O 없이 처리합니다.
AlgoBot/
├── index.js # 진입점
├── melo_server.py # MeloTTS Flask 서버 (포트 5050)
├── kokoro_server.py # Kokoro Flask 서버 (포트 5051)
├── src/
│ ├── config.js # VOICES, 설정, settings.json 관리
│ ├── tts.js # TTS 생성 (generateTTS)
│ ├── player.js # 음성 재생 (playTTS, 큐 관리)
│ ├── commands.js # 슬래시 명령어 정의 및 등록
│ ├── textProcessor.js # 텍스트 전처리
│ └── events/
│ ├── interaction.js # 슬래시 명령어 처리
│ └── message.js # TTS 채널 자동 감지
├── melo-venv/ # MeloTTS Python 가상환경
├── kokoro-venv/ # Kokoro Python 가상환경
├── settings.json # 서버별 채널/목소리/큐모드 설정 저장
└── .env # 환경 변수
- 인스턴스: AWS EC2 t3.medium (x86, 2vCPU, 4GB RAM)
- OS: Ubuntu 24.04 LTS
- 스왑: 4GB
- 고정 IP: Elastic IP 연결
- 프로세스 관리: pm2 (melo, kokoro, bot 각각 독립 실행, 재시작 시 자동 복구)
npm install# MeloTTS 가상환경
python3 -m venv melo-venv
source melo-venv/bin/activate
pip install torch torchaudio flask soundfile
pip install git+https://github.com/myshell-ai/MeloTTS.git
deactivate
# Kokoro 가상환경
python3 -m venv kokoro-venv
source kokoro-venv/bin/activate
pip install kokoro soundfile flask numpy eng-to-ipa
deactivatepm2 start melo_server.py --name melo --interpreter ./melo-venv/bin/python3
pm2 start kokoro_server.py --name kokoro --interpreter ./kokoro-venv/bin/python3
pm2 start index.js --name bot
pm2 start server/index.js --name server
pm2 save
pm2 startup # EC2 재부팅 시 자동 시작 설정# 터미널 1
source melo-venv/bin/activate && python3 melo_server.py
# 터미널 2
source kokoro-venv/bin/activate && python3 kokoro_server.py
# 터미널 3
node index.js
# 터미널 4
npm run dev:server
# 터미널 5 (프론트엔드)
cd web && npm run dev새 목소리가 추가되었을 때 해당 목소리의 샘플 파일만 생성합니다. MeloTTS, Kokoro 서버가 실행 중인 상태에서 진행해야 합니다.
node generateSamples.js [voice_key]
# 예시: node generateSamples.js ko-SunHi- 도메인: algottsbot.com (AWS Route 53)
- SSL: Let's Encrypt (Certbot, 90일마다 자동 갱신)
- 웹 서버: nginx (80 → HTTPS 리다이렉트, 443에서 프론트/백엔드 라우팅)
/auth/discord,/auth/me,/user/,/notices,/inquiries,/admin/,/samples/→ Express(3000) 프록시- 그 외 모든 경로 → Vue 빌드 결과물 (
web/dist) 정적 서빙
cd web
npm run build| 포트 | 용도 |
|---|---|
| 22 | SSH |
| 80 | HTTP (HTTPS 리다이렉트) |
| 443 | HTTPS |
TOKEN=디스코드봇토큰
DEV_TOKEN=개발용봇토큰
NODE_ENV=production
NODE_ENV=development로 설정하면 DEV_TOKEN을 사용하는 개발용 봇(아루고수-dev)으로 실행됩니다.
봇 설정을 웹에서도 관리할 수 있도록 Vue 3 기반 웹페이지를 추가했습니다. Discord OAuth로 로그인하며, 사용자 페이지(목소리/속도 설정, 공지사항, 문의)와 관리자 페이지(사용량 대시보드, 봇 상태, 에러 로그, 문의/공지 관리)로 구성됩니다.
- 프론트엔드: Vue 3 + TypeScript + Vite + Vue Router + Pinia + Naive UI + Chart.js
- 백엔드: 기존 Node.js 봇 프로세스에 Express 추가 (별도 프로세스 아님)
- DB: SQLite (better-sqlite3, WAL 모드)
- 인증: Discord OAuth2 + JWT
AlgoBot/
├── web/ # Vue 3 프론트엔드
│ ├── src/
│ │ ├── pages/
│ │ │ ├── user/ # Home, Notice, Voice, Inquiry
│ │ │ └── admin/ # Dashboard, Status, Logs, Notice, Inquiry
│ │ ├── components/layout/ # UserLayout, AdminLayout
│ │ ├── stores/user.ts # Pinia 유저 스토어 (로그인 상태, JWT)
│ │ └── router/index.ts # 라우터 + 관리자 권한 가드
│ └── .env # VITE_API_URL
├── server/ # Express 백엔드
│ ├── index.js # 서버 진입점
│ ├── routes/ # auth, user, notice, inquiry, admin/*
│ ├── middleware/ # JWT 인증, 관리자 권한 체크
│ └── db/ # SQLite 스키마 및 연결
# 백엔드
npm run dev:server
# 프론트엔드
cd web
npm run dev -- --host| 변수 | 설명 |
|---|---|
NODE_ENV |
실행 환경. production 또는 development |
DISCORD_CLIENT_ID |
Discord Developer Portal에서 발급한 운영용 앱의 Client ID |
DISCORD_CLIENT_SECRET |
운영용 앱의 Client Secret |
DISCORD_REDIRECT_URI |
운영 환경의 OAuth 콜백 주소 (예: https://도메인/auth/discord/callback) |
DEV_DISCORD_CLIENT_ID |
개발용 앱의 Client ID |
DEV_DISCORD_CLIENT_SECRET |
개발용 앱의 Client Secret |
DEV_DISCORD_REDIRECT_URI |
개발 환경의 OAuth 콜백 주소 (예: http://localhost:3000/auth/discord/callback) |
ADMIN_DISCORD_ID |
관리자 권한을 부여할 Discord 계정 ID |
JWT_SECRET |
JWT 토큰 서명에 사용할 랜덤 문자열 |
SERVER_PORT |
Express 서버 포트 (기본값: 3000) |
WEB_URL |
프론트엔드 주소. CORS 허용 및 OAuth 콜백 리다이렉트에 사용 |
BOT_HEALTH_PORT |
봇 헬스체크 서버 포트 (기본값: 3001) |
web/.env에는 VITE_API_URL로 백엔드 주소를 지정합니다. (예: https://도메인)
2026-07-08 — 운영 환경 구축, 보안 강화
- 도메인이 연결되었습니다.
- algottsbot.com 도메인으로 접속할 수 있습니다.
- HTTPS가 적용되었습니다.
- Let's Encrypt SSL 인증서가 적용되어 안전하게 접속할 수 있습니다.
- 인증서는 자동으로 갱신됩니다.
- 보안이 강화되었습니다.
- 불필요한 포트(3000, 5173)가 차단되었습니다.
- 외부에서는 80(HTTP), 443(HTTPS) 포트로만 접근 가능합니다.
- HTTP로 접속하면 자동으로 HTTPS로 리다이렉트됩니다.
- 서버 안정성이 개선되었습니다.
- pm2로 모든 프로세스를 관리합니다.
- 서버가 재부팅되면 모든 프로세스가 자동으로 다시 시작됩니다.
2026-07-03 — 목소리 설정 통합, 디스코드 목소리 선택 UI 개선, 미리듣기 기능 추가
- 디스코드와 웹페이지의 목소리 설정이 하나로 통합되었습니다.
- 어느 쪽에서 바꾸든 동일하게 반영됩니다.
- 디스코드에서
/목소리로 바꾸면 웹페이지에서도 같은 목소리로 표시됩니다. - 웹페이지에서 바꾸면 디스코드에서도 동일한 목소리로 재생됩니다.
- 웹 창에 포커스가 돌아오면 자동으로 최신 설정으로 갱신됩니다.
- 디스코드에서 목소리를 더 편하게 바꿀 수 있습니다.
/목소리명령어 실행 시 드롭다운 메뉴로 목소리를 선택할 수 있습니다.- 메시지를 닫기 전까지 계속 바꿀 수 있습니다.
- 현재 선택된 목소리가 드롭다운에 표시됩니다.
- 더 많은 설정은 웹페이지 링크로 바로 이동할 수 있습니다.
- 목소리 미리듣기 기능이 추가되었습니다.
- 각 목소리 카드에서 "미리듣기" 버튼으로 샘플 음성을 들을 수 있습니다.
- 재생 중 버튼을 다시 누르면 정지됩니다.
- 설정한 재생 속도가 미리듣기에도 반영됩니다.
2026-06-26 — 에러 로그 범위 확대, 관리자 페이지 이동 개선
- 에러 로그에서 더 많은 문제 상황을 확인할 수 있습니다.
- 명령어 처리, 메시지 처리, 음성 채널 연결 등 다양한 상황의 오류가 기록됩니다.
- Discord 로그인 실패, 잘못된 접근 시도도 기록됩니다.
- 예상하지 못한 오류가 발생해도 봇이 종료되지 않고 계속 동작하며, 내용이 로그에 남습니다.
- 관리자 페이지로 이동하기 편해졌습니다.
- 관리자 계정으로 로그인하면 상단 메뉴에 "관리자" 링크가 나타납니다.
- 관리자 페이지에서도 "사용자 페이지로" 링크로 쉽게 돌아갈 수 있습니다.
2026-06-19 — 실데이터 연동, 봇 안정성 개선
- 웹페이지가 더미데이터 대신 실제 데이터로 동작합니다.
- 목소리 목록과 내 설정(목소리/속도)이 실시간으로 연동됩니다.
- 공지사항, 문의 목록이 실제 등록된 내용으로 표시됩니다.
- 홈에서 공지사항/문의 항목을 클릭하면 해당 페이지로 이동해 바로 펼쳐서 볼 수 있습니다.
- 관리자 사용량 대시보드가 실제 TTS 사용 기록을 기준으로 집계됩니다.
- 봇 상태를 실시간으로 확인할 수 있습니다.
- Discord 봇, MeloTTS, Kokoro 엔진의 상태를 주기적으로 자동 점검합니다.
- 봇 상태 페이지를 열어두면 약 10초마다 자동으로 최신 상태로 갱신됩니다.
- 서비스 상태가 바뀌면(정상↔오류) 에러 로그에 자동으로 기록됩니다.
- 안정성이 크게 개선되었습니다.
- 로컬 TTS 엔진(MeloTTS, Kokoro)에 연결할 수 없을 때 봇 전체가 종료되던 문제를 고쳤습니다.
- 이제 TTS 생성에 실패해도 봇은 계속 동작하며, 실패 내용이 에러 로그에 남습니다.
2026-06-17 — Discord 로그인 지원
- 웹페이지에서 Discord 계정으로 로그인할 수 있게 되었습니다.
- 새로고침하거나 다시 접속해도 로그인 상태가 유지됩니다.
- 로그인하면 프로필 사진과 이름이 화면에 표시됩니다.
- 화면 레이아웃이 개선되었습니다.
- 로그인 전/후에도 메뉴 위치가 흔들리지 않도록 정리했습니다.
- 관리자 페이지가 보호됩니다.
- 로그인 및 권한이 있는 계정만 접근할 수 있습니다.
- 재로그인 속도가 개선되었습니다.
- 동의 화면이 더 빠르게 지나가도록 했습니다.
2026-06-15 — 목소리/속도 설정, 문의 기능 개선
- 목소리·속도 설정 방식이 개선되었습니다.
- 슬라이더로 재생 속도를 조절할 수 있습니다.
- 미리듣기로 먼저 확인한 뒤 "적용" 버튼을 눌러야 실제로 반영됩니다.
- 의도치 않게 설정이 바뀌는 일이 없도록 했습니다.
- 현재 사용 중인 목소리가 스크롤해도 항상 상단에 보입니다.
- 공지사항 화면이 개선되었습니다.
- 목록에서는 한 줄만 보이고, 클릭하면 펼쳐서 전체 내용을 볼 수 있습니다.
- 여러 개를 동시에 펼쳐볼 수 있습니다.
- 문의 기능이 개선되었습니다.
- 문의하기가 팝업 형태로 바뀌어 더 간단하게 작성할 수 있습니다.
- 문의 목록에서 다른 사람이 남긴 문의 내용과 답변 상태를 함께 볼 수 있습니다.
- 관리자 페이지가 추가되었습니다.
- 사용량 대시보드(목소리별 비율, 시간대별 사용량, 일별 추이)
- 서버 상태, 에러 로그
- 문의/공지 관리 화면
2026-06-12 — 웹페이지 첫 공개
- Discord 봇 설정을 웹브라우저에서도 관리할 수 있는 웹페이지가 새로 생겼습니다.
- 홈, 공지사항, 목소리·설정, 문의 페이지를 이용할 수 있습니다.
2026-06-10 — 관리자 페이지 준비
- 운영자가 사용량과 봇 상태를 확인할 수 있는 관리자 페이지를 준비 중입니다.
2026-06-08 — 채널 설정 사용성 개선
/채널설정동작이 더 편리해졌습니다.- 다시 실행하면 같은 채널이면 설정이 해제됩니다.
- 다른 채널이면 기존 설정을 해제하고 새로 설정됩니다.
- 어떤 채널이 해제/설정됐는지 메시지로 안내합니다.
2026-05-20 — 안정성 개선
- TTS 생성과 재생 과정의 안정성이 개선되었습니다.
2026-05-11 — 로컬 TTS 속도 개선
- MeloTTS, Kokoro의 응답 속도가 개선되었습니다.
- 음성을 생성할 때 디스크에 파일을 저장하지 않고 메모리에서 바로 처리하도록 변경했습니다.
2026-05-08 — MeloTTS 안정성 개선
- MeloTTS 엔진의 안정성이 개선되었습니다.
2026-05-06 — 개발 환경 분리
- 운영 중인 봇과 별개로 개발용 봇이 분리되었습니다.
- 새 기능을 더 안전하게 테스트할 수 있습니다.
- 첫 TTS 요청 지연이 줄었습니다.
- 엔진을 미리 준비해두는 워밍업 과정을 추가했습니다.