final_video.py: ffmpeg-python port

pull/1409/head
Xpl0itU 2 years ago
parent 6041cce53e
commit 6024ae7e4f

@ -18,6 +18,8 @@ from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
from rich.console import Console from rich.console import Console
from rich.progress import track from rich.progress import track
import ffmpeg
from utils.cleanup import cleanup from utils.cleanup import cleanup
from utils.console import print_step, print_substep from utils.console import print_step, print_substep
from utils.video import Video from utils.video import Video
@ -46,22 +48,14 @@ def name_normalize(name: str) -> str:
return name return name
def prepare_background(reddit_id: str, W: int, H: int) -> VideoFileClip: def prepare_background(reddit_id: str, W: int, H: int) -> str:
clip = ( output_path = f"assets/temp/{reddit_id}/background_noaudio.mp4"
VideoFileClip(f"assets/temp/{reddit_id}/background.mp4") if settings.config["settings"]["storymode"]:
.without_audio() output = ffmpeg.input(f"assets/temp/{reddit_id}/background.mp4").output(output_path, an=None, **{"c:v": "h264"}).overwrite_output()
.resize(height=H) else:
) output = ffmpeg.input(f"assets/temp/{reddit_id}/background.mp4").filter('crop', "ih*(9/16)", "ih").output(output_path, an=None, **{"c:v": "h264"}).overwrite_output()
output.run()
# calculate the center of the background clip return output_path
c = clip.w // 2
# calculate the coordinates where to crop
half_w = W // 2
x1 = c - half_w
x2 = c + half_w
return clip.crop(x1=x1, y1=0, x2=x2, y2=H)
def make_final_video( def make_final_video(
@ -81,103 +75,86 @@ def make_final_video(
W: Final[int] = int(settings.config["settings"]["resolution_w"]) W: Final[int] = int(settings.config["settings"]["resolution_w"])
H: Final[int] = int(settings.config["settings"]["resolution_h"]) H: Final[int] = int(settings.config["settings"]["resolution_h"])
# try: # if it isn't found (i.e you just updated and copied over config.toml) it will throw an error
# VOLUME_MULTIPLIER = settings.config["settings"]['background']["background_audio_volume"]
# except (TypeError, KeyError):
# print('No background audio volume found in config.toml. Using default value of 1.')
# VOLUME_MULTIPLIER = 1
reddit_id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) reddit_id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"])
print_step("Creating the final video 🎥") print_step("Creating the final video 🎥")
VideoFileClip.reW = lambda clip: clip.resize(width=W)
VideoFileClip.reH = lambda clip: clip.resize(width=H)
opacity = settings.config["settings"]["opacity"] opacity = settings.config["settings"]["opacity"]
transition = settings.config["settings"]["transition"] transition = settings.config["settings"]["transition"]
background_clip = prepare_background(reddit_id, W=W, H=H) background_clip = ffmpeg.input(prepare_background(reddit_id, W=W, H=H))
# Gather all audio clips # Gather all audio clips
audio_clips = list()
if settings.config["settings"]["storymode"]: if settings.config["settings"]["storymode"]:
if settings.config["settings"]["storymodemethod"] == 0: if settings.config["settings"]["storymodemethod"] == 0:
audio_clips = [AudioFileClip(f"assets/temp/{reddit_id}/mp3/title.mp3")] audio_clips = [ffmpeg.input(f"assets/temp/{reddit_id}/mp3/title.mp3")]
audio_clips.insert(1, AudioFileClip(f"assets/temp/{reddit_id}/mp3/postaudio.mp3")) audio_clips.insert(1, ffmpeg.input(f"assets/temp/{reddit_id}/mp3/postaudio.mp3"))
elif settings.config["settings"]["storymodemethod"] == 1: elif settings.config["settings"]["storymodemethod"] == 1:
audio_clips = [ audio_clips = [
AudioFileClip(f"assets/temp/{reddit_id}/mp3/postaudio-{i}.mp3") ffmpeg.input(f"assets/temp/{reddit_id}/mp3/postaudio-{i}.mp3")
for i in track( for i in track(
range(number_of_clips + 1), "Collecting the audio files..." range(number_of_clips + 1), "Collecting the audio files..."
) )
] ]
audio_clips.insert(0, AudioFileClip(f"assets/temp/{reddit_id}/mp3/title.mp3")) audio_clips.insert(0, ffmpeg.input(f"assets/temp/{reddit_id}/mp3/title.mp3"))
else: else:
audio_clips = [ audio_clips = [ffmpeg.input(f"assets/temp/{reddit_id}/mp3/{i}.mp3") for i in range(number_of_clips)]
AudioFileClip(f"assets/temp/{reddit_id}/mp3/{i}.mp3") audio_clips.insert(0, ffmpeg.input(f"assets/temp/{reddit_id}/mp3/title.mp3"))
for i in range(number_of_clips)
] audio_clips_durations = [float(ffmpeg.probe(f"assets/temp/{reddit_id}/mp3/{i}.mp3")['format']['duration']) for i in range(number_of_clips)]
audio_clips.insert(0, AudioFileClip(f"assets/temp/{reddit_id}/mp3/title.mp3")) audio_clips_durations.insert(0, float(ffmpeg.probe(f"assets/temp/{reddit_id}/mp3/title.mp3")['format']['duration']))
audio_concat = concatenate_audioclips(audio_clips) audio_concat = ffmpeg.concat(*audio_clips, a=1, v=0)
audio_composite = CompositeAudioClip([audio_concat]) ffmpeg.output(audio_concat, f"assets/temp/{reddit_id}/audio.mp3").overwrite_output().run()
console.log(f"[bold green] Video Will Be: {length} Seconds Long") console.log(f"[bold green] Video Will Be: {length} Seconds Long")
# add title to video
image_clips = []
# Gather all images # Gather all images
new_opacity = 1 if opacity is None or float(opacity) >= 1 else float(opacity) new_opacity = 1 if opacity is None or float(opacity) >= 1 else float(opacity)
new_transition = ( new_transition = (
0 if transition is None or float(transition) > 2 else float(transition) 0 if transition is None or float(transition) > 2 else float(transition)
) )
screenshot_width = int((W * 90) // 100) screenshot_width = "iw-800"
audio = ffmpeg.input(f"assets/temp/{reddit_id}/audio.mp3")
video = ffmpeg.input(f"assets/temp/{reddit_id}/background_noaudio.mp4")
image_clips = list()
image_clips.insert( image_clips.insert(
0, 0,
ImageClip(f"assets/temp/{reddit_id}/png/title.png") ffmpeg.input(f"assets/temp/{reddit_id}/png/title.png")['v']
.set_duration(audio_clips[0].duration) .filter('scale', screenshot_width, -1)
.resize(width=screenshot_width)
.set_opacity(new_opacity)
.crossfadein(new_transition)
.crossfadeout(new_transition),
) )
current_time = 0
if settings.config["settings"]["storymode"]: if settings.config["settings"]["storymode"]:
if settings.config["settings"]["storymodemethod"] == 0: if settings.config["settings"]["storymodemethod"] == 0:
image_clips.insert( image_clips.insert(
1, 1,
ImageClip(f"assets/temp/{reddit_id}/png/story_content.png") ffmpeg.input(f"assets/temp/{reddit_id}/png/story_content.png")
.set_duration(audio_clips[1].duration) .filter('scale', screenshot_width, -1)
.set_position("center")
.resize(width=screenshot_width)
.set_opacity(float(opacity)),
) )
video = video.overlay(image_clips[i], enable=f'between(t,{current_time},{current_time + audio_clips_durations[i]})', x='(main_w-overlay_w)/2', y='(main_h-overlay_h)/2')
current_time += audio_clips_durations[i]
elif settings.config["settings"]["storymodemethod"] == 1: elif settings.config["settings"]["storymodemethod"] == 1:
for i in track( for i in track(
range(0, number_of_clips + 1), "Collecting the image files..." range(0, number_of_clips + 1), "Collecting the image files..."
): ):
image_clips.append( image_clips.append(
ImageClip(f"assets/temp/{reddit_id}/png/img{i}.png") ffmpeg.input(f"assets/temp/{reddit_id}/png/img{i}.png")['v']
.set_duration(audio_clips[i + 1].duration) .filter('scale', screenshot_width, -1)
.resize(width=screenshot_width)
.set_opacity(new_opacity)
# .crossfadein(new_transition)
# .crossfadeout(new_transition)
) )
video = video.overlay(image_clips[i], enable=f'between(t,{current_time},{current_time + audio_clips_durations[i]})', x='(main_w-overlay_w)/2', y='(main_h-overlay_h)/2')
current_time += audio_clips_durations[i]
else: else:
for i in range(0, number_of_clips): for i in range(0, number_of_clips + 1):
image_clips.append( image_clips.append(
ImageClip(f"assets/temp/{reddit_id}/png/comment_{i}.png") ffmpeg.input(f"assets/temp/{reddit_id}/png/comment_{i}.png")['v']
.set_duration(audio_clips[i + 1].duration) .filter('scale', screenshot_width, -1)
.resize(width=screenshot_width)
.set_opacity(new_opacity)
.crossfadein(new_transition)
.crossfadeout(new_transition)
) )
video = video.overlay(image_clips[i], enable=f'between(t,{current_time},{current_time + audio_clips_durations[i]})', x='(main_w-overlay_w)/2', y='(main_h-overlay_h)/2')
current_time += audio_clips_durations[i]
img_clip_pos = background_config[3]
image_concat = concatenate_videoclips(image_clips).set_position(
img_clip_pos
) # note transition kwarg for delay in imgs
image_concat.audio = audio_composite
final = CompositeVideoClip([background_clip, image_concat])
title = re.sub(r"[^\w\s-]", "", reddit_obj["thread_title"]) title = re.sub(r"[^\w\s-]", "", reddit_obj["thread_title"])
idx = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) idx = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"])
title_thumb = reddit_obj["thread_title"] title_thumb = reddit_obj["thread_title"]
@ -185,6 +162,8 @@ def make_final_video(
filename = f"{name_normalize(title)[:251]}" filename = f"{name_normalize(title)[:251]}"
subreddit = settings.config["reddit"]["thread"]["subreddit"] subreddit = settings.config["reddit"]["thread"]["subreddit"]
final = ffmpeg.output(video, audio, f"results/{subreddit}/{filename}.mp4", f='mp4', **{"c:v": "h264"}).overwrite_output()
if not exists(f"./results/{subreddit}"): if not exists(f"./results/{subreddit}"):
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}")
@ -249,37 +228,10 @@ def make_final_video(
thumbnailSave.save(f"./assets/temp/{reddit_id}/thumbnail.png") thumbnailSave.save(f"./assets/temp/{reddit_id}/thumbnail.png")
print_substep(f"Thumbnail - Building Thumbnail in assets/temp/{reddit_id}/thumbnail.png") print_substep(f"Thumbnail - Building Thumbnail in assets/temp/{reddit_id}/thumbnail.png")
# if settings.config["settings"]['background']["background_audio"] and exists(f"assets/backgrounds/background.mp3"): final.run()
# audioclip = mpe.AudioFileClip(f"assets/backgrounds/background.mp3").set_duration(final.duration)
# audioclip = audioclip.fx( volumex, 0.2)
# final_audio = mpe.CompositeAudioClip([final.audio, audioclip])
# # lowered_audio = audio_background.multiply_volume( # todo get this to work
# # VOLUME_MULTIPLIER) # lower volume by background_audio_volume, use with fx
# final.set_audio(final_audio)
final = Video(final).add_watermark(
text=f"Background credit: {background_config[2]}",
opacity=0.4,
redditid=reddit_obj,
)
final.write_videofile(
f"assets/temp/{reddit_id}/temp.mp4",
fps=int(settings.config["settings"]["fps"]),
audio_codec="aac",
audio_bitrate="192k",
verbose=False,
threads=multiprocessing.cpu_count(),
preset="ultrafast", #TODO debug
)
ffmpeg_extract_subclip(
f"assets/temp/{reddit_id}/temp.mp4",
0,
length,
targetname=f"results/{subreddit}/{filename}.mp4",
)
#get the thumbnail image from assets/temp/id/thumbnail.png and save it in results/subreddit/thumbnails #get the thumbnail image from assets/temp/id/thumbnail.png and save it in results/subreddit/thumbnails
if settingsbackground["background_thumbnail"] and exists(f"assets/temp/{id}/thumbnail.png"): if settingsbackground["background_thumbnail"] and exists(f"assets/temp/{reddit_id}/thumbnail.png"):
shutil.move(f"assets/temp/{id}/thumbnail.png", f"./results/{subreddit}/thumbnails/{filename}.png") shutil.move(f"assets/temp/{reddit_id}/thumbnail.png", f"./results/{subreddit}/thumbnails/{filename}.png")
save_data(subreddit, filename+".mp4", title, idx, background_config[2]) save_data(subreddit, filename+".mp4", title, idx, background_config[2])
print_step("Removing temporary files 🗑") print_step("Removing temporary files 🗑")

Loading…
Cancel
Save