@ -2,18 +2,16 @@ import multiprocessing
import os
import os
import re
import re
import tempfile
import tempfile
import threading
import textwrap
import textwrap
import threading
import time
import time
from pathlib import Path
from os . path import exists # Needs to be imported specifically
from os . path import exists # Needs to be imported specifically
from typing import Final
from pathlib import Path
from typing import Tuple, Dict
from typing import Dict, Final , Tuple
import ffmpeg
import ffmpeg
import translators
import translators
from PIL import Image Draw, ImageFont , Image
from PIL import Image , Image Draw, ImageFont
from rich . console import Console
from rich . console import Console
from rich . progress import track
from rich . progress import track
@ -79,7 +77,9 @@ def name_normalize(name: str) -> str:
lang = settings . config [ " reddit " ] [ " thread " ] [ " post_lang " ]
lang = settings . config [ " reddit " ] [ " thread " ] [ " post_lang " ]
if lang :
if lang :
print_substep ( " Translating filename... " )
print_substep ( " Translating filename... " )
translated_name = translators . translate_text ( name , translator = " google " , to_language = lang )
translated_name = translators . translate_text (
name , translator = " google " , to_language = lang
)
return translated_name
return translated_name
else :
else :
return name
return name
@ -118,7 +118,10 @@ def create_fancy_thumbnail(image, text, text_color, padding, wrap=35):
lines = textwrap . wrap ( text , width = wrap )
lines = textwrap . wrap ( text , width = wrap )
y = (
y = (
( image_height / 2 )
( image_height / 2 )
- ( ( ( getheight ( font , text ) + ( len ( lines ) * padding ) / len ( lines ) ) * len ( lines ) ) / 2 )
- (
( ( getheight ( font , text ) + ( len ( lines ) * padding ) / len ( lines ) ) * len ( lines ) )
/ 2
)
+ 30
+ 30
)
)
draw = ImageDraw . Draw ( image )
draw = ImageDraw . Draw ( image )
@ -135,28 +138,52 @@ def create_fancy_thumbnail(image, text, text_color, padding, wrap=35):
if len ( lines ) == 3 :
if len ( lines ) == 3 :
lines = textwrap . wrap ( text , width = wrap + 10 )
lines = textwrap . wrap ( text , width = wrap + 10 )
font_title_size = 40
font_title_size = 40
font = ImageFont . truetype ( os . path . join ( " fonts " , " Roboto-Bold.ttf " ) , font_title_size )
font = ImageFont . truetype (
os . path . join ( " fonts " , " Roboto-Bold.ttf " ) , font_title_size
)
y = (
y = (
( image_height / 2 )
( image_height / 2 )
- ( ( ( getheight ( font , text ) + ( len ( lines ) * padding ) / len ( lines ) ) * len ( lines ) ) / 2 )
- (
(
( getheight ( font , text ) + ( len ( lines ) * padding ) / len ( lines ) )
* len ( lines )
)
/ 2
)
+ 35
+ 35
)
)
elif len ( lines ) == 4 :
elif len ( lines ) == 4 :
lines = textwrap . wrap ( text , width = wrap + 10 )
lines = textwrap . wrap ( text , width = wrap + 10 )
font_title_size = 35
font_title_size = 35
font = ImageFont . truetype ( os . path . join ( " fonts " , " Roboto-Bold.ttf " ) , font_title_size )
font = ImageFont . truetype (
os . path . join ( " fonts " , " Roboto-Bold.ttf " ) , font_title_size
)
y = (
y = (
( image_height / 2 )
( image_height / 2 )
- ( ( ( getheight ( font , text ) + ( len ( lines ) * padding ) / len ( lines ) ) * len ( lines ) ) / 2 )
- (
(
( getheight ( font , text ) + ( len ( lines ) * padding ) / len ( lines ) )
* len ( lines )
)
/ 2
)
+ 40
+ 40
)
)
elif len ( lines ) > 4 :
elif len ( lines ) > 4 :
lines = textwrap . wrap ( text , width = wrap + 10 )
lines = textwrap . wrap ( text , width = wrap + 10 )
font_title_size = 30
font_title_size = 30
font = ImageFont . truetype ( os . path . join ( " fonts " , " Roboto-Bold.ttf " ) , font_title_size )
font = ImageFont . truetype (
os . path . join ( " fonts " , " Roboto-Bold.ttf " ) , font_title_size
)
y = (
y = (
( image_height / 2 )
( image_height / 2 )
- ( ( ( getheight ( font , text ) + ( len ( lines ) * padding ) / len ( lines ) ) * len ( lines ) ) / 2 )
- (
(
( getheight ( font , text ) + ( len ( lines ) * padding ) / len ( lines ) )
* len ( lines )
)
/ 2
)
+ 30
+ 30
)
)
@ -173,7 +200,9 @@ def merge_background_audio(audio: ffmpeg, reddit_id: str):
audio ( ffmpeg ) : The TTS final audio but without background .
audio ( ffmpeg ) : The TTS final audio but without background .
reddit_id ( str ) : The ID of subreddit
reddit_id ( str ) : The ID of subreddit
"""
"""
background_audio_volume = settings . config [ " settings " ] [ " background " ] [ " background_audio_volume " ]
background_audio_volume = settings . config [ " settings " ] [ " background " ] [
" background_audio_volume "
]
if background_audio_volume == 0 :
if background_audio_volume == 0 :
return audio # Return the original audio
return audio # Return the original audio
else :
else :
@ -227,27 +256,42 @@ def make_final_video(
if settings . config [ " settings " ] [ " storymode " ] :
if settings . config [ " settings " ] [ " storymode " ] :
if settings . config [ " settings " ] [ " storymodemethod " ] == 0 :
if settings . config [ " settings " ] [ " storymodemethod " ] == 0 :
audio_clips = [ ffmpeg . input ( f " assets/temp/ { reddit_id } /mp3/title.mp3 " ) ]
audio_clips = [ ffmpeg . input ( f " assets/temp/ { reddit_id } /mp3/title.mp3 " ) ]
audio_clips . insert ( 1 , ffmpeg . input ( 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 = [
ffmpeg . input ( f " assets/temp/ { reddit_id } /mp3/postaudio- { i } .mp3 " )
ffmpeg . input ( f " assets/temp/ { reddit_id } /mp3/postaudio- { i } .mp3 " )
for i in track ( range ( number_of_clips + 1 ) , " Collecting the audio files... " )
for i in track (
range ( number_of_clips + 1 ) , " Collecting the audio files... "
)
]
]
audio_clips . insert ( 0 , ffmpeg . input ( 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 )
ffmpeg . input ( f " assets/temp/ { reddit_id } /mp3/ { i } .mp3 " )
for i in range ( number_of_clips )
]
]
audio_clips . insert ( 0 , ffmpeg . input ( f " assets/temp/ { reddit_id } /mp3/title.mp3 " ) )
audio_clips . insert ( 0 , ffmpeg . input ( f " assets/temp/ { reddit_id } /mp3/title.mp3 " ) )
audio_clips_durations = [
audio_clips_durations = [
float ( ffmpeg . probe ( f " assets/temp/ { reddit_id } /mp3/ { i } .mp3 " ) [ " format " ] [ " duration " ] )
float (
ffmpeg . probe ( f " assets/temp/ { reddit_id } /mp3/ { i } .mp3 " ) [ " format " ] [
" duration "
]
)
for i in range ( number_of_clips )
for i in range ( number_of_clips )
]
]
audio_clips_durations . insert (
audio_clips_durations . insert (
0 ,
0 ,
float ( ffmpeg . probe ( f " assets/temp/ { reddit_id } /mp3/title.mp3 " ) [ " format " ] [ " duration " ] ) ,
float (
ffmpeg . probe ( f " assets/temp/ { reddit_id } /mp3/title.mp3 " ) [ " format " ] [
" duration "
]
) ,
)
)
audio_concat = ffmpeg . concat ( * audio_clips , a = 1 , v = 0 )
audio_concat = ffmpeg . concat ( * audio_clips , a = 1 , v = 0 )
ffmpeg . output (
ffmpeg . output (
@ -290,13 +334,19 @@ def make_final_video(
if settings . config [ " settings " ] [ " storymode " ] :
if settings . config [ " settings " ] [ " storymode " ] :
audio_clips_durations = [
audio_clips_durations = [
float (
float (
ffmpeg . probe ( f " assets/temp/ { reddit_id } /mp3/postaudio- { i } .mp3 " ) [ " format " ] [ " duration " ]
ffmpeg . probe ( f " assets/temp/ { reddit_id } /mp3/postaudio- { i } .mp3 " ) [
" format "
] [ " duration " ]
)
)
for i in range ( number_of_clips )
for i in range ( number_of_clips )
]
]
audio_clips_durations . insert (
audio_clips_durations . insert (
0 ,
0 ,
float ( ffmpeg . probe ( f " assets/temp/ { reddit_id } /mp3/title.mp3 " ) [ " format " ] [ " duration " ] ) ,
float (
ffmpeg . probe ( f " assets/temp/ { reddit_id } /mp3/title.mp3 " ) [ " format " ] [
" duration "
]
) ,
)
)
if settings . config [ " settings " ] [ " storymodemethod " ] == 0 :
if settings . config [ " settings " ] [ " storymodemethod " ] == 0 :
image_clips . insert (
image_clips . insert (
@ -313,7 +363,9 @@ def make_final_video(
)
)
current_time + = audio_clips_durations [ 0 ]
current_time + = audio_clips_durations [ 0 ]
elif settings . config [ " settings " ] [ " storymodemethod " ] == 1 :
elif settings . config [ " settings " ] [ " storymodemethod " ] == 1 :
for i in track ( range ( 0 , number_of_clips + 1 ) , " Collecting the image files... " ) :
for i in track (
range ( 0 , number_of_clips + 1 ) , " Collecting the image files... "
) :
image_clips . append (
image_clips . append (
ffmpeg . input ( f " assets/temp/ { reddit_id } /png/img { i } .png " ) [ " v " ] . filter (
ffmpeg . input ( f " assets/temp/ { reddit_id } /png/img { i } .png " ) [ " v " ] . filter (
" scale " , screenshot_width , - 1
" scale " , screenshot_width , - 1
@ -329,9 +381,9 @@ def make_final_video(
else :
else :
for i in range ( 0 , number_of_clips + 1 ) :
for i in range ( 0 , number_of_clips + 1 ) :
image_clips . append (
image_clips . append (
ffmpeg . input ( f " assets/temp/ { reddit_id } /png/comment_ { i } .png " ) [ " v " ] . filter (
ffmpeg . input ( f " assets/temp/ { reddit_id } /png/comment_ { i } .png " ) [
" scale" , screenshot_width , - 1
" v"
)
]. filter ( " scale " , screenshot_width , - 1 )
)
)
image_overlay = image_clips [ i ] . filter ( " colorchannelmixer " , aa = opacity )
image_overlay = image_clips [ i ] . filter ( " colorchannelmixer " , aa = opacity )
assert (
assert (
@ -353,11 +405,15 @@ def make_final_video(
subreddit = settings . config [ " reddit " ] [ " thread " ] [ " subreddit " ]
subreddit = settings . config [ " reddit " ] [ " thread " ] [ " subreddit " ]
if not exists ( f " ./results/ { subreddit } " ) :
if not exists ( f " ./results/ { subreddit } " ) :
print_substep ( " The ' results ' folder could not be found so it was automatically created. " )
print_substep (
" The ' results ' folder could not be found so it was automatically created. "
)
os . makedirs ( f " ./results/ { subreddit } " )
os . makedirs ( f " ./results/ { subreddit } " )
if not exists ( f " ./results/ { subreddit } /OnlyTTS " ) and allowOnlyTTSFolder :
if not exists ( f " ./results/ { subreddit } /OnlyTTS " ) and allowOnlyTTSFolder :
print_substep ( " The ' OnlyTTS ' folder could not be found so it was automatically created. " )
print_substep (
" The ' OnlyTTS ' folder could not be found so it was automatically created. "
)
os . makedirs ( f " ./results/ { subreddit } /OnlyTTS " )
os . makedirs ( f " ./results/ { subreddit } /OnlyTTS " )
# create a thumbnail for the video
# create a thumbnail for the video
@ -371,7 +427,11 @@ def make_final_video(
os . makedirs ( f " ./results/ { subreddit } /thumbnails " )
os . makedirs ( f " ./results/ { subreddit } /thumbnails " )
# get the first file with the .png extension from assets/backgrounds and use it as a background for the thumbnail
# get the first file with the .png extension from assets/backgrounds and use it as a background for the thumbnail
first_image = next (
first_image = next (
( file for file in os . listdir ( " assets/backgrounds " ) if file . endswith ( " .png " ) ) ,
(
file
for file in os . listdir ( " assets/backgrounds " )
if file . endswith ( " .png " )
) ,
None ,
None ,
)
)
if first_image is None :
if first_image is None :
@ -393,7 +453,9 @@ def make_final_video(
title_thumb ,
title_thumb ,
)
)
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 "
)
text = f " Background by { background_config [ ' video ' ] [ 2 ] } "
text = f " Background by { background_config [ ' video ' ] [ 2 ] } "
background_clip = ffmpeg . drawtext (
background_clip = ffmpeg . drawtext (
@ -434,7 +496,9 @@ def make_final_video(
" b:a " : " 192k " ,
" b:a " : " 192k " ,
" threads " : multiprocessing . cpu_count ( ) ,
" threads " : multiprocessing . cpu_count ( ) ,
} ,
} ,
) . overwrite_output ( ) . global_args ( " -progress " , progress . output_file . name ) . run (
) . overwrite_output ( ) . global_args (
" -progress " , progress . output_file . name
) . run (
quiet = True ,
quiet = True ,
overwrite_output = True ,
overwrite_output = True ,
capture_stdout = False ,
capture_stdout = False ,
@ -464,7 +528,9 @@ def make_final_video(
" b:a " : " 192k " ,
" b:a " : " 192k " ,
" threads " : multiprocessing . cpu_count ( ) ,
" threads " : multiprocessing . cpu_count ( ) ,
} ,
} ,
) . overwrite_output ( ) . global_args ( " -progress " , progress . output_file . name ) . run (
) . overwrite_output ( ) . global_args (
" -progress " , progress . output_file . name
) . run (
quiet = True ,
quiet = True ,
overwrite_output = True ,
overwrite_output = True ,
capture_stdout = False ,
capture_stdout = False ,