gagndeep commited on
Commit
f6dad19
Β·
verified Β·
1 Parent(s): c3d6a54

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +322 -0
  2. requirements.txt +3 -0
app.py ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import subprocess
4
+ import tempfile
5
+ from pathlib import Path
6
+ import mimetypes
7
+ import uuid
8
+
9
+ # Define supported formats
10
+ SUPPORTED_AUDIO_FORMATS = ['mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a']
11
+ SUPPORTED_VIDEO_FORMATS = ['mp4', 'avi', 'mov', 'mkv', 'webm', 'flv']
12
+ SUPPORTED_IMAGE_FORMATS = ['jpg', 'jpeg', 'png', 'webp', 'bmp', 'gif', 'tiff']
13
+ SUPPORTED_DOCUMENT_FORMATS = ['pdf', 'docx', 'txt', 'rtf', 'html']
14
+
15
+ # Combined supported formats
16
+ SUPPORTED_FORMATS = {
17
+ 'Audio': SUPPORTED_AUDIO_FORMATS,
18
+ 'Video': SUPPORTED_VIDEO_FORMATS,
19
+ 'Image': SUPPORTED_IMAGE_FORMATS,
20
+ 'Document': SUPPORTED_DOCUMENT_FORMATS
21
+ }
22
+
23
+ def detect_file_type(file_path):
24
+ """Detect file type based on extension and mime type"""
25
+ ext = Path(file_path).suffix.lower()[1:]
26
+ mime_type, _ = mimetypes.guess_type(file_path)
27
+
28
+ if ext in SUPPORTED_AUDIO_FORMATS:
29
+ return 'Audio'
30
+ elif ext in SUPPORTED_VIDEO_FORMATS:
31
+ return 'Video'
32
+ elif ext in SUPPORTED_IMAGE_FORMATS:
33
+ return 'Image'
34
+ elif ext in SUPPORTED_DOCUMENT_FORMATS:
35
+ return 'Document'
36
+ elif mime_type and mime_type.startswith('audio/'):
37
+ return 'Audio'
38
+ elif mime_type and mime_type.startswith('video/'):
39
+ return 'Video'
40
+ elif mime_type and mime_type.startswith('image/'):
41
+ return 'Image'
42
+ elif mime_type and mime_type.startswith('text/'):
43
+ return 'Document'
44
+ else:
45
+ return 'Unknown'
46
+
47
+ def convert_media(input_file, output_format, media_type):
48
+ """Convert media file using FFmpeg for audio/video and ImageMagick for images"""
49
+ try:
50
+ # Create temp directory
51
+ with tempfile.TemporaryDirectory() as temp_dir:
52
+ input_path = os.path.join(temp_dir, f"input_{uuid.uuid4().hex}")
53
+ output_path = os.path.join(temp_dir, f"output_{uuid.uuid4().hex}.{output_format}")
54
+
55
+ # Save input file
56
+ with open(input_path, 'wb') as f:
57
+ f.write(input_file)
58
+
59
+ # Convert based on media type
60
+ if media_type == 'Audio':
61
+ cmd = [
62
+ 'ffmpeg', '-y', '-i', input_path,
63
+ '-vn', '-acodec', 'libmp3lame' if output_format == 'mp3' else 'aac',
64
+ '-q:a', '2', output_path
65
+ ]
66
+ elif media_type == 'Video':
67
+ cmd = [
68
+ 'ffmpeg', '-y', '-i', input_path,
69
+ '-c:v', 'libx264', '-crf', '23',
70
+ '-c:a', 'aac', '-b:a', '128k',
71
+ output_path
72
+ ]
73
+ elif media_type == 'Image':
74
+ cmd = [
75
+ 'convert', input_path, output_path
76
+ ]
77
+ elif media_type == 'Document':
78
+ if output_format == 'pdf':
79
+ cmd = [
80
+ 'libreoffice', '--headless', '--convert-to', 'pdf',
81
+ '--outdir', temp_dir, input_path
82
+ ]
83
+ output_path = input_path.replace('.docx', '.pdf')
84
+ else:
85
+ # Simple text conversion
86
+ with open(input_path, 'r') as f:
87
+ content = f.read()
88
+ with open(output_path, 'w') as f:
89
+ f.write(content)
90
+ return output_path
91
+
92
+ # Execute conversion
93
+ result = subprocess.run(cmd, capture_output=True, text=True)
94
+
95
+ if result.returncode != 0:
96
+ raise Exception(f"Conversion failed: {result.stderr}")
97
+
98
+ # Read output file
99
+ with open(output_path, 'rb') as f:
100
+ output_data = f.read()
101
+
102
+ return output_data
103
+
104
+ except Exception as e:
105
+ raise Exception(f"Conversion error: {str(e)}")
106
+
107
+ def process_conversion(input_file, output_format):
108
+ """Main conversion function"""
109
+ try:
110
+ # Create temp file to detect type
111
+ with tempfile.NamedTemporaryFile(delete=False) as temp_file:
112
+ temp_path = temp_file.name
113
+ temp_file.write(input_file)
114
+
115
+ # Detect media type
116
+ media_type = detect_file_type(temp_path)
117
+
118
+ if media_type == 'Unknown':
119
+ raise Exception("Unsupported file format")
120
+
121
+ # Validate output format
122
+ if output_format not in SUPPORTED_FORMATS[media_type]:
123
+ raise Exception(f"Unsupported output format for {media_type}: {output_format}")
124
+
125
+ # Convert
126
+ output_data = convert_media(input_file, output_format, media_type)
127
+
128
+ # Clean up
129
+ os.unlink(temp_path)
130
+
131
+ return output_data
132
+
133
+ except Exception as e:
134
+ if 'temp_path' in locals():
135
+ try:
136
+ os.unlink(temp_path)
137
+ except:
138
+ pass
139
+ raise Exception(f"Error: {str(e)}")
140
+
141
+ # Create custom theme
142
+ custom_theme = gr.themes.Soft(
143
+ primary_hue="blue",
144
+ secondary_hue="indigo",
145
+ neutral_hue="slate",
146
+ font=gr.themes.GoogleFont("Inter"),
147
+ text_size="lg",
148
+ spacing_size="lg",
149
+ radius_size="md"
150
+ ).set(
151
+ button_primary_background_fill="*primary_600",
152
+ button_primary_background_fill_hover="*primary_700",
153
+ block_title_text_weight="600",
154
+ )
155
+
156
+ # Create Gradio interface
157
+ with gr.Blocks() as demo:
158
+ gr.Markdown("""
159
+ # 🎡 Universal Media Converter
160
+ **Built with anycoder** - [https://huggingface.co/spaces/akhaliq/anycoder](https://huggingface.co/spaces/akhaliq/anycoder)
161
+
162
+ Convert media files between various formats using Hugging Face's zero-GPU infrastructure.
163
+ """)
164
+
165
+ with gr.Row():
166
+ with gr.Column(scale=1):
167
+ gr.Markdown("## Input Media")
168
+ input_file = gr.File(
169
+ label="Upload Media File",
170
+ file_types=[
171
+ "audio", "video", "image",
172
+ ".pdf", ".docx", ".txt", ".rtf", ".html"
173
+ ],
174
+ type="binary"
175
+ )
176
+
177
+ # Format selection
178
+ with gr.Accordion("Advanced Options", open=False):
179
+ gr.Markdown("### Select Output Format")
180
+
181
+ with gr.Row():
182
+ media_type_select = gr.Dropdown(
183
+ choices=list(SUPPORTED_FORMATS.keys()),
184
+ value="Audio",
185
+ label="Media Type"
186
+ )
187
+
188
+ format_select = gr.Dropdown(
189
+ choices=SUPPORTED_AUDIO_FORMATS,
190
+ value="mp3",
191
+ label="Output Format"
192
+ )
193
+
194
+ with gr.Column(scale=1):
195
+ gr.Markdown("## Conversion Result")
196
+ output_file = gr.File(label="Download Converted File")
197
+
198
+ status_text = gr.Textbox(
199
+ label="Status",
200
+ value="Ready to convert!",
201
+ interactive=False
202
+ )
203
+
204
+ # Update format dropdown based on media type
205
+ def update_formats(media_type):
206
+ return gr.Dropdown(
207
+ choices=SUPPORTED_FORMATS.get(media_type, []),
208
+ value=SUPPORTED_FORMATS.get(media_type, [])[0] if SUPPORTED_FORMATS.get(media_type) else ""
209
+ )
210
+
211
+ media_type_select.change(
212
+ fn=update_formats,
213
+ inputs=media_type_select,
214
+ outputs=format_select
215
+ )
216
+
217
+ # Conversion button
218
+ convert_btn = gr.Button("πŸ”„ Convert Media", variant="primary", size="lg")
219
+
220
+ def convert_wrapper(input_data, output_format):
221
+ try:
222
+ if input_data is None:
223
+ raise Exception("Please upload a file first")
224
+
225
+ # Convert
226
+ result = process_conversion(input_data, output_format)
227
+
228
+ return {
229
+ output_file: result,
230
+ status_text: f"βœ… Successfully converted to {output_format.upper()}"
231
+ }
232
+ except Exception as e:
233
+ return {
234
+ output_file: None,
235
+ status_text: f"❌ Error: {str(e)}"
236
+ }
237
+
238
+ convert_btn.click(
239
+ fn=convert_wrapper,
240
+ inputs=[input_file, format_select],
241
+ outputs=[output_file, status_text],
242
+ api_visibility="public"
243
+ )
244
+
245
+ # Examples
246
+ gr.Markdown("## πŸ“š Examples")
247
+ gr.Examples(
248
+ examples=[
249
+ ["https://example.com/sample.mp3", "wav"],
250
+ ["https://example.com/sample.mp4", "avi"],
251
+ ["https://example.com/sample.jpg", "png"],
252
+ ["https://example.com/sample.docx", "pdf"]
253
+ ],
254
+ inputs=[input_file, format_select],
255
+ outputs=[output_file, status_text],
256
+ fn=convert_wrapper,
257
+ cache_examples=True,
258
+ examples_per_page=4
259
+ )
260
+
261
+ gr.Markdown("""
262
+ ## πŸ“‹ Supported Formats
263
+
264
+ ### Audio
265
+ MP3, WAV, OGG, FLAC, AAC, M4A
266
+
267
+ ### Video
268
+ MP4, AVI, MOV, MKV, WEBM, FLV
269
+
270
+ ### Image
271
+ JPG, PNG, WEBP, BMP, GIF, TIFF
272
+
273
+ ### Document
274
+ PDF, DOCX, TXT, RTF, HTML
275
+ """)
276
+
277
+ demo.launch(
278
+ theme=custom_theme,
279
+ footer_links=[
280
+ {
281
+ "label": "Built with anycoder",
282
+ "url": "https://huggingface.co/spaces/akhaliq/anycoder"
283
+ },
284
+ {
285
+ "label": "Gradio Docs",
286
+ "url": "https://gradio.app/docs"
287
+ }
288
+ ],
289
+ css="""
290
+ .gradio-container {
291
+ max-width: 1000px !important;
292
+ }
293
+ .gr-button-primary {
294
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
295
+ border: none !important;
296
+ }
297
+ .gr-button-primary:hover {
298
+ transform: translateY(-2px);
299
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15) !important;
300
+ }
301
+ .gr-box {
302
+ border-radius: 12px !important;
303
+ border: 1px solid #e5e7eb !important;
304
+ }
305
+ """,
306
+ js="""
307
+ function addAnimation() {
308
+ const buttons = document.querySelectorAll('.gr-button-primary');
309
+ buttons.forEach(button => {
310
+ button.addEventListener('click', function() {
311
+ this.style.transform = 'scale(0.95)';
312
+ setTimeout(() => {
313
+ this.style.transform = 'scale(1)';
314
+ }, 150);
315
+ });
316
+ });
317
+ }
318
+
319
+ // Add animation when page loads
320
+ document.addEventListener('DOMContentLoaded', addAnimation);
321
+ """
322
+ )
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio>=6.0
2
+ requests
3
+ Pillow