Files
video-pipeline/modules/yt_poster.py

116 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""
yt_poster.py
This module handles the upload of videos to YouTube using the YouTube Data API v3.
It supports setting metadata such as title, description, tags, category, and privacy settings.
It also ensures that the game title "Fortnite" is included in the metadata to trigger proper categorization.
Author: gramps@llamachile.shop
"""
import os
import google.auth
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
from modules.config import OPENAI_API_KEY, DEBUG
from modules.archive import save_metadata_record
# Category ID for "Gaming" on YouTube (required for accurate categorization)
CATEGORY_ID = "20"
# Default tags to include if none are provided
DEFAULT_TAGS = [
"Fortnite", "Zero Build", "Gramps", "CoolHandGramps",
"funny", "gaming", "highlights"
]
# Default visibility setting
DEFAULT_PRIVACY = "public"
def ensure_fortnite_tag(metadata):
"""
Ensures that the word 'Fortnite' appears in at least one of the following:
- Title
- Description
- Tags list
This helps YouTube automatically detect the game and associate the video
with Fortnite gameplay.
"""
if "fortnite" not in metadata["title"].lower() and \
"fortnite" not in metadata["description"].lower() and \
not any("fortnite" in tag.lower() for tag in metadata.get("tags", [])):
metadata.setdefault("tags", []).append("Fortnite")
def upload_video(youtube, video_path, metadata):
"""
Uploads a video to YouTube with the provided metadata.
Args:
youtube: Authenticated YouTube API service object.
video_path: Path to the video file to be uploaded.
metadata: Dictionary containing video metadata fields.
Returns:
str: URL of the uploaded YouTube video.
"""
# Ensure the 'Fortnite' keyword is present somewhere in metadata
ensure_fortnite_tag(metadata)
# Construct the request body for YouTube API
request_body = {
"snippet": {
"title": metadata["title"],
"description": metadata["description"],
"tags": metadata.get("tags", DEFAULT_TAGS),
"categoryId": CATEGORY_ID # Set to "Gaming"
},
"status": {
"privacyStatus": metadata.get("privacy", DEFAULT_PRIVACY)
}
}
# Wrap the video file in a MediaFileUpload object
media = MediaFileUpload(video_path, mimetype="video/*", resumable=True)
print(f"📤 Uploading {video_path} to YouTube...")
# Execute the video insert request
request = youtube.videos().insert(
part="snippet,status",
body=request_body,
media_body=media
)
response = request.execute()
video_id = response["id"]
youtube_url = f"https://www.youtube.com/watch?v={video_id}"
print(f"✅ Uploaded to YouTube: {youtube_url}")
# Record the YouTube URL in the metadata for archive history
metadata.setdefault("youtube_url", []).append(youtube_url)
# Persist the metadata archive only if we're not in DEBUG mode
if not DEBUG:
save_metadata_record(video_path, metadata)
return youtube_url
def get_authenticated_service():
"""
Returns an authenticated YouTube API service using Application Default Credentials.
This requires that `gcloud auth application-default login` has been run successfully,
or that a service account token is available in the environment.
Returns:
googleapiclient.discovery.Resource: The YouTube API client object.
"""
credentials, _ = google.auth.default(
scopes=["https://www.googleapis.com/auth/youtube.upload"]
)
return build("youtube", "v3", credentials=credentials)