Pepguy commited on
Commit
decf4fe
·
verified ·
1 Parent(s): 5586098

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -14
app.py CHANGED
@@ -1,45 +1,71 @@
1
- # app.py (FastAPI)
2
  from fastapi import FastAPI, HTTPException, UploadFile, File, Form
3
  import subprocess
4
  import base64
5
  import os
6
  import uuid
7
  import shutil
 
8
 
9
  app = FastAPI()
10
 
 
 
 
 
 
 
 
 
 
11
  @app.post("/process-video")
12
- async def process_video(file: UploadFile = File(...), is_pro: bool = Form(False)):
13
  job_id = str(uuid.uuid4())
14
  work_dir = f"/tmp/viralcat_{job_id}"
15
  os.makedirs(work_dir, exist_ok=True)
16
  video_path = os.path.join(work_dir, "video.mp4")
17
- video_b64 = ""
18
 
19
  try:
20
- # 1. Save uploaded file
21
  with open(video_path, "wb") as buffer:
22
  shutil.copyfileobj(file.file, buffer)
23
 
24
- # 2. Check Duration
25
  probe = subprocess.run([
26
  "ffprobe", "-v", "error", "-show_entries",
27
  "format=duration", "-of", "default=noprint_wrappers=1:nokey=1",
28
  video_path
29
  ], capture_output=True, text=True, check=True)
30
-
31
  duration = float(probe.stdout.strip() or 0)
32
- if duration > 120 and not is_pro:
33
- raise ValueError(f"Video is {duration:.1f}s. Free users are limited to 120s.")
34
 
35
- # 3. Convert to Base64
36
- with open(video_path, "rb") as f:
37
- video_b64 = base64.b64encode(f.read()).decode('utf-8')
38
- print("Done")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  return {
40
  "success": True,
41
- "duration": duration,
42
- "video_base64": video_base64
43
  }
44
 
45
  except Exception as e:
 
 
1
  from fastapi import FastAPI, HTTPException, UploadFile, File, Form
2
  import subprocess
3
  import base64
4
  import os
5
  import uuid
6
  import shutil
7
+ import whisper
8
 
9
  app = FastAPI()
10
 
11
+ # Load Whisper Tiny (Fastest) once on startup
12
+ print("Loading Whisper...")
13
+ whisper_model = whisper.load_model("tiny")
14
+
15
+ def file_to_base64(filepath):
16
+ if not os.path.exists(filepath): return None
17
+ with open(filepath, "rb") as f:
18
+ return base64.b64encode(f.read()).decode('utf-8')
19
+
20
  @app.post("/process-video")
21
+ async def process_video(file: UploadFile = File(...)):
22
  job_id = str(uuid.uuid4())
23
  work_dir = f"/tmp/viralcat_{job_id}"
24
  os.makedirs(work_dir, exist_ok=True)
25
  video_path = os.path.join(work_dir, "video.mp4")
26
+ audio_path = os.path.join(work_dir, "audio.wav")
27
 
28
  try:
 
29
  with open(video_path, "wb") as buffer:
30
  shutil.copyfileobj(file.file, buffer)
31
 
32
+ # 1. Get Duration
33
  probe = subprocess.run([
34
  "ffprobe", "-v", "error", "-show_entries",
35
  "format=duration", "-of", "default=noprint_wrappers=1:nokey=1",
36
  video_path
37
  ], capture_output=True, text=True, check=True)
 
38
  duration = float(probe.stdout.strip() or 0)
 
 
39
 
40
+ # 2. Extract exactly 15 frames regardless of length
41
+ # Calculate fps to get 15 frames (e.g. if 30s, fps is 15/30 = 0.5)
42
+ fps = 15 / max(duration, 1)
43
+ subprocess.run([
44
+ "ffmpeg", "-y", "-i", video_path,
45
+ "-vf", f"fps={fps}",
46
+ "-vframes", "15",
47
+ "-q:v", "4", f"{work_dir}/frame_%03d.jpg"
48
+ ], check=True, capture_output=True)
49
+
50
+ # 3. Extract & Transcribe Audio
51
+ subprocess.run([
52
+ "ffmpeg", "-y", "-i", video_path,
53
+ "-vn", "-acodec", "pcm_s16le", "-ar", "16000", "-ac", "1", audio_path
54
+ ], check=True, capture_output=True)
55
+
56
+ transcript = ""
57
+ if os.path.exists(audio_path):
58
+ result = whisper_model.transcribe(audio_path)
59
+ transcript = result["text"].strip()
60
+
61
+ # 4. Gather frames
62
+ frame_files = sorted([f for f in os.listdir(work_dir) if f.startswith("frame_")])
63
+ frames_b64 = [file_to_base64(os.path.join(work_dir, f)) for f in frame_files]
64
+
65
  return {
66
  "success": True,
67
+ "transcript": transcript,
68
+ "frames": frames_b64
69
  }
70
 
71
  except Exception as e: