Local test entrypoint — runs the pipeline in local_mode (no Supabase upload). Usage: modal run backend/app.py --video path/to/video.mp4 modal run backend/app.py --video path/to/video.mp4 --output result.mp4
(video: str = "", output: str = "output.mp4")
| 153 | requests.exceptions.Timeout) as exc: |
| 154 | last_exc = exc |
| 155 | status = getattr(getattr(exc, "response", None), "status_code", None) |
| 156 | # 4xx (other than 408/429) are real errors — don't retry |
| 157 | if status is not None and 400 <= status < 500 and status not in (408, 429): |
| 158 | raise |
| 159 | if attempt == download_attempts: |
| 160 | raise |
| 161 | backoff = min(60, 2 ** attempt) # 2s, 4s, 8s, 16s (cap 60s) |
| 162 | print(f"[download] attempt {attempt}/{download_attempts} failed ({type(exc).__name__}: {exc}); retrying in {backoff}s") |
| 163 | time.sleep(backoff) |
| 164 | else: |
| 165 | # Should be unreachable — loop either breaks on success or raises on final attempt. |
| 166 | if last_exc is not None: |
| 167 | raise last_exc |
| 168 | |
| 169 | _stage("Loading models", 0.012) |
| 170 | |
| 171 | from backend.pipeline.run import run_pipeline |
| 172 | except Exception: |
| 173 | _stage("Processing could not start", 0, failure="Processing could not start. Press Reprocess to try again.") |
| 174 | raise |
| 175 | |
| 176 | result = run_pipeline(video_path, match_id) |
| 177 | |
| 178 | return result |
| 179 | |
| 180 | |
| 181 | @app.local_entrypoint() |
| 182 | def test_local(video: str = "", output: str = "output.mp4"): |
| 183 | """ |
| 184 | Local test entrypoint — runs the pipeline in local_mode (no Supabase upload). |
| 185 | |
| 186 | Usage: |
| 187 | modal run backend/app.py --video path/to/video.mp4 |
nothing calls this directly
no test coverage detected