youtube-uploader
YouTube/Shorts 영상 업로드 자동화 — Manim 제작 영상을 Google OAuth로 YouTube에 업로드, 숏츠 조건 자동 검증
YouTube / Shorts 업로드
Google OAuth 기반으로 YouTube에 영상을 업로드합니다. 숏츠와 일반 영상 모두 지원.
⚠️ Playwright 방식 (youtube_upload_pw.py)은 백업으로 유지. 기본 업로더는upload.py사용.
전제 조건
| 항목 | 설명 |
|------|------|
| Python 3 | google-api-python-client, google-auth-httplib2, google-auth-oauthlib |
| YouTube 계정 | 업로드 대상 채널 |
| OAuth 토큰 | ~/.hermes/secrets/youtube_token.pickle (최초 auth.py로 생성) |
Google Cloud Console 설정 (최초 1회)
1. 프로젝트 생성 및 API 활성화
- https://console.cloud.google.com/ → 새 프로젝트 생성
- API 및 서비스 → 라이브러리 →
YouTube Data API v3→ 사용 설정
2. OAuth 클라이언트 ID 생성
- API 및 서비스 → 사용자 인증 정보
- 사용자 인증 정보 만들기 → OAuth 클라이언트 ID
- 앱 유형: 데스크톱 앱
- 이름:
hermes - 승인된 리디렉션 URI:
http://localhost(필수) - JSON 다운로드 →
~/.hermes/secrets/에 저장
3. OAuth 동의 화면 설정
- OAuth 동의 화면 → 앱 정보 입력:
에르메스봇- 사용자 지원 이메일:
sigco3111k@gmail.com- 개발자 연락처:
sigco3111k@gmail.com- 범위 추가:
https://www.googleapis.com/auth/youtube.upload - 테스트 사용자:
sigco3111k@gmail.com추가 - 앱 브랜딩:
https://sigco3111.github.io/hermes-landing/- 개인정보처리방침:
https://sigco3111.github.io/hermes-landing/privacy.html- Google Search Console에서 홈페이지 소유권 확인 필수
- 게시 상태: 테스트 (개인 용도)
4. 인증 실행
cd ~/.hermes/scripts/youtube_upload && python3 auth.py
브라우저가 열리면 Google 로그인 → 경고 무시 → 권한 승인. 성공 시 youtube_token.pickle 생성.
⚠️ Google Cloud Console 설정 함정
| 문제 | 해결 |
|------|------|
| "테스트 중이며 개발자가 승인한 테스터만 액세스 가능" | 테스트 사용자에 이메일 추가 확인. 경고 화면에서 "고급" → "이동" 클릭 |
| "승인 오류: invalid_scope" | YouTube Data API v3 활성화 확인 |
| "홈페이지 소유자 확인 필요" | Search Console에서 URL 접두어로 속성 추가 → HTML 태그로 확인 |
| "앱 이름이 일치하지 않음" | OAuth 동의 화면 앱 이름과 홈페이지 일치시키기 |
| "범위 근거/데모 동영상 누락" | 민감한 범위로 인증 제출 시 필요. 개인 용도는 테스트 모드 사용 |
| "개인적 용도라 인증 제출 불가" | 테스트 모드로 유지할 것. 프로덕션 전환 시 이 에러 발생함 |
| "테스트 모드에서도 access_denied" | 프로젝트가 올바른지 확인. 다른 프로젝트로 전환되었을 수 있음. Console 상단 프로젝트 선택 확인 |
| "redirect_uri mismatch" | OAuth 클라이언트 설정에 http://localhost 및 http://localhost:8080 모두 추가 |
🔑 핵심 교훈
- 개인 용도 = 무조건 테스트 모드: 프로덕션으로 전환하면 "개인적 용도"라서 검토 거부됨. 테스트 모드에서 테스터 등록 후 사용하는 것이 유일한 방법
- 브랜딩/홈페이지 설정은 프로덕션 전환 시에만 필요: 테스트 모드에서는 앱 이름/이메일만 설정하면 됨
- 토큰 위치:
/tmp/youtube_upload/token.json(재부팅 시 소실 가능 → ~/.hermes/secrets/로 이동 권장)
사용법
최초 1회: 로그인 + 쿠키 저장
python3 ~/.hermes/scripts/youtube_upload_pw.py --login
브라우저가 열리면 Google 계정으로 YouTube Studio에 로그인. 완료되면 쿠키가 자동 저장됩니다.
일반 업로드
python3 ~/.hermes/scripts/youtube_upload_pw.py "/path/to/video.mp4" \
--title "영상 제목" \
--description "영상 설명" \
--tags "태그1 태그2" \
--privacy public
숏츠 업로드 (자동 검증)
python3 ~/.hermes/scripts/youtube_upload_pw.py "/path/to/shorts.mp4" \
--title "숏츠 제목" \
--privacy public \
--shorts
프로그래매틱 호출
from youtube_upload_pw import upload_videourl = upload_video(
file_path="video.mp4",
title="제목",
description="설명",
tags=["태그1", "태그2"],
privacy="public",
is_shorts=True,
headless=True,
)
숏츠 조건 자동 검증
업로드 전 아래 조건을 자동 확인:
| 조건 | 검증 방법 | 값 |
|------|----------|-----|
| 비율 (9:16) | ffprobe width/height | 1080x1920 |
| 길이 (≤60s) | ffprobe duration | ≤60초 |
| 해상도 | ffprobe width | ≥720p 권장 |
# 자동 검증
ffprobe -v error -show_entries stream=width,height,duration -of json video.mp4 | python3 -c "
import json, sys
d = json.load(sys.stdin)['streams'][0]
w, h, dur = d['width'], d['height'], float(d.get('duration', 0))
issues = []
if w/h != 9/16: issues.append(f'비율 오류: {w}x{h} (9:16 필요)')
if dur > 60: issues.append(f'길이 초과: {dur:.1f}s (60s 이하 필요)')
if issues:
for i in issues: print(f'❌ {i}')
sys.exit(1)
else:
print(f'✅ 숏츠 조건 충족: {w}x{h}, {dur:.1f}s')
"
Manim 세로 영상 렌더링
manim -qm --disable_caching --resolution 1080,1920 script.py Scene1 Scene2 ...
옵션
| 옵션 | 기본값 | 설명 |
|------|--------|------|
| --title, -t | 파일명 | 영상 제목 |
| --description, -d | "" | 영상 설명 |
| --tags | [] | 태그 (공백 구분) |
| --category | 28 | 카테고리 (28=Science & Tech) |
| --privacy, -p | public | public, unlisted, private |
| --shorts | false | 숏츠 모드 (비율/길이 자동 검증) |
| --login | — | 로그인 + 쿠키 저장 (최초 1회) |
| --headless | true | 헤드리스 모드 |
| --no-headless | — | 브라우저 표시 (디버그용) |
GitHub Trending 중복 방지 연동 (04-22): Notion DB(33f76f2e90978176a537d40ebb476ef9)에서 이미 업로드한 repo 확인 후 중복 제외. 속성: Uploaded(checkbox), UploadDate(date), VideoTitle(rich_text). youtube_shorts_factory.py의 collect_github_trending()에 통합됨.
YouTube 쿠키는 보통 몇 주~몇 달 유지됩니다. 만료 시 --login 다시 실행.
🔧 기존 OAuth 방식 (백업)
upload.py는 Google Cloud Console + OAuth 기반입니다. Playwright 방식으로 전환 권장하지만, 백업으로 유지합니다.
⚠️ 토큰 만료 시 인증 방법
Playwright 방식(--login)은 Google 자동화 감지로 로그인 불가. 사용하지 말 것.
OAuth 토큰 만료 시 수동 인증 스크립트 사용:
python3 /tmp/youtube_auth_manual.py
- URL이 출력됨 → 브라우저에 복붙
- Google 로그인 + 권한 승인
http://localhost/?code=...페이지로 리다이렉트됨 → 주소창의code=값 복사- 터미널에 붙여넣고 Enter
인증 완료 후 기존 upload.py로 정상 업로드 가능.
제한사항
- 삭제 불가: 현재 scope이
youtube.upload만 포함. 삭제는 YouTube 스튜디오에서 수동 - 동시 업로드: 제한 없음
- 일일 업로드 제한: Google 기본 쿼터 10,000 units/일 (업로드 1회 = 1,600 units → 하약 6개)
- 토큰 만료: refresh token으로 자동 갱신됨. pickle 파일 삭제 시 재인증 필요
Related Skills / 관련 스킬
architecture-diagram
Generate dark-themed SVG diagrams of software systems and cloud infrastructure as standalone HTML files with inline SVG graphics. Semantic component colors (cyan=frontend, emerald=backend, violet=database, amber=cloud/AWS, rose=security, orange=message bus), JetBrains Mono font, grid background. Best suited for software architecture, cloud/VPC topology, microservice maps, service-mesh diagrams, database + API layer diagrams, security groups, message buses — anything that fits a tech-infra deck with a dark aesthetic. If a more specialized diagramming skill exists for the subject (scientific, educational, hand-drawn, animated, etc.), prefer that — otherwise this skill can also serve as a general-purpose SVG diagram fallback. Based on Cocoon AI's architecture-diagram-generator (MIT).