kavehtaheri commited on
Commit
d02f7ee
·
verified ·
1 Parent(s): 982a69f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +161 -38
app.py CHANGED
@@ -10,33 +10,121 @@ import tempfile
10
  import re
11
 
12
  def download_from_google_drive(url):
13
- """Download file from Google Drive URL"""
14
  try:
15
- # Extract file ID from Google Drive URL
 
 
 
 
 
 
 
16
  if 'drive.google.com' in url:
17
- if '/file/d/' in url:
18
- file_id = url.split('/file/d/')[1].split('/')[0]
19
- elif 'id=' in url:
20
- file_id = url.split('id=')[1].split('&')[0]
21
- else:
22
- return None
 
 
 
 
 
 
 
 
 
23
 
24
- download_url = f"https://drive.google.com/uc?id={file_id}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  output_path = tempfile.mktemp(suffix='.mp4')
26
- gdown.download(download_url, output_path, quiet=False)
27
- return output_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  else:
29
- # Direct download for other URLs
30
- response = requests.get(url)
31
  output_path = tempfile.mktemp(suffix='.mp4')
 
 
32
  with open(output_path, 'wb') as f:
33
- f.write(response.content)
 
34
  return output_path
 
35
  except Exception as e:
36
  print(f"Error downloading file: {e}")
37
  return None
38
 
39
- def calculate_font_size(text, max_width, max_height, font_path):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  """Calculate optimal font size based on text length and video dimensions"""
41
  char_count = len(text)
42
 
@@ -69,9 +157,12 @@ def create_text_clip(text, font_size, video_size, position, duration, start_time
69
  else:
70
  # Try to use a system font that supports Unicode
71
  try:
72
- font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", font_size)
73
  except:
74
- font = ImageFont.load_default()
 
 
 
75
  except:
76
  font = ImageFont.load_default()
77
 
@@ -110,27 +201,49 @@ def create_text_clip(text, font_size, video_size, position, duration, start_time
110
  def process_video(video_url, music_url, poem_verse, poet_name, username, progress=gr.Progress()):
111
  """Main function to process video with text overlays and animations"""
112
 
113
- progress(0.1, desc="Downloading video...")
114
-
115
- # Download video
116
- video_path = download_from_google_drive(video_url)
117
- if not video_path:
118
- return "Error: Could not download video"
119
-
120
  try:
121
- # Load video
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  progress(0.2, desc="Loading video...")
 
 
123
  video = mp.VideoFileClip(video_path)
124
 
125
  # Download and process audio if music URL provided
 
126
  if music_url and music_url.strip():
127
  progress(0.3, desc="Processing audio...")
128
- if music_url.startswith('http'):
129
- music_path = tempfile.mktemp(suffix='.mp3')
130
- response = requests.get(music_url)
131
- with open(music_path, 'wb') as f:
132
- f.write(response.content)
133
- audio = mp.AudioFileClip(music_path)
 
 
 
 
 
 
 
 
134
  else:
135
  audio = video.audio
136
  else:
@@ -143,7 +256,7 @@ def process_video(video_url, music_url, poem_verse, poet_name, username, progres
143
  duration = video.duration
144
 
145
  # Calculate font sizes
146
- verse_font_size = calculate_font_size(poem_verse, video.w, video.h, None)
147
  poet_font_size = max(20, verse_font_size // 2)
148
  username_font_size = max(18, verse_font_size // 3)
149
 
@@ -207,7 +320,7 @@ def process_video(video_url, music_url, poem_verse, poet_name, username, progres
207
  output_path,
208
  codec='libx264',
209
  audio_codec='aac',
210
- fps=video.fps,
211
  preset='medium',
212
  ffmpeg_params=['-crf', '23']
213
  )
@@ -216,13 +329,16 @@ def process_video(video_url, music_url, poem_verse, poet_name, username, progres
216
 
217
  # Clean up
218
  video.close()
219
- if audio:
220
  audio.close()
221
  final_video.close()
222
 
223
  # Clean up temporary files
224
- if os.path.exists(video_path):
225
- os.remove(video_path)
 
 
 
226
 
227
  return output_path
228
 
@@ -242,7 +358,7 @@ def create_interface():
242
  video_url = gr.Textbox(
243
  label="Video URL (Google Drive)",
244
  placeholder="https://drive.google.com/file/d/your-file-id/view",
245
- lines=1
246
  )
247
 
248
  music_url = gr.Textbox(
@@ -276,7 +392,9 @@ def create_interface():
276
 
277
  gr.Markdown("""
278
  ### 📝 Instructions:
279
- 1. **Video URL**: Paste Google Drive video link (make sure it's publicly accessible)
 
 
280
  2. **Music URL**: Optional background music (or leave empty for original audio)
281
  3. **Poem Verse**: Your poetry text (supports Unicode/RTL languages)
282
  4. **Poet Name**: Will appear at bottom with "- " prefix
@@ -288,6 +406,11 @@ def create_interface():
288
  - Smooth zoom animation for video focus
289
  - RTL language support
290
  - Clean, professional output
 
 
 
 
 
291
  """)
292
 
293
  create_btn.click(
 
10
  import re
11
 
12
  def download_from_google_drive(url):
13
+ """Download file from Google Drive URL with improved parsing"""
14
  try:
15
+ if not url or not isinstance(url, str):
16
+ raise ValueError("Invalid URL provided")
17
+
18
+ print(f"Processing URL: {url}")
19
+
20
+ # Clean up the URL
21
+ url = url.strip()
22
+
23
  if 'drive.google.com' in url:
24
+ # Multiple patterns to handle different Google Drive URL formats
25
+ patterns = [
26
+ r'/file/d/([a-zA-Z0-9-_]+)',
27
+ r'id=([a-zA-Z0-9-_]+)',
28
+ r'/d/([a-zA-Z0-9-_]+)',
29
+ r'file/d/([a-zA-Z0-9-_]+)/view',
30
+ r'open\?id=([a-zA-Z0-9-_]+)'
31
+ ]
32
+
33
+ file_id = None
34
+ for pattern in patterns:
35
+ match = re.search(pattern, url)
36
+ if match:
37
+ file_id = match.group(1)
38
+ break
39
 
40
+ if not file_id:
41
+ # Try alternative extraction method
42
+ if '/file/d/' in url:
43
+ try:
44
+ file_id = url.split('/file/d/')[1].split('/')[0]
45
+ except IndexError:
46
+ pass
47
+ elif 'id=' in url:
48
+ try:
49
+ file_id = url.split('id=')[1].split('&')[0]
50
+ except IndexError:
51
+ pass
52
+
53
+ if not file_id:
54
+ raise ValueError("Could not extract file ID from Google Drive URL")
55
+
56
+ print(f"Extracted file ID: {file_id}")
57
+
58
+ # Create download URL
59
+ download_url = f"https://drive.google.com/uc?export=download&id={file_id}"
60
+
61
+ # Download using gdown
62
  output_path = tempfile.mktemp(suffix='.mp4')
63
+ try:
64
+ gdown.download(download_url, output_path, quiet=False)
65
+ if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
66
+ return output_path
67
+ else:
68
+ # Try alternative download method
69
+ gdown.download(f"https://drive.google.com/file/d/{file_id}/view?usp=sharing",
70
+ output_path, quiet=False, fuzzy=True)
71
+ return output_path
72
+ except Exception as e:
73
+ print(f"gdown failed: {e}")
74
+ # Fallback to direct requests
75
+ try:
76
+ response = requests.get(download_url, stream=True)
77
+ response.raise_for_status()
78
+ with open(output_path, 'wb') as f:
79
+ for chunk in response.iter_content(chunk_size=8192):
80
+ f.write(chunk)
81
+ return output_path
82
+ except Exception as e2:
83
+ print(f"Direct download also failed: {e2}")
84
+ raise e2
85
  else:
86
+ # Handle direct URLs
 
87
  output_path = tempfile.mktemp(suffix='.mp4')
88
+ response = requests.get(url, stream=True)
89
+ response.raise_for_status()
90
  with open(output_path, 'wb') as f:
91
+ for chunk in response.iter_content(chunk_size=8192):
92
+ f.write(chunk)
93
  return output_path
94
+
95
  except Exception as e:
96
  print(f"Error downloading file: {e}")
97
  return None
98
 
99
+ def download_audio_file(url):
100
+ """Download audio file from URL"""
101
+ try:
102
+ if not url or not url.strip():
103
+ return None
104
+
105
+ url = url.strip()
106
+
107
+ # Determine file extension
108
+ if url.lower().endswith(('.mp3', '.wav', '.m4a', '.aac')):
109
+ ext = url.split('.')[-1]
110
+ else:
111
+ ext = 'mp3'
112
+
113
+ output_path = tempfile.mktemp(suffix=f'.{ext}')
114
+
115
+ response = requests.get(url, stream=True)
116
+ response.raise_for_status()
117
+
118
+ with open(output_path, 'wb') as f:
119
+ for chunk in response.iter_content(chunk_size=8192):
120
+ f.write(chunk)
121
+
122
+ return output_path
123
+ except Exception as e:
124
+ print(f"Error downloading audio: {e}")
125
+ return None
126
+
127
+ def calculate_font_size(text, max_width, max_height, font_path=None):
128
  """Calculate optimal font size based on text length and video dimensions"""
129
  char_count = len(text)
130
 
 
157
  else:
158
  # Try to use a system font that supports Unicode
159
  try:
160
+ font = ImageFont.truetype("/System/Library/Fonts/Arial.ttf", font_size)
161
  except:
162
+ try:
163
+ font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", font_size)
164
+ except:
165
+ font = ImageFont.load_default()
166
  except:
167
  font = ImageFont.load_default()
168
 
 
201
  def process_video(video_url, music_url, poem_verse, poet_name, username, progress=gr.Progress()):
202
  """Main function to process video with text overlays and animations"""
203
 
 
 
 
 
 
 
 
204
  try:
205
+ if not video_url or not video_url.strip():
206
+ return "Error: Please provide a video URL"
207
+
208
+ if not poem_verse or not poem_verse.strip():
209
+ return "Error: Please provide a poem verse"
210
+
211
+ if not poet_name or not poet_name.strip():
212
+ return "Error: Please provide a poet name"
213
+
214
+ if not username or not username.strip():
215
+ return "Error: Please provide a username"
216
+
217
+ progress(0.1, desc="Downloading video...")
218
+
219
+ # Download video
220
+ video_path = download_from_google_drive(video_url)
221
+ if not video_path or not os.path.exists(video_path):
222
+ return "Error: Could not download video. Please check the URL and ensure the file is publicly accessible."
223
+
224
  progress(0.2, desc="Loading video...")
225
+
226
+ # Load video
227
  video = mp.VideoFileClip(video_path)
228
 
229
  # Download and process audio if music URL provided
230
+ audio = None
231
  if music_url and music_url.strip():
232
  progress(0.3, desc="Processing audio...")
233
+ audio_path = download_audio_file(music_url)
234
+ if audio_path and os.path.exists(audio_path):
235
+ try:
236
+ audio = mp.AudioFileClip(audio_path)
237
+ # Match audio duration to video duration
238
+ if audio.duration > video.duration:
239
+ audio = audio.subclip(0, video.duration)
240
+ elif audio.duration < video.duration:
241
+ # Loop audio if shorter than video
242
+ loops_needed = int(video.duration / audio.duration) + 1
243
+ audio = mp.concatenate_audioclips([audio] * loops_needed).subclip(0, video.duration)
244
+ except Exception as e:
245
+ print(f"Audio processing failed: {e}")
246
+ audio = video.audio
247
  else:
248
  audio = video.audio
249
  else:
 
256
  duration = video.duration
257
 
258
  # Calculate font sizes
259
+ verse_font_size = calculate_font_size(poem_verse, video.w, video.h)
260
  poet_font_size = max(20, verse_font_size // 2)
261
  username_font_size = max(18, verse_font_size // 3)
262
 
 
320
  output_path,
321
  codec='libx264',
322
  audio_codec='aac',
323
+ fps=min(video.fps, 30), # Limit FPS for better performance
324
  preset='medium',
325
  ffmpeg_params=['-crf', '23']
326
  )
 
329
 
330
  # Clean up
331
  video.close()
332
+ if audio and audio != video.audio:
333
  audio.close()
334
  final_video.close()
335
 
336
  # Clean up temporary files
337
+ try:
338
+ if os.path.exists(video_path):
339
+ os.remove(video_path)
340
+ except:
341
+ pass
342
 
343
  return output_path
344
 
 
358
  video_url = gr.Textbox(
359
  label="Video URL (Google Drive)",
360
  placeholder="https://drive.google.com/file/d/your-file-id/view",
361
+ lines=2
362
  )
363
 
364
  music_url = gr.Textbox(
 
392
 
393
  gr.Markdown("""
394
  ### 📝 Instructions:
395
+ 1. **Video URL**: Paste Google Drive video link
396
+ - Format: `https://drive.google.com/file/d/FILE_ID/view`
397
+ - Make sure the file is publicly accessible
398
  2. **Music URL**: Optional background music (or leave empty for original audio)
399
  3. **Poem Verse**: Your poetry text (supports Unicode/RTL languages)
400
  4. **Poet Name**: Will appear at bottom with "- " prefix
 
406
  - Smooth zoom animation for video focus
407
  - RTL language support
408
  - Clean, professional output
409
+
410
+ ### 🔧 Troubleshooting:
411
+ - Ensure Google Drive file is publicly accessible
412
+ - Check that the URL format is correct
413
+ - Video should be in MP4 format for best results
414
  """)
415
 
416
  create_btn.click(