Files changed (1) hide show
  1. app.py +70 -79
app.py CHANGED
@@ -14,90 +14,81 @@ def install_imagemagick():
14
 
15
  install_imagemagick()
16
 
17
- import gradio as gr
18
- import os
19
- from moviepy.editor import VideoFileClip, CompositeVideoClip, ImageClip
20
- from PIL import Image, ImageDraw, ImageFont
21
-
22
- def create_text_clip(text, fontsize=70, color='white', size=(1080, 1920)):
23
- font = ImageFont.truetype("arial.ttf", fontsize)
24
- img = Image.new('RGBA', size, (0, 0, 0, 0))
25
  draw = ImageDraw.Draw(img)
 
 
26
  w, h = draw.textbbox((0, 0), text, font=font)[2:]
27
  draw.text(((size[0] - w) / 2, (size[1] - h) / 2), text, font=font, fill=color)
28
- return img
29
-
30
- def process_video(video_file, text):
31
- # Convert video_file string path to a file object and then extract the path
32
- video_path = video_file.name if isinstance(video_file, gr.inputs.File) else video_file
33
-
34
- if not os.path.isfile(video_path):
35
- raise FileNotFoundError(f"The file {video_path} does not exist.")
36
-
37
- video = VideoFileClip(video_path)
38
-
39
- # Calculate new width to maintain the 9:16 aspect ratio
40
- new_width = int(video.h * 9 / 16)
41
-
42
- # Resize video to maintain 9:16 aspect ratio
43
- video = video.resize(width=new_width)
44
-
45
- # Create a text image
46
- text_img = create_text_clip(text, fontsize=70, color='white', size=(new_width, video.h))
47
-
48
- # Convert the text image to an ImageClip
49
- text_clip = ImageClip(text_img).set_duration(video.duration)
50
-
51
- # Composite the video with the text clip
 
 
 
 
52
  final_clip = CompositeVideoClip([video, text_clip])
53
-
54
- # Save the final video
55
- output_path = "/mnt/data/output_video.mp4"
56
- final_clip.write_videofile(output_path, codec="libx264", fps=24)
57
-
58
  return output_path
59
-
60
- # Additional inputs for the chat interface
61
- additional_inputs = [
62
- gr.Dropdown(choices=["llama3-70b-8192", "llama3-8b-8192", "mixtral-8x7b-32768", "gemma-7b-it"], value="llama3-70b-8192", label="Model"),
63
- 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."),
64
- 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."),
65
- 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."),
66
- gr.Number(precision=0, value=42, label="Seed", info="A starting point to initiate generation, use 0 for random")
67
- ]
68
-
69
- # Gradio interface with blocks and tabs
70
- # Chat Interface
71
- def create_chat_interface():
72
- return gr.ChatInterface(
73
  fn=generate_response,
74
- chatbot=gr.Chatbot(
75
- show_label=False,
76
- show_share_button=False,
77
- show_copy_button=True,
78
- likeable=True,
79
- layout="panel"
80
- ),
81
- additional_inputs=additional_inputs,
82
- title="YTSHorts Maker",
83
- description="Powered by GROQ, MoviePy, and other tools."
 
 
 
 
 
 
 
 
 
 
 
 
84
  )
85
 
86
- # Main app definition
87
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="red", secondary_hue="pink")) as demo:
88
- with gr.Tabs():
89
- # Chat Ta
90
- with gr.TabItem("Video Processing"):
91
- text_input = gr.Textbox(lines=5, label="Text (8 words max per line)")
92
- process_button = gr.Button("Process Video")
93
- video_output = gr.Video(label="Processed Video")
94
-
95
- process_button.click(
96
- fn=process_video,
97
- inputs=text_input,
98
- outputs=video_output,
99
- )
100
-
101
- # Launch the Gradio interface
102
- if __name__ == "__main__":
103
- demo.launch()
 
14
 
15
  install_imagemagick()
16
 
17
+ def create_text_clip(text, fontsize, color, size):
18
+ img = Image.new('RGB', size, color='black')
 
 
 
 
 
 
19
  draw = ImageDraw.Draw(img)
20
+ font_path = "arial.ttf" # Make sure this file is in the root directory of your space
21
+ font = ImageFont.truetype(font_path, fontsize)
22
  w, h = draw.textbbox((0, 0), text, font=font)[2:]
23
  draw.text(((size[0] - w) / 2, (size[1] - h) / 2), text, font=font, fill=color)
24
+ return np.array(img)
25
+
26
+ def process_video(text):
27
+ video_folder = "videos"
28
+ video_files = [os.path.join(video_folder, f) for f in os.listdir(video_folder) if f.endswith(('mp4', 'mov', 'avi', 'mkv'))]
29
+ if not video_files:
30
+ raise FileNotFoundError("No video files found in the specified directory.")
31
+
32
+ selected_video = random.choice(video_files)
33
+ video = VideoFileClip(selected_video)
34
+ start_time = random.uniform(0, max(0, video.duration - 60))
35
+ video = video.subclip(start_time, min(start_time + 60, video.duration))
36
+
37
+ def resize_image(image, new_size):
38
+ pil_image = Image.fromarray(image)
39
+ resized_pil = pil_image.resize(new_size[::-1], Image.LANCZOS)
40
+ return np.array(resized_pil)
41
+
42
+ new_size = (1080, int(video.h * (1080 / video.w)))
43
+ video = video.fl_image(lambda image: resize_image(image, new_size))
44
+ video = video.crop(x1=video.w // 2 - 540, x2=video.w // 2 + 540)
45
+
46
+ text_lines = text.split()
47
+ text = "\n".join([" ".join(text_lines[i:i+8]) for i in range(0, len(text_lines), 8)])
48
+
49
+ text_img = create_text_clip(text, fontsize=70, color='white', size=video.size)
50
+ text_clip = ImageClip(text_img).set_duration(video.duration).set_position(('center', 'center')).set_opacity(0.5)
51
+
52
  final_clip = CompositeVideoClip([video, text_clip])
53
+
54
+ output_path = "output.mp4"
55
+ final_clip.write_videofile(output_path, codec="libx264")
56
+
 
57
  return output_path
58
+
59
+ def chat_interface():
60
+ return gr.Interface(
 
 
 
 
 
 
 
 
 
 
 
61
  fn=generate_response,
62
+ inputs=[
63
+ gr.Textbox(label="Prompt"),
64
+ gr.Textbox(label="History", type="text"),
65
+ gr.Dropdown(choices=["llama3-70b-8192", "llama3-8b-8192", "mixtral-8x7b-32768", "gemma-7b-it"], label="Model"),
66
+ gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Temperature"),
67
+ gr.Slider(minimum=1, maximum=32192, step=1, label="Max Tokens"),
68
+ gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Top P"),
69
+ gr.Number(precision=0, label="Seed")
70
+ ],
71
+ outputs=gr.Textbox(label="Response"),
72
+ title="YTSHorts Maker - Chat Interface",
73
+ description="Powered by GROQ.",
74
+ live=True
75
+ )
76
+
77
+ def process_video_interface():
78
+ return gr.Interface(
79
+ fn=process_video,
80
+ inputs=gr.Textbox(label="Text (8 words max per line)"),
81
+ outputs=gr.Video(label="Processed Video"),
82
+ title="YTSHorts Maker - Video Processing",
83
+ description="Select a video file from 'videos' folder, add text, and process.",
84
  )
85
 
86
+ demo = gr.Interface(
87
+ fn=None,
88
+ interfaces=[chat_interface(), process_video_interface()],
89
+ title="YTSHorts Maker",
90
+ description="Powered by GROQ, MoviePy, and other tools.",
91
+ theme="soft",
92
+ )
93
+
94
+ demo.launch()