feat: Update moviepy to 2.0 (develop)

Update moviepy to 2.0 and other dependencies.

- Updated moviepy to 2.1.2.
- Updated other dependencies such as Pillow, torch, boto3,
  botocore, playwright, and elevenlabs.
- Replaced `volumex` with `MultiplyVolume`.
- Replaced `make_frame` with `frame_function`.
- Removed verbose and logger arguments where deprecated.
- Used `subclipped` instead of `subclip`.
- Changed video processing to use context manager to open
  video files, addressing ffmpeg issues.
- Removed unused variable `idy`.
- Renamed `id` variable to `thread_id` for clarity.

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
pull/2245/head
Jason Cameron 7 months ago
parent 5c72771c5a
commit 943814150c
No known key found for this signature in database

@ -6,14 +6,13 @@ from typing import Tuple
import numpy as np import numpy as np
import translators import translators
from moviepy.audio.AudioClip import AudioClip from moviepy.audio.AudioClip import AudioClip
from moviepy.audio.fx.volumex import volumex from moviepy import AudioFileClip
from moviepy.editor import AudioFileClip
from rich.progress import track from rich.progress import track
from utils import settings from utils import settings
from utils.console import print_step, print_substep from utils.console import print_step, print_substep
from utils.voice import sanitize_text from utils.voice import sanitize_text
from moviepy.audio.fx import MultiplyVolume
DEFAULT_MAX_LENGTH: int = ( DEFAULT_MAX_LENGTH: int = (
50 # Video length variable, edit this on your own risk. It should work, but it's not supported 50 # Video length variable, edit this on your own risk. It should work, but it's not supported
) )
@ -112,7 +111,6 @@ class TTSEngine:
] ]
self.create_silence_mp3() self.create_silence_mp3()
idy = None
for idy, text_cut in enumerate(split_text): for idy, text_cut in enumerate(split_text):
newtext = process_text(text_cut) newtext = process_text(text_cut)
# print(f"{idx}-{idy}: {newtext}\n") # print(f"{idx}-{idy}: {newtext}\n")
@ -171,12 +169,12 @@ class TTSEngine:
def create_silence_mp3(self): def create_silence_mp3(self):
silence_duration = settings.config["settings"]["tts"]["silence_duration"] silence_duration = settings.config["settings"]["tts"]["silence_duration"]
silence = AudioClip( silence = AudioClip(
make_frame=lambda t: np.sin(440 * 2 * np.pi * t), frame_function=lambda t: np.sin(440 * 2 * np.pi * t),
duration=silence_duration, duration=silence_duration,
fps=44100, fps=44100,
) )
silence = volumex(silence, 0) silence = silence.with_effects([MultiplyVolume(0)])
silence.write_audiofile(f"{self.path}/silence.mp3", fps=44100, verbose=False, logger=None) silence.write_audiofile(f"{self.path}/silence.mp3", fps=44100, logger=None)
def process_text(text: str, clean: bool = True): def process_text(text: str, clean: bool = True):

@ -1,23 +1,21 @@
boto3==1.34.127 boto3==1.36.8
botocore==1.34.127 botocore==1.36.8
gTTS==2.5.4 gTTS==2.5.4
moviepy==1.0.3 moviepy==2.1.2
playwright==1.48.0 playwright==1.49.1
praw==7.8.1 praw==7.8.1
requests==2.32.3 requests==2.32.3
rich==13.9.4 rich==13.9.4
toml==0.10.2 toml==0.10.2
translators==5.9.5 translators==5.9.5
pyttsx3==2.98 pyttsx3==2.98
Pillow==10.4.0
tomlkit==0.13.2 tomlkit==0.13.2
Flask==3.1.0 Flask==3.1.0
clean-text==0.6.0 clean-text==0.6.0
unidecode==1.3.8 unidecode==1.3.8
spacy==3.8.3 spacy==3.8.4
torch==2.4.1 torch==2.5.1
transformers==4.48.1 transformers==4.48.1
ffmpeg-python==0.2.0 ffmpeg-python==0.2.0
elevenlabs==1.8.1 elevenlabs==1.50.5
yt-dlp==2025.1.26 yt-dlp==2025.1.26
numpy==1.26.4

@ -6,7 +6,7 @@ from random import randrange
from typing import Any, Dict, Tuple from typing import Any, Dict, Tuple
import yt_dlp import yt_dlp
from moviepy.editor import AudioFileClip, VideoFileClip from moviepy import AudioFileClip, VideoFileClip
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
from utils import settings from utils import settings
@ -14,26 +14,26 @@ from utils.console import print_step, print_substep
def load_background_options(): def load_background_options():
background_options = {} _background_options = {}
# Load background videos # Load background videos
with open("./utils/background_videos.json") as json_file: with open("./utils/background_videos.json") as json_file:
background_options["video"] = json.load(json_file) _background_options["video"] = json.load(json_file)
# Load background audios # Load background audios
with open("./utils/background_audios.json") as json_file: with open("./utils/background_audios.json") as json_file:
background_options["audio"] = json.load(json_file) _background_options["audio"] = json.load(json_file)
# Remove "__comment" from backgrounds # Remove "__comment" from backgrounds
del background_options["video"]["__comment"] del _background_options["video"]["__comment"]
del background_options["audio"]["__comment"] del _background_options["audio"]["__comment"]
for name in list(background_options["video"].keys()): for name in list(_background_options["video"].keys()):
pos = background_options["video"][name][3] pos = _background_options["video"][name][3]
if pos != "center": if pos != "center":
background_options["video"][name][3] = lambda t: ("center", pos + t) _background_options["video"][name][3] = lambda t: ("center", pos + t)
return background_options return _background_options
def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int, int]: def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int, int]:
@ -124,10 +124,11 @@ def chop_background(background_config: Dict[str, Tuple], video_length: int, redd
"""Generates the background audio and footage to be used in the video and writes it to assets/temp/background.mp3 and assets/temp/background.mp4 """Generates the background audio and footage to be used in the video and writes it to assets/temp/background.mp3 and assets/temp/background.mp4
Args: Args:
reddit_object (Dict[str,str]) : Reddit object
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"]) thread_id = re.sub(r"[^\w\s-]", "", reddit_object["thread_id"])
if settings.config["settings"]["background"][f"background_audio_volume"] == 0: if settings.config["settings"]["background"][f"background_audio_volume"] == 0:
print_step("Volume was set to 0. Skipping background audio creation . . .") print_step("Volume was set to 0. Skipping background audio creation . . .")
@ -138,8 +139,8 @@ def chop_background(background_config: Dict[str, Tuple], video_length: int, redd
start_time_audio, end_time_audio = get_start_and_end_times( start_time_audio, end_time_audio = get_start_and_end_times(
video_length, background_audio.duration video_length, background_audio.duration
) )
background_audio = background_audio.subclip(start_time_audio, end_time_audio) background_audio = background_audio.subclipped(start_time_audio, end_time_audio)
background_audio.write_audiofile(f"assets/temp/{id}/background.mp3") background_audio.write_audiofile(f"assets/temp/{thread_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]}"
@ -149,17 +150,18 @@ def chop_background(background_config: Dict[str, Tuple], video_length: int, redd
) )
# Extract video subclip # Extract video subclip
try: try:
with VideoFileClip(f"assets/backgrounds/video/{video_choice}") as video:
new = video.subclipped(start_time_video, end_time_video)
new.write_videofile(f"assets/temp/{thread_id}/background.mp4")
except (OSError, IOError): # ffmpeg issue see #348
print_substep("FFMPEG issue. Trying again...")
ffmpeg_extract_subclip( ffmpeg_extract_subclip(
f"assets/backgrounds/video/{video_choice}", f"assets/backgrounds/video/{video_choice}",
start_time_video, start_time_video,
end_time_video, end_time_video,
targetname=f"assets/temp/{id}/background.mp4", outputfile=f"assets/temp/{thread_id}/background.mp4",
) )
except (OSError, IOError): # ffmpeg issue see #348
print_substep("FFMPEG issue. Trying again...")
with VideoFileClip(f"assets/backgrounds/video/{video_choice}") as video:
new = video.subclip(start_time_video, end_time_video)
new.write_videofile(f"assets/temp/{id}/background.mp4")
print_substep("Background video chopped successfully!", style="bold green") print_substep("Background video chopped successfully!", style="bold green")
return background_config["video"][2] return background_config["video"][2]

@ -93,7 +93,7 @@ def prepare_background(reddit_id: str, W: int, H: int) -> str:
output_path, output_path,
an=None, an=None,
**{ **{
"c:v": "h264", "c:v": "h264_nvenc",
"b:v": "20M", "b:v": "20M",
"b:a": "192k", "b:a": "192k",
"threads": multiprocessing.cpu_count(), "threads": multiprocessing.cpu_count(),
@ -438,7 +438,7 @@ def make_final_video(
path, path,
f="mp4", f="mp4",
**{ **{
"c:v": "h264", "c:v": "h264_nvenc",
"b:v": "20M", "b:v": "20M",
"b:a": "192k", "b:a": "192k",
"threads": multiprocessing.cpu_count(), "threads": multiprocessing.cpu_count(),
@ -468,7 +468,7 @@ def make_final_video(
path, path,
f="mp4", f="mp4",
**{ **{
"c:v": "h264", "c:v": "h264_nvenc",
"b:v": "20M", "b:v": "20M",
"b:a": "192k", "b:a": "192k",
"threads": multiprocessing.cpu_count(), "threads": multiprocessing.cpu_count(),

Loading…
Cancel
Save