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!
- [ ] 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 background that is picked instead of the Minecraft one.
- [x] Allowing users to choose between any subreddit.

@ -19,4 +19,5 @@ unidecode==1.3.2
spacy==3.4.1
torch==1.12.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]
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_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_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" }

@ -5,12 +5,13 @@ from pathlib import Path
from random import randrange
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 pytube import YouTube
from pytube.cli import on_progress
from utils import settings
from utils.console import print_step, print_substep
import yt_dlp
def load_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(f"Downloading {filename} from {uri}")
YouTube(uri, on_progress_callback=on_progress).streams.filter(
res="1080p"
).first().download("assets/backgrounds/video", filename=f"{credit}-{filename}")
ydl_opts = {
'format': "bestvideo[height<=1080][ext=mp4]",
"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")
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}")
print_substep("Background audio downloaded successfully! 🎉", style="bold green")
def chop_background(
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
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...✂️")
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_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_audio, end_time_audio = get_start_and_end_times(video_length, background_audio.duration)
# 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)
# Extract video subclip
try:
ffmpeg_extract_subclip(
f"assets/backgrounds/video/{video_choice}",

@ -103,6 +103,28 @@ def prepare_background(reddit_id: str, W: int, H: int) -> str:
exit()
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(
number_of_clips: int,
@ -122,6 +144,10 @@ def make_final_video(
H: Final[int] = int(settings.config["settings"]["resolution_h"])
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 🎥")
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)
audio = ffmpeg.input(f"assets/temp/{reddit_id}/audio.mp3")
background_audio = ffmpeg.input(f"assets/temp/{reddit_id}/background.mp3")
final_audio = ffmpeg.filter([audio, background_audio], "amix")
final_audio = merge_background_audio(audio,reddit_id)
image_clips = list()
@ -263,9 +288,9 @@ def make_final_video(
print_substep("The results folder didn't exist so I made it")
os.makedirs(f"./results/{subreddit}")
if not exists(f"./results/{subreddit}/{filename}"):
print_substep("The results folder didn't exist so I made it")
os.makedirs(f"./results/{subreddit}/{filename}")
if not exists(f"./results/{subreddit}/OnlyTTS") and allowOnlyTTSFolder:
print_substep("The 'OnlyTTS' folder didn't exist so I made it")
os.makedirs(f"./results/{subreddit}/OnlyTTS")
# create a thumbnail for the video
settingsbackground = settings.config["settings"]["background"]
@ -326,9 +351,10 @@ def make_final_video(
old_percentage = pbar.n
pbar.update(status - old_percentage)
path = f"results/{subreddit}/{filename}"
path = path[:251]
path = f"results/{subreddit}"
#path = path + ".mp4"
if(allowOnlyTTSFolder):
processingLength = 2*length
with ProgressFfmpeg(length, on_update_example) as progress:
ffmpeg.output(
@ -348,32 +374,38 @@ def make_final_video(
capture_stdout=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
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()
save_data(subreddit, filename + ".mp4", title, idx, background_config['video'][2])
print_step("Removing temporary files 🗑")
cleanups = cleanup(reddit_id)
print_substep(f"Removed {cleanups} temporary files 🗑")
print_step("Done! 🎉 The video is in the results folder 📁")
print_step("Done! 🎉 The video is in the results folder 📁")
Loading…
Cancel
Save