xxparthparekhxx commited on
Commit
3a9977f
·
1 Parent(s): 7aaea12

added all the features

Browse files
Files changed (3) hide show
  1. .gitignore +1 -0
  2. app.py +380 -0
  3. requirements.txt +4 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .venv
app.py ADDED
@@ -0,0 +1,380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import shutil
4
+ import PIL
5
+ from PIL import Image
6
+ import py7zr
7
+ import tarfile
8
+ import zipfile
9
+ import ffmpeg
10
+ from pathlib import Path
11
+ import tempfile
12
+ from PIL import ImageDraw
13
+ def generate_thumbnail(input_video, time_position=0):
14
+ if input_video is None:
15
+ return None
16
+
17
+ temp_dir = tempfile.mkdtemp()
18
+ output_path = os.path.join(temp_dir, "thumbnail.jpg")
19
+
20
+ stream = ffmpeg.input(input_video.name, ss=time_position)
21
+ stream = ffmpeg.output(stream, output_path, vframes=1)
22
+ ffmpeg.run(stream, overwrite_output=True)
23
+
24
+ return output_path
25
+
26
+ def extract_audio(input_video, output_format="mp3"):
27
+ if input_video is None:
28
+ return None
29
+
30
+ temp_dir = tempfile.mkdtemp()
31
+ output_path = os.path.join(temp_dir, f"extracted_audio.{output_format}")
32
+
33
+ stream = ffmpeg.input(input_video.name)
34
+ stream = ffmpeg.output(stream, output_path, acodec='libmp3lame')
35
+ ffmpeg.run(stream, overwrite_output=True)
36
+
37
+ return output_path
38
+
39
+ def trim_video(input_video, start_time, end_time):
40
+ if input_video is None:
41
+ return None
42
+
43
+ temp_dir = tempfile.mkdtemp()
44
+ output_path = os.path.join(temp_dir, "trimmed_video.mp4")
45
+
46
+ stream = ffmpeg.input(input_video.name, ss=start_time, t=end_time-start_time)
47
+ stream = ffmpeg.output(stream, output_path, acodec='copy', vcodec='copy')
48
+ ffmpeg.run(stream, overwrite_output=True)
49
+
50
+ return output_path
51
+
52
+ def crop_image(input_image, x1, y1, x2, y2):
53
+ if input_image is None:
54
+ return None
55
+
56
+ temp_dir = tempfile.mkdtemp()
57
+ img = Image.open(input_image.name)
58
+ cropped = img.crop((x1, y1, x2, y2))
59
+
60
+ output_path = os.path.join(temp_dir, f"cropped_image.{input_image.name.split('.')[-1]}")
61
+ cropped.save(output_path)
62
+
63
+ return output_path
64
+
65
+ def add_watermark(input_image, watermark_text, position="bottom-right"):
66
+ if input_image is None:
67
+ return None
68
+
69
+ temp_dir = tempfile.mkdtemp()
70
+ img = Image.open(input_image.name)
71
+ draw = ImageDraw.Draw(img)
72
+
73
+ # Basic font settings - you can enhance this with custom fonts
74
+ font_size = int(min(img.width, img.height) * 0.05)
75
+ text_width = len(watermark_text) * font_size * 0.6
76
+ text_height = font_size
77
+
78
+ # Position mapping
79
+ positions = {
80
+ "top-left": (10, 10),
81
+ "top-right": (img.width - text_width - 10, 10),
82
+ "bottom-left": (10, img.height - text_height - 10),
83
+ "bottom-right": (img.width - text_width - 10, img.height - text_height - 10)
84
+ }
85
+
86
+ x, y = positions.get(position, positions["bottom-right"])
87
+ draw.text((x, y), watermark_text, fill=(255, 255, 255, 128))
88
+
89
+ output_path = os.path.join(temp_dir, f"watermarked_image.{input_image.name.split('.')[-1]}")
90
+ img.save(output_path)
91
+
92
+ return output_path
93
+
94
+ def convert_image(input_image, output_format, compression_level):
95
+ if input_image is None:
96
+ return None
97
+
98
+ temp_dir = tempfile.mkdtemp()
99
+ output_path = os.path.join(temp_dir, f"converted_image.{output_format.lower()}")
100
+
101
+ img = Image.open(input_image.name)
102
+
103
+ if output_format.lower() == 'jpeg' and img.mode == 'RGBA':
104
+ background = Image.new('RGB', img.size, (255, 255, 255))
105
+ background.paste(img, mask=img.split()[3])
106
+ img = background
107
+
108
+ # Quality ranges from 1 (worst) to 95 (best)
109
+ quality = max(1, min(95, int(95 - (compression_level * 0.94))))
110
+
111
+ if output_format.lower() in ['jpeg', 'webp']:
112
+ img.save(output_path, quality=quality, optimize=True)
113
+ elif output_format.lower() == 'png':
114
+ img.save(output_path, optimize=True, compression_level=int(compression_level/10))
115
+ else:
116
+ img.save(output_path)
117
+
118
+ return output_path
119
+
120
+ def compress_video(input_video, compression_level, output_format="mp4"):
121
+ if input_video is None:
122
+ return None
123
+
124
+ temp_dir = tempfile.mkdtemp()
125
+ output_path = os.path.join(temp_dir, f"compressed_video.{output_format}")
126
+
127
+ # CRF scale is 0-51 (lower means better quality, higher means more compression)
128
+ crf = int(51 * (compression_level / 100))
129
+
130
+ stream = ffmpeg.input(input_video.name)
131
+ stream = ffmpeg.output(stream, output_path,
132
+ vcodec='libx265',
133
+ crf=crf,
134
+ acodec='aac')
135
+ ffmpeg.run(stream, overwrite_output=True)
136
+
137
+ return output_path
138
+
139
+ def compress_files(input_files, compression_format, compression_level):
140
+ if not input_files:
141
+ return None
142
+
143
+ temp_dir = tempfile.mkdtemp()
144
+ timestamp = Path(input_files[0].name).stem
145
+
146
+ if compression_format == "zip":
147
+ output_path = os.path.join(temp_dir, f"compressed_{timestamp}.zip")
148
+ compression = zipfile.ZIP_DEFLATED
149
+ compresslevel = int(9 * compression_level / 100) # 0-9 scale
150
+ with zipfile.ZipFile(output_path, 'w', compression=compression, compresslevel=compresslevel) as zipf:
151
+ for file in input_files:
152
+ zipf.write(file.name, os.path.basename(file.name))
153
+
154
+ if compression_format == "7z":
155
+ output_path = os.path.join(temp_dir, f"compressed_{timestamp}.7z")
156
+ # Map compression level to preset filters
157
+ compression_filters = [
158
+ {'id': py7zr.FILTER_LZMA2, 'preset': int(9 * compression_level / 100)}
159
+ ]
160
+ with py7zr.SevenZipFile(output_path, 'w', filters=compression_filters) as szf:
161
+ for file in input_files:
162
+ szf.write(file.name, os.path.basename(file.name))
163
+
164
+ elif compression_format == "tar.gz":
165
+ output_path = os.path.join(temp_dir, f"compressed_{timestamp}.tar.gz")
166
+ compresslevel = int(9 * compression_level / 100) # 0-9 scale
167
+ with tarfile.open(output_path, "w:gz", compresslevel=compresslevel) as tar:
168
+ for file in input_files:
169
+ tar.add(file.name, arcname=os.path.basename(file.name))
170
+
171
+ elif compression_format == "tar.xz":
172
+ output_path = os.path.join(temp_dir, f"compressed_{timestamp}.tar.xz")
173
+ preset = int(9 * compression_level / 100) # 0-9 scale
174
+ with tarfile.open(output_path, "w:xz", preset=preset) as tar:
175
+ for file in input_files:
176
+ tar.add(file.name, arcname=os.path.basename(file.name))
177
+
178
+ return output_path
179
+
180
+ def resize_image(input_image, width, height, maintain_aspect):
181
+ if input_image is None:
182
+ return None
183
+
184
+ temp_dir = tempfile.mkdtemp()
185
+ img = Image.open(input_image.name)
186
+
187
+ if maintain_aspect:
188
+ # Calculate new dimensions maintaining aspect ratio
189
+ aspect_ratio = img.width / img.height
190
+ if width:
191
+ height = int(width / aspect_ratio)
192
+ else:
193
+ width = int(height * aspect_ratio)
194
+
195
+ # Ensure we have valid dimensions
196
+ width = width if width else img.width
197
+ height = height if height else img.height
198
+
199
+ resized_img = img.resize((width, height), Image.Resampling.LANCZOS)
200
+ output_path = os.path.join(temp_dir, f"resized_image.{input_image.name.split('.')[-1]}")
201
+ resized_img.save(output_path)
202
+
203
+ return output_path
204
+
205
+
206
+ # Create the Gradio interface
207
+ with gr.Blocks(title="Media Toolbox") as app:
208
+ gr.Markdown("""# Universal Media Toolbox (For all Your Ai Media Needs ✨✨)
209
+ #### Note: Higher compression values will significantly reduce file quality and size.
210
+ #### Recommended compression levels:
211
+ #### - Images: 20-40 for good balance between quality and size
212
+ #### - Videos: 30-50 for reasonable quality
213
+ #### - Files: 50-70 for general use
214
+ #### Only use maximum compression (90-100) when file size is critical and quality loss is acceptable
215
+ """)
216
+
217
+ with gr.Tab("Image Conversion"):
218
+ with gr.Row():
219
+ with gr.Column():
220
+ image_input = gr.File(label="Upload Image")
221
+ image_format = gr.Dropdown(
222
+ choices=["PNG", "JPEG", "WEBP", "GIF", "BMP"],
223
+ value="PNG",
224
+ label="Convert to Format"
225
+ )
226
+ image_compression = gr.Slider(
227
+ minimum=0,
228
+ maximum=100,
229
+ value=20,
230
+ label="Compression Level (0: Highest Quality, 100: Maximum Compression)"
231
+ )
232
+ image_convert_btn = gr.Button("Convert Image")
233
+ with gr.Column():
234
+ image_output = gr.File(label="Converted Image")
235
+
236
+ with gr.Tab("Image Resize"):
237
+ with gr.Row():
238
+ with gr.Column():
239
+ resize_input = gr.File(label="Upload Image")
240
+ with gr.Row():
241
+ width = gr.Number(label="Width (pixels)", value=800)
242
+ height = gr.Number(label="Height (pixels)", value=600)
243
+ maintain_aspect = gr.Checkbox(label="Maintain Aspect Ratio", value=True)
244
+ resize_btn = gr.Button("Resize Image")
245
+ with gr.Column():
246
+ resize_output = gr.File(label="Resized Image")
247
+
248
+ with gr.Tab("Image Crop"):
249
+ with gr.Row():
250
+ with gr.Column():
251
+ crop_input = gr.File(label="Upload Image")
252
+ with gr.Row():
253
+ x1 = gr.Number(label="Left", value=0)
254
+ y1 = gr.Number(label="Top", value=0)
255
+ x2 = gr.Number(label="Right", value=100)
256
+ y2 = gr.Number(label="Bottom", value=100)
257
+ crop_btn = gr.Button("Crop Image")
258
+ with gr.Column():
259
+ crop_output = gr.File(label="Cropped Image")
260
+
261
+ with gr.Tab("Image Watermark"):
262
+ with gr.Row():
263
+ with gr.Column():
264
+ watermark_input = gr.File(label="Upload Image")
265
+ watermark_text = gr.Textbox(label="Watermark Text")
266
+ position = gr.Dropdown(
267
+ choices=["top-left", "top-right", "bottom-left", "bottom-right"],
268
+ value="bottom-right",
269
+ label="Position"
270
+ )
271
+ watermark_btn = gr.Button("Add Watermark")
272
+ with gr.Column():
273
+ watermark_output = gr.File(label="Watermarked Image")
274
+
275
+ with gr.Tab("Video Compression"):
276
+ with gr.Row():
277
+ with gr.Column():
278
+ video_input = gr.File(label="Upload Video")
279
+ compression_level = gr.Slider(
280
+ minimum=0,
281
+ maximum=100,
282
+ value=50,
283
+ label="Compression Level (0: Highest Quality, 100: Highest Compression)"
284
+ )
285
+ video_compress_btn = gr.Button("Compress Video")
286
+ with gr.Column():
287
+ video_output = gr.File(label="Compressed Video")
288
+
289
+ with gr.Tab("Video Trim"):
290
+ with gr.Row():
291
+ with gr.Column():
292
+ trim_input = gr.File(label="Upload Video")
293
+ with gr.Row():
294
+ start_time = gr.Number(label="Start Time (seconds)", value=0)
295
+ end_time = gr.Number(label="End Time (seconds)", value=10)
296
+ trim_btn = gr.Button("Trim Video")
297
+ with gr.Column():
298
+ trim_output = gr.File(label="Trimmed Video")
299
+
300
+ with gr.Tab("Audio Extraction"):
301
+ with gr.Row():
302
+ with gr.Column():
303
+ audio_input = gr.File(label="Upload Video")
304
+ audio_format = gr.Dropdown(
305
+ choices=["mp3", "wav", "aac"],
306
+ value="mp3",
307
+ label="Audio Format"
308
+ )
309
+ extract_btn = gr.Button("Extract Audio")
310
+ with gr.Column():
311
+ audio_output = gr.File(label="Extracted Audio")
312
+
313
+ with gr.Tab("Video Thumbnail"):
314
+ with gr.Row():
315
+ with gr.Column():
316
+ thumbnail_input = gr.File(label="Upload Video")
317
+ time_pos = gr.Number(label="Time Position (seconds)", value=0)
318
+ thumbnail_btn = gr.Button("Generate Thumbnail")
319
+ with gr.Column():
320
+ thumbnail_output = gr.File(label="Video Thumbnail")
321
+
322
+ with gr.Tab("File Compression"):
323
+ with gr.Row():
324
+ with gr.Column():
325
+ files_input = gr.File(label="Upload Files", file_count="multiple")
326
+ compression_format = gr.Dropdown(
327
+ choices=["zip", "7z", "tar.gz", "tar.xz"],
328
+ value="zip",
329
+ label="Compression Format"
330
+ )
331
+ file_compression = gr.Slider(
332
+ minimum=0,
333
+ maximum=100,
334
+ value=50,
335
+ label="Compression Level (0: Fastest/Largest, 100: Slowest/Smallest)"
336
+ )
337
+ files_compress_btn = gr.Button("Compress Files")
338
+ with gr.Column():
339
+ files_output = gr.File(label="Compressed Files")
340
+
341
+ # Connect all interface components
342
+ image_convert_btn.click(convert_image,
343
+ inputs=[image_input, image_format, image_compression],
344
+ outputs=image_output)
345
+
346
+ resize_btn.click(resize_image,
347
+ inputs=[resize_input, width, height, maintain_aspect],
348
+ outputs=resize_output)
349
+
350
+ crop_btn.click(crop_image,
351
+ inputs=[crop_input, x1, y1, x2, y2],
352
+ outputs=crop_output)
353
+
354
+ watermark_btn.click(add_watermark,
355
+ inputs=[watermark_input, watermark_text, position],
356
+ outputs=watermark_output)
357
+
358
+ video_compress_btn.click(compress_video,
359
+ inputs=[video_input, compression_level],
360
+ outputs=video_output)
361
+
362
+ trim_btn.click(trim_video,
363
+ inputs=[trim_input, start_time, end_time],
364
+ outputs=trim_output)
365
+
366
+ extract_btn.click(extract_audio,
367
+ inputs=[audio_input, audio_format],
368
+ outputs=audio_output)
369
+
370
+ thumbnail_btn.click(generate_thumbnail,
371
+ inputs=[thumbnail_input, time_pos],
372
+ outputs=thumbnail_output)
373
+
374
+ files_compress_btn.click(compress_files,
375
+ inputs=[files_input, compression_format, file_compression],
376
+ outputs=files_output)
377
+
378
+
379
+ if __name__ == "__main__":
380
+ app.launch()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio
2
+ Pillow
3
+ py7zr
4
+ ffmpeg-python