new toml config and added background audio feature
This commit is contained in:
1 parent
15a4f80f99
commit
1f48c53a74
5 files changed
+89
-47
No files matched your search
@@ -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.
|
||||
|
||||
+2
-1
@@ -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 📁")
|
||||
Reference in new issue
Block a user