new toml config and added background audio feature

pull/1590/head
Lucas 2 years ago
parent 15a4f80f99
commit 1f48c53a74

@ -70,7 +70,7 @@ In its current state, this bot does exactly what it needs to do. However, improv
I have tried to simplify the code so anyone can read it and start contributing at any skill level. Don't be shy :) contribute! I have tried to simplify the code so anyone can read it and start contributing at any skill level. Don't be shy :) contribute!
- [ ] Creating better documentation and adding a command line interface. - [ ] Creating better documentation and adding a command line interface.
- [ ] Allowing the user to choose background music for their videos. - [x] Allowing the user to choose background music for their videos.
- [x] Allowing users to choose a reddit thread instead of being randomized. - [x] Allowing users to choose a reddit thread instead of being randomized.
- [x] Allowing users to choose a background that is picked instead of the Minecraft one. - [x] Allowing users to choose a background that is picked instead of the Minecraft one.
- [x] Allowing users to choose between any subreddit. - [x] Allowing users to choose between any subreddit.

@ -20,3 +20,4 @@ spacy==3.4.1
torch==1.12.1 torch==1.12.1
transformers==4.25.1 transformers==4.25.1
ffmpeg-python==0.2.0 ffmpeg-python==0.2.0
yt-dlp==2023.3.4

@ -35,7 +35,8 @@ resolution_h = { optional = false, default = 1920, example = 2560, explantation
[settings.background] [settings.background]
background_video = { optional = true, default = "minecraft", example = "rocket-league", options = ["minecraft", "gta", "rocket-league", "motor-gta", "csgo-surf", "cluster-truck", "minecraft-2","multiversus","fall-guys","steep", ""], explanation = "Sets the background for the video based on game name" } background_video = { optional = true, default = "minecraft", example = "rocket-league", options = ["minecraft", "gta", "rocket-league", "motor-gta", "csgo-surf", "cluster-truck", "minecraft-2","multiversus","fall-guys","steep", ""], explanation = "Sets the background for the video based on game name" }
background_audio = { optional = true, default = "lofi", example = "minecraft", options = ["minecraft","lofi","undertale"], explanation = "Sets a audio to play in the background (put a background.mp3 file in the assets/backgrounds directory for it to be used.)" } background_audio = { optional = true, default = "lofi", example = "minecraft", options = ["minecraft","lofi","undertale"], explanation = "Sets a audio to play in the background (put a background.mp3 file in the assets/backgrounds directory for it to be used.)" }
background_audio_volume = { optional = true, type = "float", default = 0.1, example = 0.05, explanation="Sets the volume of the background audio. Warning: if you set more than 1.0, the volume will be increased" } background_audio_volume = { optional = true, type = "float", nmin = 0, nmax = 1, default = 0.1, example = 0.05, explanation="Sets the volume of the background audio. Type a value between 0 and 1.", oob_error = "The volume HAS to be between 0 and 1", input_error = "The volume HAS to be a float number between 0 and 1"}
allow_only_tts = { optional = true, type = "bool", default = false, example = false, explanation="Used if you want to render another video with only TTS audio in a separate folder", input_error = "The value HAS to be true or false"}
background_thumbnail = { optional = true, type = "bool", default = false, example = false, options = [true, false,], explanation = "Generate a thumbnail for the video (put a thumbnail.png file in the assets/backgrounds directory.)" } background_thumbnail = { optional = true, type = "bool", default = false, example = false, options = [true, false,], explanation = "Generate a thumbnail for the video (put a thumbnail.png file in the assets/backgrounds directory.)" }
background_thumbnail_font_family = { optional = true, default = "arial", example = "arial", explanation = "Font family for the thumbnail text" } background_thumbnail_font_family = { optional = true, default = "arial", example = "arial", explanation = "Font family for the thumbnail text" }
background_thumbnail_font_size = { optional = true, type = "int", default = 96, example = 96, explanation = "Font size in pixels for the thumbnail text" } background_thumbnail_font_size = { optional = true, type = "int", default = 96, example = 96, explanation = "Font size in pixels for the thumbnail text" }

@ -5,12 +5,13 @@ from pathlib import Path
from random import randrange from random import randrange
from typing import Any, Tuple,Dict from typing import Any, Tuple,Dict
from moviepy.editor import VideoFileClip,AudioFileClip,afx from moviepy.editor import VideoFileClip,AudioFileClip
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
from pytube import YouTube from pytube import YouTube
from pytube.cli import on_progress from pytube.cli import on_progress
from utils import settings from utils import settings
from utils.console import print_step, print_substep from utils.console import print_step, print_substep
import yt_dlp
def load_background_options(): def load_background_options():
background_options = {} background_options = {}
@ -81,9 +82,14 @@ def download_background_video(background_config: Tuple[str, str, str, Any]):
) )
print_substep("Downloading the backgrounds videos... please be patient 🙏 ") print_substep("Downloading the backgrounds videos... please be patient 🙏 ")
print_substep(f"Downloading {filename} from {uri}") print_substep(f"Downloading {filename} from {uri}")
YouTube(uri, on_progress_callback=on_progress).streams.filter( ydl_opts = {
res="1080p" 'format': "bestvideo[height<=1080][ext=mp4]",
).first().download("assets/backgrounds/video", filename=f"{credit}-{filename}") "outtmpl": f"assets/backgrounds/video/{credit}-{filename}",
"retries": 10,
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(uri)
print_substep("Background video downloaded successfully! 🎉", style="bold green") print_substep("Background video downloaded successfully! 🎉", style="bold green")
def download_background_audio(background_config: Tuple[str, str, str]): def download_background_audio(background_config: Tuple[str, str, str]):
@ -103,6 +109,8 @@ def download_background_audio(background_config: Tuple[str, str, str]):
).first().download("assets/backgrounds/audio", filename=f"{credit}-{filename}") ).first().download("assets/backgrounds/audio", filename=f"{credit}-{filename}")
print_substep("Background audio downloaded successfully! 🎉", style="bold green") print_substep("Background audio downloaded successfully! 🎉", style="bold green")
def chop_background( def chop_background(
background_config: Dict[str,Tuple], video_length: int, reddit_object: dict background_config: Dict[str,Tuple], video_length: int, reddit_object: dict
): ):
@ -112,23 +120,23 @@ def chop_background(
background_config (Dict[str,Tuple]]) : Current background configuration background_config (Dict[str,Tuple]]) : Current background configuration
video_length (int): Length of the clip where the background footage is to be taken out of video_length (int): Length of the clip where the background footage is to be taken out of
""" """
id = re.sub(r"[^\w\s-]", "", reddit_object["thread_id"])
if(settings.config["settings"]["background"][f"background_audio_volume"] == 0):
print_step("Volume was set to 0. Skipping background audio creation . . .")
else:
print_step("Finding a spot in the backgrounds audio to chop...✂️")
audio_choice = f"{background_config['audio'][2]}-{background_config['audio'][1]}"
background_audio = AudioFileClip(f"assets/backgrounds/audio/{audio_choice}")
start_time_audio, end_time_audio = get_start_and_end_times(video_length, background_audio.duration)
background_audio = background_audio.subclip(start_time_audio,end_time_audio)
background_audio.write_audiofile(f"assets/temp/{id}/background.mp3")
print_step("Finding a spot in the backgrounds video to chop...✂️") print_step("Finding a spot in the backgrounds video to chop...✂️")
video_choice = f"{background_config['video'][2]}-{background_config['video'][1]}" video_choice = f"{background_config['video'][2]}-{background_config['video'][1]}"
audio_choice = f"{background_config['audio'][2]}-{background_config['audio'][1]}"
id = re.sub(r"[^\w\s-]", "", reddit_object["thread_id"])
background_video = VideoFileClip(f"assets/backgrounds/video/{video_choice}") background_video = VideoFileClip(f"assets/backgrounds/video/{video_choice}")
background_audio = AudioFileClip(f"assets/backgrounds/audio/{audio_choice}")
start_time_video, end_time_video = get_start_and_end_times(video_length, background_video.duration) start_time_video, end_time_video = get_start_and_end_times(video_length, background_video.duration)
start_time_audio, end_time_audio = get_start_and_end_times(video_length, background_audio.duration) # Extract video subclip
# Create a audio clip
background_audio_volume = settings.config["settings"]["background"][f"background_audio_volume"]
background_audio = background_audio.fx(afx.volumex,background_audio_volume)
background_audio = background_audio.subclip(start_time_audio,end_time_audio)
background_audio.write_audiofile(f"assets/temp/{id}/background.mp3")
#background_video.set_audio(background_audio)
try: try:
ffmpeg_extract_subclip( ffmpeg_extract_subclip(
f"assets/backgrounds/video/{video_choice}", f"assets/backgrounds/video/{video_choice}",

@ -103,6 +103,28 @@ def prepare_background(reddit_id: str, W: int, H: int) -> str:
exit() exit()
return output_path return output_path
def merge_background_audio(audio: ffmpeg, reddit_id: str):
"""Gather an audio and merge with assets/backgrounds/background.mp3
Args:
audio (ffmpeg): The TTS final audio but without background.
reddit_id (str): The ID of subreddit
"""
background_audio_volume = settings.config["settings"]["background"]["background_audio_volume"]
if (background_audio_volume == 0):
return audio # Return the original audio
else:
# sets volume to config
bg_audio = (
ffmpeg.input(f"assets/temp/{reddit_id}/background.mp3")
.filter(
"volume",
background_audio_volume,
)
)
# Merges audio and background_audio
merged_audio = ffmpeg.filter([audio, bg_audio], "amix", duration="longest")
return merged_audio # Return merged audio
def make_final_video( def make_final_video(
number_of_clips: int, number_of_clips: int,
@ -122,6 +144,10 @@ def make_final_video(
H: Final[int] = int(settings.config["settings"]["resolution_h"]) H: Final[int] = int(settings.config["settings"]["resolution_h"])
reddit_id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) reddit_id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"])
allowOnlyTTSFolder: bool = settings.config["settings"]["background"]["allow_only_tts"] \
and settings.config["settings"]["background"]["background_audio_volume"] != 0
print_step("Creating the final video 🎥") print_step("Creating the final video 🎥")
background_clip = ffmpeg.input(prepare_background(reddit_id, W=W, H=H)) background_clip = ffmpeg.input(prepare_background(reddit_id, W=W, H=H))
@ -177,8 +203,7 @@ def make_final_video(
screenshot_width = int((W * 45) // 100) screenshot_width = int((W * 45) // 100)
audio = ffmpeg.input(f"assets/temp/{reddit_id}/audio.mp3") audio = ffmpeg.input(f"assets/temp/{reddit_id}/audio.mp3")
background_audio = ffmpeg.input(f"assets/temp/{reddit_id}/background.mp3") final_audio = merge_background_audio(audio,reddit_id)
final_audio = ffmpeg.filter([audio, background_audio], "amix")
image_clips = list() image_clips = list()
@ -263,9 +288,9 @@ def make_final_video(
print_substep("The results folder didn't exist so I made it") print_substep("The results folder didn't exist so I made it")
os.makedirs(f"./results/{subreddit}") os.makedirs(f"./results/{subreddit}")
if not exists(f"./results/{subreddit}/{filename}"): if not exists(f"./results/{subreddit}/OnlyTTS") and allowOnlyTTSFolder:
print_substep("The results folder didn't exist so I made it") print_substep("The 'OnlyTTS' folder didn't exist so I made it")
os.makedirs(f"./results/{subreddit}/{filename}") os.makedirs(f"./results/{subreddit}/OnlyTTS")
# create a thumbnail for the video # create a thumbnail for the video
settingsbackground = settings.config["settings"]["background"] settingsbackground = settings.config["settings"]["background"]
@ -326,9 +351,10 @@ def make_final_video(
old_percentage = pbar.n old_percentage = pbar.n
pbar.update(status - old_percentage) pbar.update(status - old_percentage)
path = f"results/{subreddit}/{filename}" path = f"results/{subreddit}"
path = path[:251]
#path = path + ".mp4" #path = path + ".mp4"
if(allowOnlyTTSFolder):
processingLength = 2*length
with ProgressFfmpeg(length, on_update_example) as progress: with ProgressFfmpeg(length, on_update_example) as progress:
ffmpeg.output( ffmpeg.output(
@ -348,30 +374,36 @@ def make_final_video(
capture_stdout=False, capture_stdout=False,
capture_stderr=False, capture_stderr=False,
) )
with ProgressFfmpeg(length, on_update_example) as progress:
ffmpeg.output(
background_clip,
audio,
path+"/NoBackgroundAudio.mp4",
f="mp4",
**{
"c:v": "h264",
"b:v": "20M",
"b:a": "192k",
"threads": multiprocessing.cpu_count(),
},
).overwrite_output().global_args("-progress", progress.output_file.name).run(
quiet=True,
overwrite_output=True,
capture_stdout=False,
capture_stderr=False,
)
old_percentage = pbar.n old_percentage = pbar.n
pbar.update(100 - old_percentage) pbar.update(100 - old_percentage)
if(allowOnlyTTSFolder):
print_step("Rendering the Only TTS Video 🎥")
with ProgressFfmpeg(length, on_update_example) as progress:
ffmpeg.output(
background_clip,
audio,
path+f"/OnlyTTS/{filename}.mp4",
f="mp4",
**{
"c:v": "h264",
"b:v": "20M",
"b:a": "192k",
"threads": multiprocessing.cpu_count(),
},
).overwrite_output().global_args("-progress", progress.output_file.name).run(
quiet=True,
overwrite_output=True,
capture_stdout=False,
capture_stderr=False,
)
old_percentage = pbar.n
pbar.update(100 - old_percentage)
pbar.close() pbar.close()
save_data(subreddit, filename + ".mp4", title, idx, background_config['video'][2]) save_data(subreddit, filename + ".mp4", title, idx, background_config['video'][2])
print_step("Removing temporary files 🗑") print_step("Removing temporary files 🗑")
cleanups = cleanup(reddit_id) cleanups = cleanup(reddit_id)

Loading…
Cancel
Save