ShortsAutomator / app.py
TIMBOVILL's picture
Update app.py
8b87f76 verified
raw
history blame
4.23 kB
import os
import random
import gradio as gr
from groq import Groq
from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import subprocess
# Ensure ImageMagick is installed
def install_imagemagick():
if not os.path.exists('/usr/bin/convert'):
subprocess.run(['apt-get', 'update'])
subprocess.run(['apt-get', 'install', '-y', 'imagemagick'])
install_imagemagick()
def create_text_clip(text, fontsize, color, size):
img = Image.new('RGB', size, color='black')
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("arial.ttf", fontsize)
w, h = draw.textsize(text, font=font)
draw.text(((size[0] - w) / 2, (size[1] - h) / 2), text, font=font, fill=color)
return np.array(img)
def process_video(text):
video_folder = "videos"
video_files = [os.path.join(video_folder, f) for f in os.listdir(video_folder) if f.endswith(('mp4', 'mov', 'avi', 'mkv'))]
if not video_files:
raise FileNotFoundError("No video files found in the specified directory.")
selected_video = random.choice(video_files)
video = VideoFileClip(selected_video)
start_time = random.uniform(0, max(0, video.duration - 60))
video = video.subclip(start_time, min(start_time + 60, video.duration))
def resize_image(image, new_size):
pil_image = Image.fromarray(image)
resized_pil = pil_image.resize(new_size[::-1], Image.LANCZOS)
return np.array(resized_pil)
new_size = (1080, int(video.h * (1080 / video.w)))
video = video.fl_image(lambda image: resize_image(image, new_size))
video = video.crop(x1=video.w // 2 - 540, x2=video.w // 2 + 540)
text_lines = text.split()
text = "\n".join([" ".join(text_lines[i:i+8]) for i in range(0, len(text_lines), 8)])
text_img = create_text_clip(text, fontsize=70, color='white', size=video.size)
text_clip = TextClip(img=text_img, size=video.size, duration=video.duration)
final = CompositeVideoClip([video, text_clip])
output_path = "output.mp4"
final.write_videofile(output_path, codec="libx264")
return output_path
# Additional inputs for the chat interface
additional_inputs = [
gr.Dropdown(choices=["llama3-70b-8192", "llama3-8b-8192", "mixtral-8x7b-32768", "gemma-7b-it"], value="llama3-70b-8192", label="Model"),
gr.Slider(minimum=0.0, maximum=1.0, step=0.01, value=0.5, label="Temperature", info="Controls diversity of the generated text. Lower is more deterministic, higher is more creative."),
gr.Slider(minimum=1, maximum=32192, step=1, value=4096, label="Max Tokens", info="The maximum number of tokens that the model can process in a single response.<br>Maximums: 8k for gemma 7b, llama 7b & 70b, 32k for mixtral 8x7b."),
gr.Slider(minimum=0.0, maximum=1.0, step=0.01, value=0.5, label="Top P", info="A method of text generation where a model will only consider the most probable next tokens that make up the probability p."),
gr.Number(precision=0, value=42, label="Seed", info="A starting point to initiate generation, use 0 for random")
]
# Gradio interface with blocks and tabs
# Chat Interface
def create_chat_interface():
return gr.ChatInterface(
fn=generate_response,
chatbot=gr.Chatbot(
show_label=False,
show_share_button=False,
show_copy_button=True,
likeable=True,
layout="panel"
),
additional_inputs=additional_inputs,
title="YTSHorts Maker",
description="Powered by GROQ, MoviePy, and other tools."
)
# Main app definition
with gr.Blocks(theme=gr.themes.Soft(primary_hue="red", secondary_hue="pink")) as demo:
with gr.Tabs():
# Chat Ta
with gr.TabItem("Video Processing"):
text_input = gr.Textbox(lines=5, label="Text (8 words max per line)")
process_button = gr.Button("Process Video")
video_output = gr.Video(label="Processed Video")
process_button.click(
fn=process_video,
inputs=text_input,
outputs=video_output,
)
# Launch the Gradio interface
if __name__ == "__main__":
demo.launch()