moved youtube scirpts into there own folder

This commit is contained in:
SumGuyV5 committed 2026-09-13 16:01:40 +00:00
1 parent 8bf85fea2e
commit afe6490d20
15 files changed
+127 -102

No files matched your search

+4 -4
View File
@@ -6,10 +6,10 @@ import time
from package.database import Database
import uploader
from uploader import CategoryId
import package.youtube.uploader as uploader
from package.youtube.uploader import CategoryId
import youtube_hashtags
import package.youtube.hashtags as hashtags
import package.transcribe_video as transcribe_video
CHANNEL_NAME = 'teampgp' # Replace with the streamer's username
@@ -43,7 +43,7 @@ def top_hashtags(id: str):
print(f"Transcribe file not found {file_srt}")
return []
tags = youtube_hashtags.get_top_hashtags(file_srt)
tags = hashtags.get_top_hashtags(file_srt)
return tags
def download():
+4 -4
View File
@@ -5,8 +5,8 @@ from datetime import datetime
from package.database import Database
import uploader
from uploader import CategoryId
import package.youtube.uploader as uploader
from package.youtube.uploader import CategoryId
CHANNEL_NAME = 'teampgp' # Replace with the streamer's username
DB = Database("clips")
@@ -49,9 +49,9 @@ def top_hashtags(slug: str):
print(f"Transcribe file not found {file_srt}")
return []
import youtube_hashtags
import package.youtube.hashtags as hashtags
return youtube_hashtags.get_top_hashtags(file_srt)
return hashtags.get_top_hashtags(file_srt)
def download_clips():
+1 -1
View File
@@ -14,7 +14,7 @@ os.makedirs(CACHE_DIR, exist_ok=True)
# 3. Expose Database Tools (Added)
# Replace 'DatabaseClient' and 'connect_to_db' with your actual class/function names
from .build_videos import main as build_videos
from .build_videos import build_videos
from .config import CHANNEL_NAME, DB
from .database import Database
from .transcribe_video import transcribe_to_srt
+4 -4
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
import youtube_short
import package.youtube.shorts as yt_shorts
import package.transcribe_video as transcribe_video
import package.twitch.chat_vod as chat_vod
from package.config import DB as DB
@@ -108,16 +108,16 @@ def build_shorts():
print(f"🚀 Processing: Clip to Youtube Short {title}")
print("====================================================")
youtube_short.fit_to_9_16_letterbox(target_dir, top_txt, f"Clipped By: {creator_name}.")
yt_shorts.fit_to_9_16_letterbox(target_dir, top_txt, f"Clipped By: {creator_name}.")
print("====================================================")
print(f"✅ Processing: Clip to Youtube Short Done.")
print("====================================================")
def main():
def build_videos():
build_shorts()
build_transcribe()
build_chat_video()
if __name__ == "__main__":
main()
build_videos()
+3 -3
View File
@@ -2,9 +2,9 @@
# Expose components from individual modules using relative imports
from .chat_vod import combine_twitch_vod_and_chat
from .download_thumbnails import main as download_thumbnails
from .download_videos import main as download_videos
from .video_info import main as video_info
from .download_thumbnails import download_thumbnails
from .download_videos import download_videos
from .video_info import video_info
# Explicitly define what is exposed when importing the subpackage
__all__ = [
+3
View File
@@ -4,6 +4,9 @@ import cv2
import package.utils as utils
def get_video_height(video_path: str) -> int:
"""
Gets the videos height
"""
# Open the video file
video = cv2.VideoCapture(video_path)
+2 -2
View File
@@ -80,7 +80,7 @@ def save_image(url: str, filename: str, stream: bool = True):
except Exception as e:
print(f"❌ An error occurred during file writing: {e}")
async def main():
async def download_thumbnails():
# Initialize connection & automatically authorize the App token
await config.get_twitch()
twitch = config.TWITCH # Twitch(APP_ID, APP_SECRET)
@@ -141,4 +141,4 @@ async def main():
await download_clip_thumbnail(id, thumbnail_url)
if __name__ == '__main__':
asyncio.run(main())
asyncio.run(download_thumbnails())
+2 -5
View File
@@ -14,7 +14,7 @@ def write_csv(data, file_name):
# Write all rows at once
writer.writerows(data)
def download():
def download_videos():
"""Find all undownloaded videos and clips, and download them safely."""
undownloaded = DB.get_undownloaded()
@@ -96,8 +96,5 @@ def download():
print("Finished Downloading Pipeline.")
def main():
download()
if __name__ == "__main__":
main()
download_videos()
+5 -5
View File
@@ -40,7 +40,7 @@ async def get_game_name_by_id(game_id: str) -> str:
pass
return "Unknown Game"
async def get_vod_game_name(vod_id: str):
async def get_vod_game_name(vod_id: str) -> tuple:
"""Asynchronously query Twitch GQL endpoint for VOD game metadata."""
game_id = "0"
game_name = "Unknown Game"
@@ -83,7 +83,7 @@ async def get_vod_game_name(vod_id: str):
return game_id, game_name
async def get_streamer_vods():
async def get_streamer_vods() -> list:
await config.get_twitch()
print(f"Starting VOD extraction for {config.USER.display_name}...")
@@ -121,7 +121,7 @@ async def get_streamer_vods():
print(f"\nFinished extracting VODs. Total gathered: {len(all_vods)}")
return all_vods
async def get_streamer_clips():
async def get_streamer_clips() -> list:
await config.get_twitch()
print(f"Starting clip extraction for {config.USER.display_name}...")
@@ -151,7 +151,7 @@ async def get_streamer_clips():
print(f"\nFinished extracting clips. Total gathered: {len(all_clips)}")
return all_clips
async def main():
async def video_info():
print("--- Script Started ---")
vods_list = await get_streamer_vods()
@@ -179,4 +179,4 @@ async def main():
print(f"Recent VOD: '{clips_list[0]['title']}'")
if __name__ == "__main__":
asyncio.run(main())
asyncio.run(video_info())
+15
View File
@@ -0,0 +1,15 @@
# package/youtube/__init__.py
# Expose components from individual modules using relative imports
from .find_tags import find_tags
from .hashtags import get_top_nouns
from .shorts import fit_to_9_16_letterbox
from .uploader import upload_video, CategoryId
# Explicitly define what is exposed when importing the subpackage
__all__ = [
"find_tags",
"get_top_nouns",
"fit_to_9_16_letterbox",
"upload_video",
]
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
import json
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
CREDENTIALS = None
def load_credentials() -> Credentials:
"""Load credentials from secrets.json"""
try:
with open('secrets.json', 'r') as f:
creds_data = json.load(f)
credentials = Credentials(
token=creds_data['token'],
refresh_token=creds_data['refresh_token'],
token_uri=creds_data['token_uri'],
client_id=creds_data['client_id'],
client_secret=creds_data['client_secret'],
scopes=creds_data['scopes']
)
# Refresh token if expired
if credentials.expired:
credentials.refresh(Request())
return credentials
except FileNotFoundError:
print("Error: secrets.json not found! Please run setup.py first.")
return None
except Exception as e:
print(f"Error loading credentials: {str(e)}")
return None
CREDENTIALS = load_credentials()
@@ -1,37 +1,12 @@
#!/usr/bin/env python3
import json
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
from typing import Any
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
def load_credentials():
"""Load credentials from secrets.json (Reused from your previous flow)"""
try:
with open('secrets.json', 'r') as f:
creds_data = json.load(f)
import package.youtube.config as config
credentials = Credentials(
token=creds_data['token'],
refresh_token=creds_data['refresh_token'],
token_uri=creds_data['token_uri'],
client_id=creds_data['client_id'],
client_secret=creds_data['client_secret'],
scopes=creds_data['scopes']
)
if credentials.expired:
credentials.refresh(Request())
return credentials
except FileNotFoundError:
print("Error: secrets.json not found!")
return None
except Exception as e:
print(f"Error loading credentials: {str(e)}")
return None
def get_my_uploads_playlist_id(youtube):
def get_my_uploads_playlist_id(youtube: build) -> Any:
"""Retrieves the system upload playlist ID for the authenticated user's channel."""
try:
# mine=True automatically references the authorized account
@@ -47,7 +22,7 @@ def get_my_uploads_playlist_id(youtube):
print(f"API Error retrieving channel details: {str(e)}")
return None
def scan_channel_videos_for_tag(youtube, uploads_playlist_id: str, target_tag: str):
def scan_channel_videos_for_tag(youtube: build, uploads_playlist_id: str, target_tag: str) -> list:
"""
Loops through all channel video uploads and filters those possessing the target tag.
"""
@@ -120,12 +95,12 @@ def scan_channel_videos_for_tag(youtube, uploads_playlist_id: str, target_tag: s
return matched_videos
def main():
credentials = load_credentials()
if not credentials:
def find_tags():
if not config.CREDENTIALS:
return
youtube = build('youtube', 'v3', credentials=credentials)
youtube = build('youtube', 'v3', credentials=config.CREDENTIALS)
# 1. Fetch your dynamic uploads playlist pointer
uploads_id = get_my_uploads_playlist_id(youtube)
@@ -144,4 +119,4 @@ def main():
print(f"{index}. {item['title']} -> https://youtu.be{item['id']}")
if __name__ == "__main__":
main()
find_tags()
@@ -14,7 +14,16 @@ nltk.download('punkt_tab', quiet=True)
nltk.download('averaged_perceptron_tagger', quiet=True) # Required for POS tagging
nltk.download('averaged_perceptron_tagger_eng', quiet=True)
def extract_text_from_srt(file_path: str):
def extract_text_from_srt(file_path: str) -> str:
"""
Extracts the text from the srt file.
Args:
file_path (str): is the path to the str file.
Returns:
returns (str): returns the cleaned up text.
"""
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
# Remove SRT timestamps and sequence numbers
@@ -22,7 +31,16 @@ def extract_text_from_srt(file_path: str):
clean_text = re.sub(r'\d+', '', clean_text)
return clean_text
def extract_text_from_json(file_path: str):
def extract_text_from_json(file_path: str) -> str:
"""
Extracts the text from the json file.
Args:
file_path (str): is the path to the json file.
Returns:
returns (str): returns the cleaned up text.
"""
with open(file_path, "r", encoding="utf-8") as file:
data = json.load(file)
@@ -34,7 +52,17 @@ def extract_text_from_json(file_path: str):
# Return a single merged string of all chat text
return " ".join(messages)
def get_top_nouns(file_path: str, top_n: int = 10):
def get_top_nouns(file_path: str, top_n: int = 10) -> list:
"""
Gets the top number of nouns based on past (top_n) arg.
Args:
file_path (str): is the path to the text file.
top_n (int): is the number of nouns to return.
Returns:
returns (list): returns a list of nouns.
"""
# 1. Extract raw text
if file_path.endswith(".srt"):
raw_text = extract_text_from_srt(file_path)
@@ -126,7 +126,6 @@ def fit_to_9_16_letterbox(input_path: str, top_text: str = "TOP TEXT", bottom_te
if os.path.exists(path):
os.unlink(path)
if __name__ == "__main__":
import time
+7 -35
View File
@@ -1,16 +1,15 @@
#!/usr/bin/env python3
import os
import json
import argparse
from enum import Enum
from datetime import datetime
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
from googleapiclient.errors import HttpError
import package.youtube.config as config
class CategoryId(Enum):
"""Official YouTube Category IDs for API Uploads."""
@@ -30,34 +29,7 @@ class CategoryId(Enum):
SCIENCE_AND_TECHNOLOGY = "28"
NONPROFITS_AND_ACTIVISM = "29"
def load_credentials():
"""Load credentials from secrets.json"""
try:
with open('secrets.json', 'r') as f:
creds_data = json.load(f)
credentials = Credentials(
token=creds_data['token'],
refresh_token=creds_data['refresh_token'],
token_uri=creds_data['token_uri'],
client_id=creds_data['client_id'],
client_secret=creds_data['client_secret'],
scopes=creds_data['scopes']
)
# Refresh token if expired
if credentials.expired:
credentials.refresh(Request())
return credentials
except FileNotFoundError:
print("Error: secrets.json not found! Please run setup.py first.")
return None
except Exception as e:
print(f"Error loading credentials: {str(e)}")
return None
def upload_video(file_path: str, title: str, category: CategoryId, description: str = "", privacyStatus: str = 'private', tags: list = None, release_time: datetime = None):
def upload_video(file_path: str, title: str, category: CategoryId, description: str = "", privacyStatus: str = 'private', tags: list = None, release_time: datetime = None) -> bool:
"""
Upload a video to YouTube
@@ -82,12 +54,11 @@ def upload_video(file_path: str, title: str, category: CategoryId, description:
return False
# Load credentials
credentials = load_credentials()
if not credentials:
if not config.CREDENTIALS:
return False
# Create YouTube API client
youtube = build('youtube', 'v3', credentials=credentials)
youtube = build('youtube', 'v3', credentials=config.CREDENTIALS)
# Configure the status object dynamically
status_body = {
@@ -197,5 +168,6 @@ def main():
tags=parsed_tags,
release_time=release_datetime
)
if __name__ == "__main__":
main()