Whisper-TikTok-Demo / src /video_creator.py
MatteoFasulo's picture
New [DEV] version
b9adb22
from pathlib import Path
import stable_whisper as whisper
# Local imports
from .subtitle_creator import srt_create
from .text_to_speech import tts
from .tiktok import upload_tiktok
from .video_prepare import prepare_background
from .video_downloader import download_video as youtube_download
from utils import *
HOME = Path.cwd()
media_folder = HOME / 'media'
class ClipMaker:
def __init__(self, clip: dict, args):
self.clip = clip
self.args = args
# Fetch clip data or set default values
self.series = clip.get('series', 'Crazy facts that you did not know')
self.part = clip.get('part', '1')
self.text = clip.get('text', 'The first person to survive going over Niagara Falls in a barrel was a 63-year-old school teacher')
self.tags = clip.get('tags', ['survive', 'Niagara Falls', 'facts'])
self.outro = clip.get('outro', 'I hope you enjoyed this video. If you did, please give it a thumbs up and subscribe to my channel. I will see you in the next video.')
# Set media folder path
self.path = Path(media_folder).absolute()
def download_background_video(self, folder='background') -> None:
# Download background video for the clip
youtube_download(url=self.args.url, folder=folder)
console.log(f"{msg.OK}Video downloaded from {self.args.url} to {folder}")
return None
def load_model(self):
# Load Whisper model
model = self.args.model
if self.args.model != "large" and not self.args.non_english:
model = self.args.model + ".en"
whisper_model = whisper.load_model(model)
# Set model to class attribute
self.model = whisper_model
return whisper_model
def merge_clip_text(self) -> tuple:
# Merge clip series, part, text and outro to create a single text for the clip
req_text = f"{self.series} - Part {self.part}.\n{self.text}\n{self.outro}" # TODO: allow user to customize this
# Remove whitespaces from series name and create a folder for the series
series = self.series.replace(' ', '_')
filename = f"{self.path}{os.sep}{series}{os.sep}{series}_{self.part}.mp3"
# Create series folder if it does not exist
Path(f"{self.path}{os.sep}{series}").mkdir(parents=True, exist_ok=True)
# Set class attributes for text and mp3 (audio) file
self.req_text = req_text
self.mp3_file = filename
return req_text, filename
async def text_to_speech(self) -> None:
# Convert text to speech using the selected TTS voice
await tts(self.req_text, outfile=self.mp3_file, voice=self.args.tts, args=self.args)
return None
def generate_transcription(self) -> Path:
# Generate subtitles for the clip using the Whisper model
ass_filename = srt_create(self.model,
self.path, self.series, self.part, self.mp3_file, **vars(self.args))
# Get the absolute path of .ass file
ass_filename = Path(ass_filename).absolute()
# Set class attribute for .ass style file of subtitles
self.ass_file = ass_filename
return ass_filename
def select_background(self, random: bool = True) -> Path:
# Select which background video to use for the clip
try:
# Background video selected with WebUI for Streamlit
# Add to the path the parent folder (background)
background_file = self.args.mp4_background
background_mp4 = Path(HOME / 'background' / background_file) # Concat path
background_mp4 = background_mp4.absolute()
except AttributeError: # Local CLI execution
if random:
background_mp4 = random_background()
else: # TODO: allow the user to select which background video to use
pass
# Set class attribute for mp4 background file
self.mp4_background = background_mp4
return background_mp4
def integrate_subtitles(self) -> Path:
# Use FFMPEG to integrate subtitles into background video and trim everything with fixed length of the audio file
final_video = prepare_background(str(self.mp4_background), filename_mp3=self.mp3_file, filename_srt=str(self.ass_file), verbose=self.args.verbose)
final_video = Path(final_video).absolute()
# Set class attribute for mp4 final clip file
self.mp4_final_video = final_video
return final_video
def upload_to_tiktok(self) -> bool: # TODO: check if still working with Cookie
# Automatic upload on TikTok
uploaded = upload_tiktok(str(self.mp4_final_video), title=f"{self.series} - {self.part}", tags=self.tags, headless=not self.args.verbose)
return uploaded