diff --git a/TitleDescriptionUpdater.py b/TitleDescriptionUpdater.py index 7c9cbf5..4594884 100644 --- a/TitleDescriptionUpdater.py +++ b/TitleDescriptionUpdater.py @@ -1,11 +1,19 @@ # Script to automatically update a YouTube video with the translated title, description, and subtitles for each language import auth from googleapiclient.errors import HttpError +from googleapiclient.http import MediaFileUpload import copy import json +import os +import sys +import langcodes videoID = "abcdefghijkl" translatedJsonFile = r"output\Translated Items.json" +subtitlesFolder = r"output" + +updateTitleAndDescription = True +uploadSubtitles = True # Override language codes, like for localization. Put the original on the left, and the new on the right overRiddenLangCodes = { @@ -20,6 +28,80 @@ YOUTUBE_API = auth.youtube_authentication() +# --------------------------------------------------------------------------------------- + +################################ Subtitles ################################ +if uploadSubtitles: + # Process subtitles to upload + subtitleFilesDict = {} + + # Get list of subtitle files in the directory + for file in os.listdir(subtitlesFolder): + if file.endswith(".srt"): + nameNoExt = os.path.splitext(file)[0] + # Get the language code from the end of the filename. Assumes the code will be separated by ' - ' + if ' - ' in nameNoExt: + parsedLanguageCode = nameNoExt.split(' - ')[-1].strip() + else: + # Print error and ask whether to continue + print(f"\nWARNING: Could not find language code in filename: {file}") + print("\nTo read the language code, separate the language code from the rest of the filename with: ") + print(" ' - ' (a dash surrounded by spaces)") + print("For example: 'Whatever Video - en-us.wav'") + print("Enter 'y' to skip that track and conitnue, or enter anything else to exit.") + + userInput = input("Continue Anyway? (y/n): ") + if userInput.lower() != 'y': + sys.exit() + + # Check if the language code is valid, if so save to dictionary for next steps + try: + langObject = langcodes.get(parsedLanguageCode) + threeLetterCode = langObject.to_alpha3() + languageDisplayName = langcodes.get(threeLetterCode).display_name() + # Add to dictionary + subtitleFilesDict[parsedLanguageCode] = file + + except: + print(f"\nWARNING: Language code '{parsedLanguageCode}' is not valid for file: {file}") + print("Enter 'y' to skip that track and conitnue, or enter anything else to exit.") + userInput = input("\nContinue Anyway and Skip File? (y/n): ") + if userInput.lower() != 'y': + sys.exit() + + +def list_captions(videoID): + results = auth.YOUTUBE_API.captions().list( + part="snippet", + videoId=videoID + ).execute() + return results + +#captionsList = list_captions(videoID) + + +def upload_caption(videoID, language, name, file): + # Convert file to bytes + subtitleData = MediaFileUpload(file, mimetype="text/plain", resumable=True) + + insert_result = auth.YOUTUBE_API.captions().insert( + part="snippet", + body=dict( + snippet=dict( + videoId=videoID, + language=language, + name=name, + isDraft=False + ) + ), + media_body=subtitleData + ).execute() + pass + +# --------------------------------------------------------------------------------------- + +################################ Title and Description ################################ + def get_video_info(videoID): response = YOUTUBE_API.videos().list( part = "snippet,localizations", @@ -61,14 +143,27 @@ def update_title_and_description(videoID, translatedJson): "description": description } - # Send request to update localization - localization_result = YOUTUBE_API.videos().update( - part = "localizations", - body = { - "id": videoID, - "localizations": newLocals - }, - ).execute() + try: + # Send request to update localization + localization_result = YOUTUBE_API.videos().update( + part = "localizations", + body = { + "id": videoID, + "localizations": newLocals + }, + ).execute() + + except HttpError as hx: + print(f"An HTTP error {hx.resp.status} occurred:\n{hx.content}") + errorMessage = str(hx.error_details[0]['message']) + errorReason = str(hx.error_details[0]['reason']) + if errorReason == "insufficientPermissions": + print(f"Error: {errorMessage}.\nThis script requires a different set of permissions for use with YouTube.") + print("Create a separate project in the Google Cloud Platform, and follow these steps:") + print(" - Enable the YouTube Data API, grant the scopes: https://www.googleapis.com/auth/youtube.force-ssl") + print(" - Save the credentials file, but for this one call it 'yt_client_secrets.json'") + +# --------------------------------------------------------------------------------------- def get_video_title(videoID): try: @@ -87,7 +182,9 @@ def get_video_title(videoID): else: print("Something went wrong. No video found.") return None + +# --------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------- # Get video title to confirm @@ -102,14 +199,22 @@ def get_video_title(videoID): elif choice.lower() == "y": pass -try: +# --------------------------------------------------------------------------------------- + +if updateTitleAndDescription: + # Update titles and descriptions + print("\nUpdating titles and descriptions...") update_title_and_description(videoID, translatedJson) -except HttpError as hx: - print(f"An HTTP error {hx.resp.status} occurred:\n{hx.content}") - errorMessage = str(hx.error_details[0]['message']) - errorReason = str(hx.error_details[0]['reason']) - if errorReason == "insufficientPermissions": - print(f"Error: {errorMessage}.\nThis script requires a different set of permissions for use with YouTube.") - print("Create a separate project in the Google Cloud Platform, and follow these steps:") - print(" - Enable the YouTube Data API, grant the scopes: https://www.googleapis.com/auth/youtube.force-ssl") - print(" - Save the credentials file, but for this one call it 'yt_client_secrets.json'") + +if uploadSubtitles: + # Upload captions + for langCode, fileName in subtitleFilesDict.items(): + # Get language display name + languageDisplayName = langcodes.get(langCode).display_name() + # Get file path + filePath = os.path.join(subtitlesFolder, fileName) + # Upload the caption + print("\nUploading caption for language: " + languageDisplayName + " (" + langCode + ")") + upload_caption(videoID, langCode, "", filePath) # Use empty string as the name, so it will apply as the default caption for that language + +print("\nDone!")