MadhavRupala commited on
Commit
f548b8e
·
verified ·
1 Parent(s): 3326cc0

Upload 4 files

Browse files
Files changed (4) hide show
  1. README.md +74 -26
  2. app.py +280 -65
  3. gitignore +37 -2
  4. requirements.txt +2 -0
README.md CHANGED
@@ -1,7 +1,7 @@
1
  ---
2
- title: Image Processing Studio
3
- emoji: 🎨
4
- colorFrom: blue
5
  colorTo: purple
6
  sdk: gradio
7
  sdk_version: 4.44.0
@@ -10,34 +10,82 @@ pinned: false
10
  license: mit
11
  ---
12
 
13
- # Image Processing Studio
14
 
15
- A fast and simple image processing app built with Gradio. Apply various effects to your images:
16
 
17
- - **Grayscale** - Convert to black and white
18
- - **Blur** - Apply Gaussian blur
19
- - **Sharpen** - Enhance image sharpness
20
- - **Brightness** - Adjust brightness levels
21
- - **Contrast** - Modify contrast
22
- - **Sepia** - Apply vintage sepia tone
23
 
24
- ## How to Use
 
 
 
25
 
26
- 1. Upload an image
27
- 2. Select an effect
28
- 3. Adjust the intensity slider
29
- 4. Click "Apply Effect"
 
 
 
 
 
30
 
31
- ## Local Development
32
 
33
- ```bash
34
- pip install -r requirements.txt
35
- python app.py
36
- ```
 
37
 
38
- ## Deploy to Hugging Face Spaces
 
 
 
 
 
39
 
40
- 1. Create a new Space on [Hugging Face](https://huggingface.co/new-space)
41
- 2. Choose Gradio as SDK
42
- 3. Upload these files: `app.py`, `requirements.txt`, `README.md`
43
- 4. Your Space will automatically build and deploy!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: AI Video Ad Generator
3
+ emoji: 🎬
4
+ colorFrom: indigo
5
  colorTo: purple
6
  sdk: gradio
7
  sdk_version: 4.44.0
 
10
  license: mit
11
  ---
12
 
13
+ # 🎬 AI Video Ad Generator
14
 
15
+ Create professional video advertisements with AI-generated images and custom text overlays in seconds!
16
 
17
+ ## Features
 
 
 
 
 
18
 
19
+ ### 🎨 AI Image Generation
20
+ - Generate high-quality images using Stable Diffusion XL
21
+ - Perfect for product ads, social media posts, and marketing materials
22
+ - Simple prompt-based generation
23
 
24
+ ### 🎥 Video Ad Creation
25
+ - Upload multiple images or use AI-generated ones
26
+ - Add custom text overlays for each slide
27
+ - Multiple transition effects (Fade, Slide, Zoom)
28
+ - Multiple output formats:
29
+ - 1920x1080 (Full HD)
30
+ - 1280x720 (HD)
31
+ - 1080x1920 (Instagram Story)
32
+ - 1080x1080 (Instagram Square)
33
 
34
+ ## 🚀 How to Use
35
 
36
+ ### Step 1: Generate Images (Optional)
37
+ 1. Get your Hugging Face API token from [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
38
+ 2. Enter the token and describe your desired image
39
+ 3. Click "Generate Image"
40
+ 4. Download or use directly in video creation
41
 
42
+ ### Step 2: Create Video Ad
43
+ 1. Upload your images (or use generated ones)
44
+ 2. Add text for each slide (one line per slide)
45
+ 3. Choose duration, transition effect, and output size
46
+ 4. Click "Create Video Ad"
47
+ 5. Download your video!
48
 
49
+ ## 📋 Example Prompts
50
+
51
+ - "Modern smartphone on wooden desk, professional photography, 4K"
52
+ - "Delicious pizza with fresh ingredients, food photography, top view"
53
+ - "Luxury car in city at sunset, cinematic lighting"
54
+ - "Happy family using laptop at home, lifestyle photography"
55
+
56
+ ## 🛠️ Technical Details
57
+
58
+ - **AI Model**: Stable Diffusion XL Base 1.0
59
+ - **Video Processing**: OpenCV + PIL
60
+ - **Formats**: MP4 (H.264)
61
+ - **FPS**: 30
62
+ - **Transitions**: Smooth interpolation
63
+
64
+ ## 📝 Requirements
65
+
66
+ - Hugging Face API token (free tier available)
67
+ - Images in JPG, PNG format
68
+ - Recommended: 3-5 images for best results
69
+
70
+ ## 🎯 Use Cases
71
+
72
+ - Social media ads
73
+ - Product promotions
74
+ - Event announcements
75
+ - Brand storytelling
76
+ - Instagram/Facebook content
77
+ - YouTube intros
78
+
79
+ ## 🔒 Privacy
80
+
81
+ - No data is stored permanently
82
+ - Videos are generated on-demand
83
+ - Your API token is never saved
84
+
85
+ ## 📄 License
86
+
87
+ MIT License - Feel free to use and modify!
88
+
89
+ ---
90
+
91
+ Made with ❤️ using Gradio and Hugging Face
app.py CHANGED
@@ -1,87 +1,302 @@
1
  import gradio as gr
 
2
  import numpy as np
3
- from PIL import Image, ImageEnhance, ImageFilter
 
 
 
 
 
4
 
5
- def process_image(image, operation, intensity):
6
- """Process image with various operations"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  if image is None:
8
  return None
9
 
10
- img = Image.fromarray(image)
 
11
 
12
- if operation == "Grayscale":
13
- img = img.convert("L").convert("RGB")
 
 
14
 
15
- elif operation == "Blur":
16
- img = img.filter(ImageFilter.GaussianBlur(radius=intensity))
 
 
17
 
18
- elif operation == "Sharpen":
19
- enhancer = ImageEnhance.Sharpness(img)
20
- img = enhancer.enhance(1 + intensity/10)
 
 
 
 
 
 
 
 
21
 
22
- elif operation == "Brightness":
23
- enhancer = ImageEnhance.Brightness(img)
24
- img = enhancer.enhance(1 + intensity/10)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
- elif operation == "Contrast":
27
- enhancer = ImageEnhance.Contrast(img)
28
- img = enhancer.enhance(1 + intensity/10)
29
 
30
- elif operation == "Sepia":
31
- img = img.convert("RGB")
32
- pixels = np.array(img)
33
- tr = 0.393 * pixels[:,:,0] + 0.769 * pixels[:,:,1] + 0.189 * pixels[:,:,2]
34
- tg = 0.349 * pixels[:,:,0] + 0.686 * pixels[:,:,1] + 0.168 * pixels[:,:,2]
35
- tb = 0.272 * pixels[:,:,0] + 0.534 * pixels[:,:,1] + 0.131 * pixels[:,:,2]
36
- pixels[:,:,0] = np.clip(tr, 0, 255)
37
- pixels[:,:,1] = np.clip(tg, 0, 255)
38
- pixels[:,:,2] = np.clip(tb, 0, 255)
39
- img = Image.fromarray(pixels.astype('uint8'))
40
 
41
- return np.array(img)
42
 
43
- # Create Gradio interface
44
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
45
  gr.Markdown("""
46
- # 🎨 Image Processing Studio
47
- Upload an image and apply various effects with adjustable intensity.
48
  """)
49
 
50
- with gr.Row():
51
- with gr.Column():
52
- input_image = gr.Image(label="Upload Image", type="numpy")
53
- operation = gr.Radio(
54
- choices=["Grayscale", "Blur", "Sharpen", "Brightness", "Contrast", "Sepia"],
55
- value="Grayscale",
56
- label="Effect"
57
- )
58
- intensity = gr.Slider(
59
- minimum=0,
60
- maximum=10,
61
- value=5,
62
- step=0.5,
63
- label="Intensity"
64
- )
65
- process_btn = gr.Button("Apply Effect", variant="primary")
 
 
 
 
66
 
67
- with gr.Column():
68
- output_image = gr.Image(label="Processed Image")
69
-
70
- gr.Examples(
71
- examples=[
72
- ["Grayscale", 5],
73
- ["Blur", 3],
74
- ["Sepia", 5],
75
- ["Sharpen", 7],
76
- ],
77
- inputs=[operation, intensity],
78
- )
 
 
 
79
 
80
- process_btn.click(
81
- fn=process_image,
82
- inputs=[input_image, operation, intensity],
83
- outputs=output_image
84
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  if __name__ == "__main__":
87
  demo.launch()
 
1
  import gradio as gr
2
+ import cv2
3
  import numpy as np
4
+ from PIL import Image, ImageDraw, ImageFont, ImageFilter
5
+ import requests
6
+ import io
7
+ import os
8
+ from datetime import datetime
9
+ import json
10
 
11
+ # Hugging Face API configuration
12
+ HF_API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
13
+
14
+ def generate_ai_image(prompt, hf_token):
15
+ """Generate image using Hugging Face Stable Diffusion"""
16
+ if not hf_token:
17
+ return None, "❌ Please provide your Hugging Face API token"
18
+
19
+ headers = {"Authorization": f"Bearer {hf_token}"}
20
+ payload = {"inputs": prompt}
21
+
22
+ try:
23
+ response = requests.post(HF_API_URL, headers=headers, json=payload, timeout=60)
24
+ if response.status_code == 200:
25
+ image = Image.open(io.BytesIO(response.content))
26
+ return image, "✅ Image generated successfully!"
27
+ else:
28
+ return None, f"❌ Error: {response.status_code} - {response.text}"
29
+ except Exception as e:
30
+ return None, f"❌ Error generating image: {str(e)}"
31
+
32
+ def add_text_to_image(image, text, position, font_size, text_color, bg_opacity):
33
+ """Add text overlay to image"""
34
  if image is None:
35
  return None
36
 
37
+ img = image.copy()
38
+ draw = ImageDraw.Draw(img, 'RGBA')
39
 
40
+ try:
41
+ font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", font_size)
42
+ except:
43
+ font = ImageFont.load_default()
44
 
45
+ # Get text size
46
+ bbox = draw.textbbox((0, 0), text, font=font)
47
+ text_width = bbox[2] - bbox[0]
48
+ text_height = bbox[3] - bbox[1]
49
 
50
+ # Calculate position
51
+ img_width, img_height = img.size
52
+ if position == "Top":
53
+ x = (img_width - text_width) // 2
54
+ y = 50
55
+ elif position == "Center":
56
+ x = (img_width - text_width) // 2
57
+ y = (img_height - text_height) // 2
58
+ else: # Bottom
59
+ x = (img_width - text_width) // 2
60
+ y = img_height - text_height - 50
61
 
62
+ # Draw background rectangle
63
+ padding = 20
64
+ bg_color = (0, 0, 0, int(255 * bg_opacity))
65
+ draw.rectangle(
66
+ [x - padding, y - padding, x + text_width + padding, y + text_height + padding],
67
+ fill=bg_color
68
+ )
69
+
70
+ # Draw text
71
+ color_map = {
72
+ "White": (255, 255, 255),
73
+ "Black": (0, 0, 0),
74
+ "Red": (255, 0, 0),
75
+ "Blue": (0, 100, 255),
76
+ "Yellow": (255, 255, 0)
77
+ }
78
+ draw.text((x, y), text, font=font, fill=color_map.get(text_color, (255, 255, 255)))
79
+
80
+ return img
81
+
82
+ def create_video_ad(images, texts, duration_per_slide, transition_type, output_size, hf_token):
83
+ """Create video ad from images with text overlays"""
84
+ if not images or len(images) == 0:
85
+ return None, "❌ Please provide at least one image"
86
+
87
+ # Parse output size
88
+ size_map = {
89
+ "1920x1080 (Full HD)": (1920, 1080),
90
+ "1280x720 (HD)": (1280, 720),
91
+ "1080x1920 (Instagram Story)": (1080, 1920),
92
+ "1080x1080 (Instagram Square)": (1080, 1080)
93
+ }
94
+ width, height = size_map[output_size]
95
+
96
+ # Video settings
97
+ fps = 30
98
+ frames_per_slide = int(duration_per_slide * fps)
99
+ transition_frames = 15 # 0.5 seconds
100
+
101
+ # Create video writer
102
+ output_path = f"/tmp/video_ad_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
103
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
104
+ out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
105
+
106
+ total_slides = len(images)
107
+
108
+ # Split texts by newline
109
+ text_list = [t.strip() for t in texts.split('\n') if t.strip()]
110
+
111
+ for idx, img_input in enumerate(images):
112
+ # Handle both file paths and PIL images
113
+ if isinstance(img_input, str):
114
+ img = Image.open(img_input).convert('RGB')
115
+ else:
116
+ img = img_input.convert('RGB')
117
+
118
+ # Resize image
119
+ img = img.resize((width, height), Image.Resampling.LANCZOS)
120
+
121
+ # Add text overlay if available
122
+ if idx < len(text_list) and text_list[idx]:
123
+ overlay = Image.new('RGBA', img.size, (0, 0, 0, 0))
124
+ draw = ImageDraw.Draw(overlay)
125
+
126
+ try:
127
+ font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 60)
128
+ except:
129
+ font = ImageFont.load_default()
130
+
131
+ # Draw text in center
132
+ text = text_list[idx]
133
+ bbox = draw.textbbox((0, 0), text, font=font)
134
+ text_width = bbox[2] - bbox[0]
135
+ text_height = bbox[3] - bbox[1]
136
+ x = (width - text_width) // 2
137
+ y = (height - text_height) // 2
138
+
139
+ # Background
140
+ padding = 30
141
+ draw.rectangle(
142
+ [x - padding, y - padding, x + text_width + padding, y + text_height + padding],
143
+ fill=(0, 0, 0, 180)
144
+ )
145
+ draw.text((x, y), text, font=font, fill=(255, 255, 255))
146
+
147
+ img = Image.alpha_composite(img.convert('RGBA'), overlay).convert('RGB')
148
+
149
+ # Write main frames
150
+ for _ in range(frames_per_slide - transition_frames):
151
+ frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
152
+ out.write(frame)
153
+
154
+ # Add transition
155
+ if idx < total_slides - 1:
156
+ next_img_input = images[idx + 1]
157
+ if isinstance(next_img_input, str):
158
+ next_img = Image.open(next_img_input).convert('RGB')
159
+ else:
160
+ next_img = next_img_input.convert('RGB')
161
+ next_img = next_img.resize((width, height), Image.Resampling.LANCZOS)
162
+
163
+ for t in range(transition_frames):
164
+ alpha = t / transition_frames
165
+
166
+ if transition_type == "Fade":
167
+ blended = Image.blend(img, next_img, alpha)
168
+ elif transition_type == "Slide Left":
169
+ offset = int(width * alpha)
170
+ blended = Image.new('RGB', (width, height))
171
+ blended.paste(img, (-offset, 0))
172
+ blended.paste(next_img, (width - offset, 0))
173
+ elif transition_type == "Zoom In":
174
+ scale = 1 + alpha * 0.3
175
+ scaled = img.resize((int(width * scale), int(height * scale)), Image.Resampling.LANCZOS)
176
+ x_offset = (scaled.width - width) // 2
177
+ y_offset = (scaled.height - height) // 2
178
+ cropped = scaled.crop((x_offset, y_offset, x_offset + width, y_offset + height))
179
+ blended = Image.blend(cropped, next_img, alpha * 0.5)
180
+ else:
181
+ blended = next_img
182
+
183
+ frame = cv2.cvtColor(np.array(blended), cv2.COLOR_RGB2BGR)
184
+ out.write(frame)
185
 
186
+ out.release()
 
 
187
 
188
+ # Get file size
189
+ file_size = os.path.getsize(output_path) / (1024 * 1024) # MB
 
 
 
 
 
 
 
 
190
 
191
+ return output_path, f"✅ Video created! {total_slides} slides, {duration_per_slide}s each, {file_size:.2f} MB"
192
 
193
+ # Gradio Interface
194
+ with gr.Blocks(theme=gr.themes.Soft(), title="AI Video Ad Generator") as demo:
195
  gr.Markdown("""
196
+ # 🎬 AI Video Ad Generator
197
+ Create professional video ads with AI-generated images and custom text overlays.
198
  """)
199
 
200
+ with gr.Tab("🎨 Generate Images"):
201
+ gr.Markdown("### Generate AI Images for Your Video Ad")
202
+ with gr.Row():
203
+ with gr.Column():
204
+ hf_token_gen = gr.Textbox(
205
+ label="Hugging Face API Token",
206
+ placeholder="hf_...",
207
+ type="password",
208
+ info="Get your token from https://huggingface.co/settings/tokens"
209
+ )
210
+ image_prompt = gr.Textbox(
211
+ label="Image Prompt",
212
+ placeholder="e.g., Modern smartphone on wooden desk, professional photography",
213
+ lines=3
214
+ )
215
+ generate_btn = gr.Button("🎨 Generate Image", variant="primary", size="lg")
216
+
217
+ with gr.Column():
218
+ generated_image = gr.Image(label="Generated Image", type="pil")
219
+ gen_status = gr.Textbox(label="Status", interactive=False)
220
 
221
+ generate_btn.click(
222
+ fn=generate_ai_image,
223
+ inputs=[image_prompt, hf_token_gen],
224
+ outputs=[generated_image, gen_status]
225
+ )
226
+
227
+ gr.Examples(
228
+ examples=[
229
+ ["Modern luxury car on city street, cinematic lighting, 4K"],
230
+ ["Delicious pizza with fresh ingredients, food photography"],
231
+ ["Smartphone with glowing screen, tech advertisement"],
232
+ ["Happy family using laptop at home, lifestyle photography"],
233
+ ],
234
+ inputs=[image_prompt]
235
+ )
236
 
237
+ with gr.Tab("🎥 Create Video Ad"):
238
+ gr.Markdown("### Upload Images and Create Your Video Ad")
239
+
240
+ with gr.Row():
241
+ with gr.Column():
242
+ input_images = gr.File(
243
+ label="Upload Images",
244
+ file_count="multiple",
245
+ file_types=["image"]
246
+ )
247
+ slide_texts = gr.Textbox(
248
+ label="Text for Each Slide (one per line)",
249
+ placeholder="Slide 1 Text\nSlide 2 Text\nSlide 3 Text",
250
+ lines=5
251
+ )
252
+ duration = gr.Slider(
253
+ minimum=1,
254
+ maximum=10,
255
+ value=3,
256
+ step=0.5,
257
+ label="Duration per Slide (seconds)"
258
+ )
259
+ transition = gr.Radio(
260
+ choices=["Fade", "Slide Left", "Zoom In", "None"],
261
+ value="Fade",
262
+ label="Transition Effect"
263
+ )
264
+ video_size = gr.Radio(
265
+ choices=[
266
+ "1920x1080 (Full HD)",
267
+ "1280x720 (HD)",
268
+ "1080x1920 (Instagram Story)",
269
+ "1080x1080 (Instagram Square)"
270
+ ],
271
+ value="1280x720 (HD)",
272
+ label="Output Size"
273
+ )
274
+ hf_token_video = gr.Textbox(
275
+ label="Hugging Face API Token (optional)",
276
+ placeholder="hf_...",
277
+ type="password"
278
+ )
279
+ create_btn = gr.Button("🎬 Create Video Ad", variant="primary", size="lg")
280
+
281
+ with gr.Column():
282
+ output_video = gr.Video(label="Generated Video Ad")
283
+ video_status = gr.Textbox(label="Status", interactive=False)
284
+
285
+ create_btn.click(
286
+ fn=create_video_ad,
287
+ inputs=[input_images, slide_texts, duration, transition, video_size, hf_token_video],
288
+ outputs=[output_video, video_status]
289
+ )
290
+
291
+ gr.Markdown("""
292
+ ---
293
+ ### 📝 How to Use:
294
+ 1. **Generate Images**: Enter your HuggingFace API token and describe the image you want
295
+ 2. **Create Video**: Upload your images, add text for each slide, and customize settings
296
+ 3. **Download**: Your video will be ready in seconds!
297
+
298
+ 💡 **Tip**: Get a free API token at [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
299
+ """)
300
 
301
  if __name__ == "__main__":
302
  demo.launch()
gitignore CHANGED
@@ -3,9 +3,44 @@ __pycache__/
3
  *$py.class
4
  *.so
5
  .Python
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  env/
7
  venv/
8
- .venv/
9
- *.egg-info/
 
 
 
 
 
 
 
 
 
 
10
  .DS_Store
 
 
 
11
  flagged/
 
 
 
 
 
3
  *$py.class
4
  *.so
5
  .Python
6
+ build/
7
+ develop-eggs/
8
+ dist/
9
+ downloads/
10
+ eggs/
11
+ .eggs/
12
+ lib/
13
+ lib64/
14
+ parts/
15
+ sdist/
16
+ var/
17
+ wheels/
18
+ *.egg-info/
19
+ .installed.cfg
20
+ *.egg
21
+ MANIFEST
22
+
23
+ # Virtual environments
24
  env/
25
  venv/
26
+ ENV/
27
+ env.bak/
28
+ venv.bak/
29
+
30
+ # IDEs
31
+ .vscode/
32
+ .idea/
33
+ *.swp
34
+ *.swo
35
+ *~
36
+
37
+ # OS
38
  .DS_Store
39
+ Thumbs.db
40
+
41
+ # Gradio
42
  flagged/
43
+ /tmp/
44
+
45
+ # Logs
46
+ *.log
requirements.txt CHANGED
@@ -1,3 +1,5 @@
1
  gradio==4.44.0
 
2
  numpy==1.24.3
3
  Pillow==10.0.0
 
 
1
  gradio==4.44.0
2
+ opencv-python-headless==4.8.1.78
3
  numpy==1.24.3
4
  Pillow==10.0.0
5
+ requests==2.31.0