mirror of
https://github.com/Paillat-dev/viralfactory.git
synced 2026-01-02 09:16:19 +00:00
Support for upgraded moviepy
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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="",
|
||||
)
|
||||
]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user