jcnok commited on
Commit
73228b4
·
verified ·
1 Parent(s): 05961ac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -29
app.py CHANGED
@@ -23,12 +23,12 @@ from fastapi.responses import FileResponse, JSONResponse
23
  from starlette.background import BackgroundTask
24
 
25
  # ==============================================================================
26
- # 1. APLICATION CONFIGURATION & SETUP
27
  # ==============================================================================
28
  app = FastAPI(
29
  title="FFmpeg as a Service for n8n",
30
  description="A robust API to create videos from image and audio Gradio URLs.",
31
- version="3.1.0",
32
  )
33
 
34
  TEMP_DIR = "/tmp/ffmpeg_processing"
@@ -75,7 +75,7 @@ async def process_video_from_urls(payload: Dict = Body(...)):
75
  unique_id = str(uuid.uuid4())
76
  temp_processing_dir = os.path.join(TEMP_DIR, unique_id)
77
  os.makedirs(temp_processing_dir)
78
-
79
  try:
80
  image_urls = payload.get("image_urls", [])
81
  audio_url = payload.get("audio_url")
@@ -85,39 +85,37 @@ async def process_video_from_urls(payload: Dict = Body(...)):
85
  if not all([image_urls, audio_url, total_duration]):
86
  raise HTTPException(status_code=400, detail="Bad Request: 'image_urls', 'audio_url', and 'total_duration' are required.")
87
 
88
- # --- Step 1: Download All Media in Parallel ---
89
- print("--- STEP 1: DOWNLOADING ALL MEDIA ---")
90
  async with aiohttp.ClientSession(headers=BROWSER_HEADERS) as session:
91
- all_urls = image_urls + [audio_url]
92
- tasks = [session.get(url) for url in all_urls]
93
- responses = await asyncio.gather(*tasks, return_exceptions=True)
94
-
95
- local_image_paths = []
96
- narracao_path = os.path.join(temp_processing_dir, "narracao.mp3")
97
-
98
- for i, res in enumerate(responses):
99
- if isinstance(res, Exception) or res.status != 200:
100
- url = all_urls[i]
101
- raise HTTPException(status_code=502, detail=f"Failed to download media from {url}. Status: {getattr(res, 'status', 'N/A')}")
102
-
103
- content = await res.read()
104
- if i < len(image_urls):
105
- path = os.path.join(temp_processing_dir, f"image_{i:02d}.jpg")
106
- local_image_paths.append(path)
107
- with open(path, 'wb') as f: f.write(content)
108
- else:
109
- with open(narracao_path, 'wb') as f: f.write(content)
110
-
111
- print("--- SUCCESS: ALL MEDIA DOWNLOADED ---")
112
-
113
  # --- Step 2: Create Silent Video Slideshow ---
114
  print("--- STEP 2: CREATING SILENT VIDEO ---")
115
  duration_per_image = total_duration / len(image_urls)
116
  silent_video_path = os.path.join(temp_processing_dir, "silent_video.mp4")
117
-
118
- # Usando a sintaxe de -framerate que é mais robusta
119
  input_pattern = shlex.quote(os.path.join(temp_processing_dir, 'image_%02d.jpg'))
120
  framerate = 1 / duration_per_image
 
121
  cmd_video = f"ffmpeg -framerate {framerate} -i {input_pattern} -c:v libx264 -pix_fmt yuv420p -r 25 -y {shlex.quote(silent_video_path)}"
122
  await run_subprocess(cmd_video)
123
  print("--- SUCCESS: SILENT VIDEO CREATED ---")
 
23
  from starlette.background import BackgroundTask
24
 
25
  # ==============================================================================
26
+ # 1. APPLICATION CONFIGURATION & SETUP
27
  # ==============================================================================
28
  app = FastAPI(
29
  title="FFmpeg as a Service for n8n",
30
  description="A robust API to create videos from image and audio Gradio URLs.",
31
+ version="4.0.0",
32
  )
33
 
34
  TEMP_DIR = "/tmp/ffmpeg_processing"
 
75
  unique_id = str(uuid.uuid4())
76
  temp_processing_dir = os.path.join(TEMP_DIR, unique_id)
77
  os.makedirs(temp_processing_dir)
78
+
79
  try:
80
  image_urls = payload.get("image_urls", [])
81
  audio_url = payload.get("audio_url")
 
85
  if not all([image_urls, audio_url, total_duration]):
86
  raise HTTPException(status_code=400, detail="Bad Request: 'image_urls', 'audio_url', and 'total_duration' are required.")
87
 
88
+ # --- Step 1: Download All Media SEQUENTIALLY ---
89
+ print("--- STEP 1: DOWNLOADING ALL MEDIA (SEQUENTIAL MODE) ---")
90
  async with aiohttp.ClientSession(headers=BROWSER_HEADERS) as session:
91
+ # First, download the audio file.
92
+ narracao_path = os.path.join(temp_processing_dir, "narracao.mp3")
93
+ print(f"Downloading audio from {audio_url}...")
94
+ async with session.get(audio_url) as resp:
95
+ if resp.status != 200:
96
+ raise HTTPException(status_code=502, detail=f"Failed to download audio. Status: {resp.status}, URL: {audio_url}")
97
+ with open(narracao_path, "wb") as f: f.write(await resp.read())
98
+ print("SUCCESS: Audio downloaded.")
99
+
100
+ # Now, loop and download images one by one.
101
+ local_image_paths = []
102
+ for i, url in enumerate(image_urls):
103
+ local_path = os.path.join(temp_processing_dir, f"image_{i:02d}.jpg")
104
+ print(f"Downloading image {i+1}/{len(image_urls)} from {url}...")
105
+ async with session.get(url) as resp:
106
+ if resp.status != 200:
107
+ raise HTTPException(status_code=502, detail=f"Failed to download image {i+1}. Status: {resp.status}, URL: {url}")
108
+ with open(local_path, "wb") as f: f.write(await resp.read())
109
+ local_image_paths.append(local_path)
110
+ print("SUCCESS: All images downloaded.")
111
+
 
112
  # --- Step 2: Create Silent Video Slideshow ---
113
  print("--- STEP 2: CREATING SILENT VIDEO ---")
114
  duration_per_image = total_duration / len(image_urls)
115
  silent_video_path = os.path.join(temp_processing_dir, "silent_video.mp4")
 
 
116
  input_pattern = shlex.quote(os.path.join(temp_processing_dir, 'image_%02d.jpg'))
117
  framerate = 1 / duration_per_image
118
+
119
  cmd_video = f"ffmpeg -framerate {framerate} -i {input_pattern} -c:v libx264 -pix_fmt yuv420p -r 25 -y {shlex.quote(silent_video_path)}"
120
  await run_subprocess(cmd_video)
121
  print("--- SUCCESS: SILENT VIDEO CREATED ---")