Spaces:
Sleeping
Sleeping
| // api.js | |
| // Shared API client — all fetch calls to the FastAPI backend go through here. | |
| const _h = window.location.hostname; | |
| const API_BASE = (_h === 'localhost' || _h === '127.0.0.1' || _h === '::1' || _h === '') | |
| ? 'http://127.0.0.1:8000' // local dev | |
| : 'https://parina13-synthsenses-api.hf.space'; // production | |
| /** | |
| * Wakes the Render server if it has spun down (free tier cold start ~30-90s). | |
| * Updates the loading message while waiting. | |
| */ | |
| async function _wakeServer() { | |
| const TIMEOUT_MS = 90_000; | |
| const POLL_MS = 3_000; | |
| const deadline = Date.now() + TIMEOUT_MS; | |
| // Try once immediately — if server is up this returns fast | |
| try { | |
| const res = await fetch(`${API_BASE}/health`, { method: 'GET' }); | |
| if (res.ok) return; | |
| } catch (_) { /* server is sleeping, start polling */ } | |
| // Show "waking up" message if server didn't respond immediately | |
| const loadingEl = document.getElementById('loading'); | |
| const loadingP = loadingEl ? loadingEl.querySelector('p') : null; | |
| if (loadingP) loadingP.textContent = 'Waking up server (first request may take ~30s)…'; | |
| while (Date.now() < deadline) { | |
| await new Promise(r => setTimeout(r, POLL_MS)); | |
| try { | |
| const res = await fetch(`${API_BASE}/health`, { method: 'GET' }); | |
| if (res.ok) { | |
| if (loadingP) loadingP.textContent = 'Analysing video…'; | |
| return; | |
| } | |
| } catch (_) { /* still booting */ } | |
| } | |
| throw new Error('Server took too long to wake up. Please try again in a moment.'); | |
| } | |
| /** | |
| * POST /analyze/synthetic | |
| * @param {File} videoFile | |
| * @returns {Promise<{label, confidence, prob_ai, prob_deepfake}>} | |
| */ | |
| async function analyzeSynthetic(videoFile) { | |
| await _wakeServer(); | |
| const form = new FormData(); | |
| form.append('video', videoFile); | |
| const res = await fetch(`${API_BASE}/analyze/synthetic`, { | |
| method: 'POST', | |
| body: form, | |
| }); | |
| if (!res.ok) { | |
| const err = await res.json().catch(() => ({ detail: res.statusText })); | |
| throw new Error(err.detail || 'Synthetic detection failed.'); | |
| } | |
| return res.json(); | |
| } | |
| /** | |
| * POST /analyze/virality | |
| * @param {File} videoFile | |
| * @param {{title, post_hour, post_day, tag_count, user_caption, user_hashtags}} meta | |
| * @returns {Promise<{virality_score, label, probability, top_features, features, explanation}>} | |
| */ | |
| async function analyzeVirality(videoFile, meta) { | |
| await _wakeServer(); | |
| const form = new FormData(); | |
| form.append('video', videoFile); | |
| form.append('title', meta.title ?? ''); | |
| form.append('post_hour', meta.post_hour ?? 12); | |
| form.append('post_day', meta.post_day ?? 1); | |
| form.append('tag_count', meta.tag_count ?? 5); | |
| form.append('user_caption', meta.user_caption ?? ''); | |
| form.append('user_hashtags', meta.user_hashtags ?? ''); | |
| const res = await fetch(`${API_BASE}/analyze/virality`, { | |
| method: 'POST', | |
| body: form, | |
| }); | |
| if (!res.ok) { | |
| const err = await res.json().catch(() => ({ detail: res.statusText })); | |
| throw new Error(err.detail || 'Virality prediction failed.'); | |
| } | |
| return res.json(); | |
| } | |