← back to AgentAbrams
video/upload_youtube.py
90 lines
#!/usr/bin/env python3
"""
upload_youtube.py — Upload video to YouTube via OAuth refresh token.
Reads credentials from environment variables (safe for CI/CD).
Usage:
python3 video/upload_youtube.py <video_file> <title> <description>
Environment variables:
YOUTUBE_CLIENT_ID
YOUTUBE_CLIENT_SECRET
YOUTUBE_REFRESH_TOKEN
"""
import os
import sys
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
SCOPES = ["https://www.googleapis.com/auth/youtube.upload"]
def get_youtube_service():
required = ["YOUTUBE_REFRESH_TOKEN", "YOUTUBE_CLIENT_ID", "YOUTUBE_CLIENT_SECRET"]
missing = [k for k in required if not os.environ.get(k)]
if missing:
print(f"ERROR: missing environment variables: {', '.join(missing)}", file=sys.stderr)
sys.exit(1)
creds = Credentials(
token=None,
refresh_token=os.environ["YOUTUBE_REFRESH_TOKEN"],
token_uri="https://oauth2.googleapis.com/token",
client_id=os.environ["YOUTUBE_CLIENT_ID"],
client_secret=os.environ["YOUTUBE_CLIENT_SECRET"],
scopes=SCOPES,
)
return build("youtube", "v3", credentials=creds)
def upload_video(video_path, title, description, privacy="public"):
youtube = get_youtube_service()
body = {
"snippet": {
"title": title,
"description": description,
"tags": ["Claude Code", "AI agents", "AgentAbrams", "BuildInPublic"],
"categoryId": "28", # Science & Technology
},
"status": {
"privacyStatus": privacy,
"selfDeclaredMadeForKids": False,
},
}
media = MediaFileUpload(video_path, resumable=True, chunksize=1024 * 1024)
request = youtube.videos().insert(part="snippet,status", body=body, media_body=media)
response = None
while response is None:
status, response = request.next_chunk()
if status:
pct = int(status.progress() * 100)
print(f"Uploading... {pct}%")
video_id = response["id"]
print(f"Upload complete. Video ID: {video_id}")
print(f"URL: https://www.youtube.com/watch?v={video_id}")
return video_id
def main():
if len(sys.argv) < 4:
print("Usage: upload_youtube.py <video_file> <title> <description>", file=sys.stderr)
sys.exit(2)
if not os.path.isfile(sys.argv[1]):
print(f"Video file not found: {sys.argv[1]}", file=sys.stderr)
sys.exit(2)
upload_video(sys.argv[1], sys.argv[2], sys.argv[3])
if __name__ == "__main__":
main()