Support for upgraded moviepy

This commit is contained in:
2024-03-02 15:19:30 +01:00
parent 6b6b18507a
commit 455514e475
13 changed files with 87 additions and 68 deletions

View File

@@ -4,7 +4,7 @@ google_auth_oauthlib==1.2.0
Google_Images_Search==1.4.6
gradio==4.19.0
httplib2==0.22.0
moviepy==1.0.3
git+https://github.com/OsaAjani/moviepy.git
openai==1.13.3
orjson==3.9.15
protobuf==4.25.3
@@ -14,8 +14,7 @@ PyYAML==6.0.1
Requests==2.31.0
SQLAlchemy==2.0.27
git+https://github.com/Paillat-dev/tiktok-uploader.git
torch==2.2.0
TTS==0.22.0
TTS==0.22.0
whisper_timestamped==1.14.4
Pillow==9.5.0

View File

@@ -3,7 +3,7 @@ import time
from datetime import datetime
import gradio
import moviepy.editor as mp
import moviepy as mp
from .. import engines
from ..models import Video, SessionLocal
@@ -171,10 +171,10 @@ class GenerationContext:
*self.index_8,
*self.index_9,
]
clip = mp.CompositeVideoClip(clips, size=(self.width, self.height))
audio = mp.CompositeAudioClip(self.audio)
clip.set_duration(self.duration)
clip: mp.CompositeVideoClip = clip.set_audio(audio)
clip = mp.CompositeVideoClip(clips, size=(self.width, self.height)).with_duration(self.duration).with_audio(
audio
)
clip.write_videofile(self.get_file_path("final.mp4"), fps=60, threads=4, codec="h264_nvenc")
self.progress(0.8, "Generating metadata...")
@@ -192,7 +192,5 @@ class GenerationContext:
self.store_in_db()
self.progress(1, "Done!")
if os.name == 'nt':
os.system(f"start {os.path.abspath(self.dir)}")
else:
os.system(f"open {self.dir}")
command = "start" if os.name == 'nt' else "open"
os.system(f"{command} {os.path.abspath(self.dir)}")

View File

@@ -2,11 +2,11 @@ import os
from typing import Literal, TypedDict, List
import gradio as gr
import moviepy.editor as mp
import moviepy as mp
import moviepy.video.fx as vfx
import openai
from openai import OpenAI
import requests
from moviepy.video.fx.resize import resize
from . import BaseAssetsEngine
@@ -79,15 +79,11 @@ class DallEAssetsEngine(BaseAssetsEngine):
img = mp.ImageClip("temp.png")
os.remove("temp.png")
img: mp.ImageClip = img.set_duration(end - start)
img: mp.ImageClip = img.set_start(start)
img: mp.ImageClip = resize(img, width=max_width)
if self.aspect_ratio == "portrait":
img: mp.ImageClip = img.set_position(("center", "top"))
elif self.aspect_ratio == "landscape":
img: mp.ImageClip = img.set_position(("center", "top"))
elif self.aspect_ratio == "square":
img: mp.ImageClip = img.set_position(("center", "top"))
img: mp.ImageClip = img.with_duration(end - start)
img: mp.ImageClip = img.with_start(start)
img: mp.ImageClip = img.with_effects([vfx.Resize(width=max_width)])
position = img.with_position(("center", "top"))
img: mp.ImageClip = img.with_position(position)
clips.append(img)
return clips

View File

@@ -3,10 +3,10 @@ import shutil
from typing import TypedDict
import gradio as gr
import moviepy.editor as mp
from google_images_search import GoogleImagesSearch
from moviepy.video.fx.resize import resize
import moviepy as mp
import moviepy.video.fx as vfx
from google_images_search import GoogleImagesSearch
from . import BaseAssetsEngine
@@ -38,7 +38,7 @@ class GoogleAssetsEngine(BaseAssetsEngine):
super().__init__()
def generate(self, options: list[Spec]) -> list[mp.ImageClip]:
max_width = self.ctx.width / 3 * 2
max_width = int(self.ctx.width / 3 * 2)
clips = []
for option in options:
query = option["query"]
@@ -61,13 +61,11 @@ class GoogleAssetsEngine(BaseAssetsEngine):
# delete the temp folder
except Exception as e:
print(e)
continue
finally:
shutil.rmtree("temp")
img: mp.ImageClip = img.set_duration(end - start)
img: mp.ImageClip = img.set_start(start)
img: mp.ImageClip = resize(img, width=max_width)
img: mp.ImageClip = img.set_position(("center", "top"))
img = img.with_duration(end - start).with_start(start).with_effects([vfx.Resize(width=max_width)]).with_position(("center", "top"))
clips.append(img)
return clips

View File

@@ -4,9 +4,8 @@ import shutil
import time
import gradio as gr
import moviepy.editor as mp
from moviepy.audio.fx.audio_fadein import audio_fadein
from moviepy.audio.fx.audio_fadeout import audio_fadeout
import moviepy as mp
import moviepy.audio.fx as afx
from . import BaseAudioBackgroundEngine
@@ -43,18 +42,18 @@ class MusicAudioBackgroundEngine(BaseAudioBackgroundEngine):
background = mp.AudioFileClip(f"{self.background_audio.path}")
self.ctx.credits += f"\n{self.background_audio.data['credits']}"
# we add fade in and fade out to the audio
background: mp.AudioFileClip = background.fx(audio_fadein, 1).fx(audio_fadeout, 1)
background = background.with_effects([afx.AudioFadeIn(1), afx.AudioFadeOut(1)])
# loop the audio to match the duration of the video
audio_clips = []
while sum([clip.duration for clip in audio_clips]) < self.ctx.duration:
audio_clips.append(background)
# now we cut the audio to match the duration of the video exactly
audio: mp.AudioFileClip = mp.concatenate_audioclips(audio_clips)
audio: mp.AudioFileClip = audio.subclip(0, self.ctx.duration)
audio = mp.concatenate_audioclips(audio_clips)
audio = audio.with_subclip(0, self.ctx.duration)
# finally we add a new fade OUT only to the audio
audio: mp.AudioFileClip = audio.fx(audio_fadeout, 1)
audio = audio.with_effects([afx.AudioFadeOut(1)])
# change volume to 0.5
audio: mp.AudioFileClip = audio.volumex(0.5)
audio: mp.AudioFileClip = audio.with_multiply_volume(0.5)
self.ctx.audio.append(audio)
@classmethod

View File

@@ -4,9 +4,8 @@ import shutil
import time
import gradio as gr
import moviepy.editor as mp
from moviepy.video.fx.crop import crop
from moviepy.video.fx.resize import resize
import moviepy as mp
import moviepy.video.fx as vfx
from . import BaseBackgroundEngine
@@ -47,14 +46,16 @@ class VideoBackgroundEngine(BaseBackgroundEngine):
"The background video is shorter than the video to be generated."
)
start = random.uniform(0, background_max_start)
clip = background.subclip(start, start + self.ctx.duration)
clip = background.with_subclip(start, start + self.ctx.duration)
self.ctx.credits += f"\n{self.background_video.data['credits']}"
clip = resize(clip, width=self.ctx.width, height=self.ctx.height)
w, h = clip.size
if w > h:
clip = crop(clip, width=self.ctx.width, height=self.ctx.height, x_center=w / 2, y_center=h / 2)
resolution: float = w / h
canvas_resolution: float = self.ctx.width / self.ctx.height
if resolution > canvas_resolution:
clip = clip.with_effects([vfx.Resize(height=self.ctx.height)])
else:
clip = crop(clip, width=self.ctx.width, height=self.ctx.height, x_center=w / 2, y_center=h / 2)
clip = clip.with_effects([vfx.Resize(width=self.ctx.width)])
clip = clip.with_position(("center", "center"))
self.ctx.index_0.append(clip)
@classmethod

View File

@@ -1,6 +1,6 @@
from abc import ABC, abstractmethod
import moviepy.editor as mp
import moviepy as mp
from sqlalchemy.future import select
from ..chore import GenerationContext

View File

@@ -1,10 +1,37 @@
import gradio as gr
import os
import shutil
from moviepy.editor import TextClip
import platform
import moviepy as mp
from . import BaseCaptioningEngine
def get_available_fonts():
#on windows, the fonts are in the C:\Windows\Fonts and C:\Users\Username\AppData\Local\Microsoft\Windows\Fonts
#on linux, the fonts are in the /usr/share/fonts directory
#on mac, the fonts are in the /Library/Fonts, /System/Library/Fonts, and ~/Library/Fonts directories
if platform.system() == "Windows":
font_dirs = [
"C:\\Windows\\Fonts",
"C:\\Users\\{}\\AppData\\Local\\Microsoft\\Windows\\Fonts".format(os.getlogin()),
]
elif platform.system() == "Linux":
font_dirs = ["/usr/share/fonts"]
elif platform.system() == "Darwin":
font_dirs = [
"/Library/Fonts",
"/System/Library/Fonts",
"{}/Library/Fonts".format(os.path.expanduser("~")),
]
else:
font_dirs = []
fonts = []
for font_dir in font_dirs:
for root, dirs, files in os.walk(font_dir):
for file in files:
if file.endswith(".ttf") or file.endswith(".otf"):
fonts.append(file)
return list(set(fonts))
class SimpleCaptioningEngine(BaseCaptioningEngine):
name = "SimpleCaptioningEngine"
@@ -20,21 +47,22 @@ class SimpleCaptioningEngine(BaseCaptioningEngine):
super().__init__()
def build_caption_object(self, text: str, start: float, end: float) -> TextClip:
def build_caption_object(self, text: str, start: float, end: float) -> mp.TextClip:
return (
TextClip(
text,
fontsize=self.font_size,
mp.TextClip(
text=text,
font_size=self.font_size,
color=self.font_color,
font=self.font,
stroke_color=self.stroke_color,
stroke_width=self.stroke_width,
method="caption",
size=(self.ctx.width / 3 * 2, None),
size=(int(self.ctx.width / 3 * 2), None),
text_align="center",
)
.set_position(("center", 0.65), relative=True)
.set_start(start)
.set_duration(end - start)
.with_position(("center", 0.65), relative=True)
.with_start(start)
.with_duration(end - start)
)
def ends_with_punctuation(self, text: str) -> bool:
@@ -95,7 +123,7 @@ class SimpleCaptioningEngine(BaseCaptioningEngine):
with gr.Group():
font = gr.Dropdown(
label="Font",
choices=TextClip.list("font"),
choices=get_available_fonts(),
value="Comic-Sans-MS-Bold",
allow_custom_value=True, # Allow custom font
)

View File

@@ -19,8 +19,8 @@ class CustomScriptEngine(BaseScriptEngine):
def get_options(cls) -> list:
return [
gr.Textbox(
label="Prompt",
placeholder="Enter your prompt here",
label="Script",
placeholder="Enter your script here",
value="",
)
]

View File

@@ -7,7 +7,7 @@ from ...utils.prompting import get_prompt
class ScientificFactsScriptEngine(BaseScriptEngine):
name = "Scientific facts Thoughts"
name = "Scientific facts"
description = "Generate a scientific facts script."
num_options = 1

View File

@@ -1,7 +1,7 @@
from abc import abstractmethod
from typing import TypedDict
import moviepy.editor as mp
import moviepy as mp
import whisper_timestamped as wt
from torch.cuda import is_available

View File

@@ -89,7 +89,7 @@ class CoquiTTSEngine(BaseTTSEngine):
"ko", # Korean
"hi", # Hindi
]
num_options = 4
num_options = 5
def __init__(self, options: list):
super().__init__()
@@ -99,7 +99,7 @@ class CoquiTTSEngine(BaseTTSEngine):
self.to_force_duration = options[2]
self.duration = options[3]
os.environ["COQUI_TOS_AGREED"] = options[4]
os.environ["COQUI_TOS_AGREED"] = str(options[4])
try:
self.tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2")
except:

View File

@@ -25,7 +25,9 @@ class TikTokUploadEngine(BaseUploadEngine):
description: str = self.ctx.description
hashtags = self.hashtags.strip().split(" ")
# extract any hashtags from the description / title and remove them from the description
title = title.strip()
description = description.strip()
#we get all the hastags from title and description and add them to the list of hashtags, while removing them from the title and description
for word in title.split():
if word.startswith("#"):
hashtags.append(word)
@@ -35,12 +37,10 @@ class TikTokUploadEngine(BaseUploadEngine):
hashtags.append(word)
description = description.replace(word, "")
title = title.strip()
description = description.strip()
hashtags_str = " ".join(hashtags) + " " if hashtags else ""
failed = upload_video(
filename=self.ctx.get_file_path("final.mp4"),
description=f"{title}\n{description} {hashtags_str}",
description=f"{title} {hashtags_str}\n{description}",
cookies_str=cookies,
browser="chrome",
comment=True, stitch=False, duet=False