osnarayana commited on
Commit
2c3ea7b
Β·
1 Parent(s): e2fc4a2

Fix video_service.py

Browse files
Files changed (1) hide show
  1. app/services/video_service.py +12 -32
app/services/video_service.py CHANGED
@@ -1,34 +1,14 @@
1
- # app/services/video_service.py
2
-
3
- import os
4
- import uuid
5
- import requests
6
  from gtts import gTTS
7
  from mutagen.mp3 import MP3
8
  from moviepy.editor import ImageClip, concatenate_videoclips, AudioFileClip
9
- from dotenv import load_dotenv
10
-
11
- load_dotenv()
12
-
13
- UNSPLASH_KEY = os.getenv("UNSPLASH_ACCESS_KEY")
14
- UNSPLASH_API = "https://api.unsplash.com/photos/random"
15
 
16
- def fetch_unsplash_images(query, count=3):
17
- headers = {"Accept-Version": "v1", "Authorization": f"Client-ID {UNSPLASH_KEY}"}
18
- urls = []
19
-
20
- for _ in range(count):
21
- r = requests.get(UNSPLASH_API, params={"query": query}, headers=headers)
22
- if r.status_code == 200:
23
- data = r.json()
24
- if isinstance(data, dict):
25
- urls.append(data["urls"]["regular"])
26
- elif isinstance(data, list) and len(data) > 0:
27
- urls.append(data[0]["urls"]["regular"])
28
- return urls
29
 
30
  def generate_video_file(script: str, duration: int = None) -> str:
31
- # βœ… Use /tmp for Hugging Face Spaces
32
  base_tmp = "/tmp/video"
33
  audio_tmp = "/tmp/audio"
34
  tmp_images = "/tmp/video_tmp"
@@ -41,7 +21,7 @@ def generate_video_file(script: str, duration: int = None) -> str:
41
  video_path = os.path.join(base_tmp, video_filename)
42
  audio_path = os.path.join(audio_tmp, f"audio_{uuid.uuid4().hex}.mp3")
43
 
44
- # Step 1: Generate audio
45
  tts = gTTS(text=script, lang='en')
46
  tts.save(audio_path)
47
 
@@ -54,25 +34,24 @@ def generate_video_file(script: str, duration: int = None) -> str:
54
  if not images:
55
  raise Exception("No images found from Unsplash for the prompt")
56
 
57
- clips = []
58
  per_image_duration = audio_duration / len(images)
59
- tmp_files = []
60
 
61
  for url in images:
62
  img_data = requests.get(url).content
63
  tmp_file = os.path.join(tmp_images, f"tmp_{uuid.uuid4().hex}.jpg")
64
  tmp_files.append(tmp_file)
65
-
66
  with open(tmp_file, "wb") as f:
67
  f.write(img_data)
68
 
69
  clip = ImageClip(tmp_file).resize(height=720).set_duration(per_image_duration)
70
  clips.append(clip)
71
 
 
72
  final_clip = concatenate_videoclips(clips, method="compose").set_duration(audio_duration)
73
  final_clip = final_clip.set_audio(AudioFileClip(audio_path))
74
 
75
- # βœ… Use /tmp temp audio to avoid "generated" folder
76
  final_clip.write_videofile(
77
  video_path,
78
  fps=24,
@@ -81,10 +60,11 @@ def generate_video_file(script: str, duration: int = None) -> str:
81
  threads=4,
82
  preset="ultrafast",
83
  temp_audiofile="/tmp/temp-audio.m4a",
84
- remove_temp=True
 
85
  )
86
 
87
- # Cleanup
88
  for file in tmp_files:
89
  try:
90
  os.remove(file)
 
1
+ import os, uuid, requests
 
 
 
 
2
  from gtts import gTTS
3
  from mutagen.mp3 import MP3
4
  from moviepy.editor import ImageClip, concatenate_videoclips, AudioFileClip
5
+ from moviepy.config import change_settings
 
 
 
 
 
6
 
7
+ # βœ… Force MoviePy temp directory to /tmp
8
+ change_settings({"FFMPEG_BINARY": "ffmpeg"})
9
+ os.environ["TMPDIR"] = "/tmp"
 
 
 
 
 
 
 
 
 
 
10
 
11
  def generate_video_file(script: str, duration: int = None) -> str:
 
12
  base_tmp = "/tmp/video"
13
  audio_tmp = "/tmp/audio"
14
  tmp_images = "/tmp/video_tmp"
 
21
  video_path = os.path.join(base_tmp, video_filename)
22
  audio_path = os.path.join(audio_tmp, f"audio_{uuid.uuid4().hex}.mp3")
23
 
24
+ # Step 1: Generate TTS audio
25
  tts = gTTS(text=script, lang='en')
26
  tts.save(audio_path)
27
 
 
34
  if not images:
35
  raise Exception("No images found from Unsplash for the prompt")
36
 
37
+ clips, tmp_files = [], []
38
  per_image_duration = audio_duration / len(images)
 
39
 
40
  for url in images:
41
  img_data = requests.get(url).content
42
  tmp_file = os.path.join(tmp_images, f"tmp_{uuid.uuid4().hex}.jpg")
43
  tmp_files.append(tmp_file)
 
44
  with open(tmp_file, "wb") as f:
45
  f.write(img_data)
46
 
47
  clip = ImageClip(tmp_file).resize(height=720).set_duration(per_image_duration)
48
  clips.append(clip)
49
 
50
+ # Step 4: Build final video
51
  final_clip = concatenate_videoclips(clips, method="compose").set_duration(audio_duration)
52
  final_clip = final_clip.set_audio(AudioFileClip(audio_path))
53
 
54
+ # βœ… Step 5: Export video with all temp files in /tmp
55
  final_clip.write_videofile(
56
  video_path,
57
  fps=24,
 
60
  threads=4,
61
  preset="ultrafast",
62
  temp_audiofile="/tmp/temp-audio.m4a",
63
+ remove_temp=True,
64
+ ffmpeg_params=["-avoid_negative_ts", "make_zero"]
65
  )
66
 
67
+ # Cleanup images
68
  for file in tmp_files:
69
  try:
70
  os.remove(file)