버전: v2.4 | 최종 갱신: 2026-03-18
대상: 박씨 (ADMIN) 전용
텔레그램 메시지/파일
↓
@parksy_bridges_bot (bot.py)
↓
┌──────────────────────────────────────────┐
│ Track A: 파일 드랍 │
│ 오디오/MIDI → _run_runner() │
│ │
│ Track B: YouTube URL (텍스트 감지) │
│ URL 포함 텍스트 → _run_runner() │
│ │
│ 텍스트 (일반) → _run_claude() │
└──────────────────────────────────────────┘
↓
runner.py 파이프라인 (L0~L7)
↓
품질 채점 (score_engine) → 90점 미만이면 경고
↓
M4A 출력 → 텔레그램 전송 → /approve → YouTube 업로드
| 항목 | 경로 | |
| **bot.py** | `/mnt/d/PARKSY/parksy-audio/local-agent/bot.py` | |
|---|---|---|
| **runner.py** | `/mnt/d/tmp/runner.py` | |
| **M4A 출력** | `/mnt/d/PARKSY/parksy-audio/local-agent/outputs/` | |
| **작업 디렉토리** | `/mnt/d/PARKSY/parksy-audio/local-agent/outputs/work/` | |
| **봇 로그** | `/mnt/d/PARKSY/parksy-audio/local-agent/bot.log` | |
| **최적 설정** | `/mnt/d/PARKSY/parksy-audio/local-agent/optimal_config.json` | |
| **텔레그램 설정** | `/mnt/d/PARKSY/parksy-audio/local-agent/telegram_config.json` | |
| **upload.cjs** | `/home/dtsli/dtslib-papyrus/tools/youtube/upload.cjs` | |
| **YouTube 토큰** | `/home/dtsli/dtslib-papyrus/tools/youtube/accounts/` | |
| **upload spec 디렉토리** | `/home/dtsli/dtslib-papyrus/tools/youtube/uploads/` |
tmux list-sessions
| 세션 | 역할 | |
| `tg-audio` | @parksy_bridges_bot | |
|---|---|---|
| `tg-image` | @parksy_bridge_bot (이미지 봇) | |
| `claude-main` | Claude Code 메인 | |
| `watchdog` | 감시 프로세스 |
tmux send-keys -t tg-audio "C-c" Enter
sleep 2
tmux send-keys -t tg-audio "python3 /mnt/d/PARKSY/parksy-audio/local-agent/bot.py" Enter
tail -f /mnt/d/PARKSY/parksy-audio/local-agent/bot.log
tmux capture-pane -t tg-audio -p | tail -20
ADMIN — 전체 명령어 + 파일 드랍 + YouTube URL
SLOT (3명) — 파일 드랍만
기타 — 접근 불가
설정 파일: /mnt/d/PARKSY/parksy-audio/local-agent/telegram_config.json
/addslot 123456789 홍길동
/rmslot 123456789
/slots
상대방 ID 확인: @userinfobot에 /start 전송
| 명령어 | 함수 | 설명 | ||
| `/start` | `cmd_start()` | 봇 소개 + 명령어 목록 | ||
|---|---|---|---|---|
| `/status` | `cmd_status()` | 작업 중 여부, pending 파일, 슬롯 상태 | ||
| `/approve` | `cmd_approve()` | 마지막 결과물 YouTube 업로드 | ||
| `/upload` | `cmd_upload()` | `/approve`와 동일 | ||
| `/stop` | `cmd_stop()` | 진행 중 작업 중단 | ||
| `/new` | `cmd_new()` | Claude 세션 초기화 | ||
| `/render [설명]` | `cmd_render()` | Claude에게 렌더링 지시 | ||
| `/queue` | `cmd_queue()` | 큐 상태 확인 (Claude) | ||
| `/score [설명]` | `cmd_score()` | 악보 처리 상태 (Claude) | ||
| `/slots` | `cmd_slots()` | 슬롯 목록 | ||
| `/addslot ID 이름` | `cmd_addslot()` | 슬롯 추가 | ||
| `/rmslot ID` | `cmd_rmslot()` | 슬롯 제거 |
handle_audio() / handle_document() → _run_runner()
지원 확장자: .wav .mp3 .m4a .flac .ogg .mid .midi
handle_text() → _extract_yt_url() → _run_runner()
# handle_text() YouTube 감지 로직
yt_url = _extract_yt_url(text) # URL 추출
caption = text.replace(yt_url, '') # URL 제외 나머지 = 캡션
await _run_runner(bot, chat_id, yt_url, caption)
감지되는 URL 패턴:
소스 전략: 보컬 없는 연주 영상만 타겟. 클린 인스트루멘탈 → basic_pitch 전사 품질 극대화.
URL이 없는 일반 텍스트 → _run_claude()
# _run_runner() 핵심 로직
args = [sys.executable, RUNNER_PY, file_path, '--no-opt']
# 캡션 키워드 파싱
# 감정: triumph / elegy / nocturne / epic / pastoral
# 스타일: bruckner / mahler / faure
[L0] yt_fetch — YouTube URL 다운로드 + 클립
[L1] separator — Demucs v4 소스 분리 (--separate 플래그 시)
[L2] transcriber — 악기별 전사 (piano/vocal/auto)
[L3] arranger — 감정 프리셋 + Markov 편곡
[L4] composer — Bruckner/Mahler/Fauré 스타일
[L5] humanizer — 미세 타이밍·루바토·페달
[L6] optimizer — FluidSynth 렌더 + EQ/Comp
[L6b] mastering — matchering AI 마스터링 or pedalboard
[L7] score_engine — 품질 채점 (90점 미만이면 경고)
→ M4A 출력: local-agent/outputs/{name}_final.m4a
봇에서는 --no-opt 플래그로 실행 (L7 최적화 루프 생략, 빠른 렌더).
단, --no-opt에서도 결과물 채점 후 90점 미만이면 경고 봇 로그에 기록됨.
90점 미만 결과물은 YouTube에 올리지 말 것.
# MIDI 직접
python3 /mnt/d/tmp/runner.py beethoven.mid --emotion triumph --style bruckner
# 오디오 (자동 전사)
python3 /mnt/d/tmp/runner.py nocturne.wav --emotion nocturne --style faure
# YouTube URL
python3 /mnt/d/tmp/runner.py "https://youtube.com/watch?v=..." --start 1:00 --end 2:00
# 최적화 루프 포함 (고품질)
python3 /mnt/d/tmp/runner.py audio.wav --iterations 10 --target 90
# 제안 모드
python3 /mnt/d/tmp/runner.py audio.wav --suggest
| 점수 | 판정 | |
| **90점 이상** | 출시 가능 | |
|---|---|---|
| **90점 미만** | 경고. `--iterations 10 --target 90`으로 재렌더 |
봇 로그에 채점 결과가 자동으로 기록됨. /approve 전에 로그 확인 권장.
/approve
↓
_do_upload()
↓
M4A → ffmpeg → _yt.mp4 (검정 배경 1280×720, CRF28, AAC 192k)
↓
spec JSON 생성 → PAPYRUS_UPLOAD_DIR/
↓
node upload.cjs a {spec_name}
↓
YouTube 비공개 업로드 → URL 텔레그램 전송
| 키 | 계정 | 채널 | ||
| `a` | dimas.thomas.sancho@gmail.com | parksy 계열 | ||
|---|---|---|---|---|
| `b` | dtslib1979@gmail.com | branch hub | ||
| `c` | Thomas.tj.Park@gmail.com | EAE | ||
| `d` | dimas@dtslib.com | HQ |
봇은 항상 계정 a 사용.
/home/dtsli/dtslib-papyrus/tools/youtube/accounts/
├── token_a.json
├── token_b.json
├── token_c.json
└── token_d.json
cat /home/dtsli/dtslib-papyrus/tools/youtube/accounts/token_a.json \
| python3 -c "import json,sys; t=json.load(sys.stdin); \
print('scope:', t.get('scope','')); \
print('refresh_token:', 'O' if t.get('refresh_token') else 'X')"
cd /home/dtsli/dtslib-papyrus/tools/youtube
node yt_oauth_auto.cjs # 계정 a
node yt_oauth_b.cjs # 계정 b
node yt_oauth_c.cjs # 계정 c
node yt_oauth_d.cjs # 계정 d
cd /home/dtsli/dtslib-papyrus/tools/youtube
node upload.cjs a # 대화형 모드
node upload.cjs a spec.json # spec 파일 지정
tail -50 /mnt/d/PARKSY/parksy-audio/local-agent/bot.log
ls -lth /mnt/d/PARKSY/parksy-audio/local-agent/outputs/*.m4a 2>/dev/null
python3 /mnt/d/tmp/runner.py /tmp/test.wav --no-opt
python3 /mnt/d/tmp/runner.py input.wav --iterations 10 --target 90
cd /home/dtsli/dtslib-papyrus/tools/youtube
node upload.cjs a
node yt_oauth_auto.cjs # 토큰 만료 시
tmux capture-pane -t tg-audio -p | tail -10
tmux send-keys -t tg-audio "C-c" Enter
sleep 2
tmux send-keys -t tg-audio "python3 /mnt/d/PARKSY/parksy-audio/local-agent/bot.py" Enter
텔레그램에서 /status 확인 후 새 파일 다시 보내면 자동으로 덮어씌워진다.
{
"soundfont": "D:\\VST\\SGM-V2.01.sf2",
"fs_gain": 0.7,
"low_shelf_gain": -3,
"mid_cut_gain": -2,
"presence_gain": 4.5,
"bright_gain": 3.5,
"air_shelf_gain": 4.0,
"comp_threshold": -15,
"comp_ratio": 1.5,
"vel_scurve_k": 3.0,
"ambient_file": "D:\\VST\\ambient\\rain_nat.mp3",
"ambient_volume": -20
}
수동 수정 후 봇 재시작 없이 바로 반영된다 (파이프라인 실행 시마다 로드).
| 레포 | 경로 | 역할 | ||
| parksy-audio | `/mnt/d/PARKSY/parksy-audio` | 이 레포 (봇 + 파이프라인) | ||
|---|---|---|---|---|
| dtslib-papyrus | `/home/dtsli/dtslib-papyrus` | YouTube upload.cjs + 토큰 | ||
| dtslib-localpc | `/mnt/d/PARKSY/dtslib-localpc` | 관제탑 (상태 파일) | ||
| tmp | `/mnt/d/tmp` | runner.py + score_engine + optimizer 등 |
작성: 2026-03-18 | @parksy_bridges_bot v2.4 | ADMIN ONLY