Spaces:
Sleeping
Sleeping
| // src/api/client.js — API wrapper for MultiSense-DF backend | |
| const API_BASE = import.meta.env.VITE_API_BASE || 'http://localhost:8000'; | |
| /** | |
| * Mock results for demo mode | |
| */ | |
| export const DEMO_RESULTS = { | |
| verdict: 'FAKE', | |
| confidence: 0.923, | |
| visual_score: 0.871, | |
| audio_score: 0.956, | |
| lipsync_score: 0.834, | |
| contributions: { visual: 0.38, audio: 0.41, lipsync: 0.21 }, | |
| sync_profile: [ | |
| 0.82, 0.79, 0.81, 0.23, 0.19, 0.21, 0.18, 0.76, 0.78, 0.72, | |
| 0.15, 0.14, 0.17, 0.13, 0.68, 0.71, 0.69, 0.22, 0.24, 0.19, | |
| 0.81, 0.83, 0.79, 0.14, 0.12, 0.16, 0.71, 0.73, 0.68, 0.21, | |
| 0.84, 0.82, 0.78, 0.17, 0.15, 0.19, 0.72, 0.74, 0.71, 0.23, | |
| 0.83, 0.81, 0.76, 0.18, 0.14, 0.21, 0.69, 0.73, 0.70, 0.25, | |
| ], | |
| gradcam_image: null, | |
| filename: 'demo_video.mp4', | |
| }; | |
| /** | |
| * Analyze a video file. Returns structured detection results. | |
| * Throws if the request fails. | |
| */ | |
| export async function analyzeVideo(file, onProgress) { | |
| const formData = new FormData(); | |
| formData.append('file', file); | |
| // Simulate early-stage progress while uploading | |
| onProgress && onProgress('uploading'); | |
| const response = await fetch(`${API_BASE}/analyze`, { | |
| method: 'POST', | |
| body: formData, | |
| }); | |
| if (!response.ok) { | |
| const errorText = await response.text().catch(() => 'Unknown server error'); | |
| throw new Error(`Server returned ${response.status}: ${errorText}`); | |
| } | |
| const data = await response.json(); | |
| return data; | |
| } | |
| /** | |
| * Simulate analysis with demo data — fetches from /demo/fake if backend is up, | |
| * otherwise falls back to the local DEMO_RESULTS mock. | |
| */ | |
| export async function runDemoAnalysis(onStepChange) { | |
| const steps = [ | |
| { key: 'frames', delay: 900 }, | |
| { key: 'audio', delay: 900 }, | |
| { key: 'lipsync', delay: 900 }, | |
| { key: 'fusion', delay: 700 }, | |
| { key: 'done', delay: 300 }, | |
| ]; | |
| // Walk through visual progress steps | |
| for (let i = 0; i < steps.length - 1; i++) { | |
| onStepChange && onStepChange(steps[i].key); | |
| await sleep(steps[i].delay); | |
| } | |
| // Try to get real demo data from backend, fall back to local mock | |
| let result = DEMO_RESULTS; | |
| try { | |
| const res = await fetch(`${API_BASE}/demo/fake?filename=celeb_df_sample.mp4`); | |
| if (res.ok) result = await res.json(); | |
| } catch (_) { | |
| // backend not reachable — use local mock | |
| } | |
| onStepChange && onStepChange('done'); | |
| await sleep(300); | |
| return result; | |
| } | |
| function sleep(ms) { | |
| return new Promise((resolve) => setTimeout(resolve, ms)); | |
| } | |