From 04e30d2d5ff749763be8945e22fbc1386d609a1c Mon Sep 17 00:00:00 2001 From: kennydd0 <76538784+kennydd0@users.noreply.github.com> Date: Tue, 1 Jul 2025 12:02:00 +0200 Subject: [PATCH] Add YouTube upload helper --- requirements.txt | 4 ++++ utils/tiktok_upload.py | 19 +++++++++++++++ utils/youtube_upload.py | 53 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 utils/tiktok_upload.py create mode 100644 utils/youtube_upload.py diff --git a/requirements.txt b/requirements.txt index e6e2e7b..1cbb90e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,3 +22,7 @@ ffmpeg-python==0.2.0 elevenlabs==1.3.0 yt-dlp==2024.5.27 numpy==1.26.4 +tiktok-uploader==1.1.1 +google-api-python-client==2.171.0 +google-auth-oauthlib==1.2.2 +google-auth-httplib2==0.2.0 diff --git a/utils/tiktok_upload.py b/utils/tiktok_upload.py new file mode 100644 index 0000000..ee9727e --- /dev/null +++ b/utils/tiktok_upload.py @@ -0,0 +1,19 @@ +from tiktok_uploader.upload import upload_video +from utils import settings + + +def upload_to_tiktok(filepath: str, description: str = "") -> None: + """Upload a video to TikTok using the configured sessionid. + + Parameters + ---------- + filepath : str + Path to the video file that should be uploaded. + description : str, optional + Description for the TikTok post, by default "" + """ + sessionid = settings.config["settings"]["tts"].get("tiktok_sessionid") + if not sessionid: + raise ValueError("TikTok sessionid is missing from the configuration.") + + upload_video(filename=filepath, description=description, sessionid=sessionid) diff --git a/utils/youtube_upload.py b/utils/youtube_upload.py new file mode 100644 index 0000000..8653722 --- /dev/null +++ b/utils/youtube_upload.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +import os +from typing import List, Optional + +from google.oauth2.credentials import Credentials +from googleapiclient.discovery import build +from googleapiclient.http import MediaFileUpload +from google_auth_oauthlib.flow import InstalledAppFlow +from google.auth.transport.requests import Request + + +SCOPES = ["https://www.googleapis.com/auth/youtube.upload"] +CLIENT_SECRETS_FILE = "youtube_client_secrets.json" +TOKEN_FILE = "youtube_token.json" + + +def _get_service(): + """Return an authenticated YouTube service object.""" + creds: Optional[Credentials] = None + if os.path.exists(TOKEN_FILE): + creds = Credentials.from_authorized_user_file(TOKEN_FILE, SCOPES) + if not creds or not creds.valid: + if creds and creds.expired and creds.refresh_token: + creds.refresh(Request()) + else: + flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES) + creds = flow.run_console() + with open(TOKEN_FILE, "w") as token: + token.write(creds.to_json()) + return build("youtube", "v3", credentials=creds) + + +def upload_to_youtube( + filepath: str, + title: str, + description: str = "", + *, + privacy_status: str = "private", + tags: Optional[List[str]] = None, +) -> dict: + """Upload a video to YouTube with the given metadata.""" + youtube = _get_service() + body = { + "snippet": {"title": title, "description": description, "tags": tags or []}, + "status": {"privacyStatus": privacy_status}, + } + media = MediaFileUpload(filepath) + request = youtube.videos().insert( + part="snippet,status", body=body, media_body=media + ) + return request.execute() +