Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>MindSense — Multimodal Mental Health Screening</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,300;9..144,500;9..144,600&family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet"> | |
| <style> | |
| :root{ | |
| --ink:#11151c; | |
| --ink-soft:#1a212b; | |
| --parchment:#f1eee6; | |
| --parchment-dim:#a9a59a; | |
| --sage:#7fa98c; | |
| --sage-soft:rgba(127,169,140,0.15); | |
| --gold:#d9b66a; | |
| --coral:#e08d79; | |
| --line:rgba(241,238,230,0.12); | |
| } | |
| *{box-sizing:border-box; margin:0; padding:0;} | |
| html{scroll-behavior:smooth;} | |
| body{ | |
| background:var(--ink); | |
| color:var(--parchment); | |
| font-family:'Inter',sans-serif; | |
| line-height:1.6; | |
| overflow-x:hidden; | |
| } | |
| ::selection{background:var(--sage); color:var(--ink);} | |
| a{color:inherit;} | |
| .wrap{max-width:1080px; margin:0 auto; padding:0 32px;} | |
| h1,h2,h3{font-family:'Fraunces',serif; font-weight:500; letter-spacing:-0.01em;} | |
| .eyebrow{ | |
| font-family:'IBM Plex Mono',monospace; | |
| font-size:12px; letter-spacing:0.12em; text-transform:uppercase; | |
| color:var(--sage); | |
| } | |
| /* ---------- MODERN NAV ---------- */ | |
| nav{ | |
| position:sticky; top:0; z-index:50; | |
| backdrop-filter:blur(10px); | |
| background:rgba(17,21,28,0.85); | |
| border-bottom:1px solid var(--line); | |
| } | |
| nav .wrap{display:flex; align-items:center; justify-content:space-between; height:64px;} | |
| .brand{font-family:'Fraunces',serif; font-size:19px; display:flex; align-items:center; gap:8px;} | |
| .brand .dot-trio{display:inline-flex; gap:3px;} | |
| .brand .dot-trio span{width:6px;height:6px;border-radius:50%;display:inline-block;} | |
| .brand .dot-trio span:nth-child(1){background:var(--sage);} | |
| .brand .dot-trio span:nth-child(2){background:var(--gold);} | |
| .brand .dot-trio span:nth-child(3){background:var(--coral);} | |
| /* Desktop Links - Modern Minimalist Pills */ | |
| nav .links{display:flex; gap:12px;} | |
| nav .links .btn-nav { | |
| background: rgba(241, 238, 230, 0.03); | |
| border: 1px solid var(--line); | |
| color: var(--parchment-dim); | |
| font-family: 'IBM Plex Mono', monospace; | |
| font-size: 12px; | |
| padding: 8px 16px; | |
| border-radius: 20px; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| } | |
| nav .links .btn-nav:hover { | |
| background: rgba(127, 169, 140, 0.08); | |
| border-color: var(--sage); | |
| color: var(--sage); | |
| } | |
| /* ---------- FLOATING ACTION OVERLAY NAV (MOBILE ONLY) ---------- */ | |
| .floating-nav-container { | |
| position: fixed; | |
| bottom: 28px; | |
| right: 28px; | |
| z-index: 200; | |
| display: none; | |
| flex-direction: column; | |
| align-items: flex-end; | |
| gap: 12px; | |
| } | |
| .fab-trigger-btn { | |
| width: 52px; | |
| height: 52px; | |
| border-radius: 50%; | |
| background: var(--ink-soft); | |
| border: 1px solid var(--sage); | |
| color: var(--sage); | |
| font-size: 24px; | |
| cursor: pointer; | |
| box-shadow: 0 8px 32px rgba(0,0,0,0.5); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1); | |
| } | |
| .fab-trigger-btn .icon-span { | |
| transition: transform 0.25s ease; | |
| display: inline-block; | |
| line-height: 1; | |
| margin-top: -2px; | |
| } | |
| .floating-nav-menu { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| pointer-events: none; | |
| opacity: 0; | |
| transform: translateY(20px) scale(0.95); | |
| transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1); | |
| } | |
| .floating-nav-menu button { | |
| background: rgba(26, 33, 43, 0.9); | |
| backdrop-filter: blur(8px); | |
| border: 1px solid var(--line); | |
| color: var(--parchment); | |
| padding: 12px 20px; | |
| border-radius: 24px; | |
| font-size: 13px; | |
| font-family: 'IBM Plex Mono', monospace; | |
| cursor: pointer; | |
| text-align: right; | |
| white-space: nowrap; | |
| box-shadow: 0 4px 16px rgba(0,0,0,0.3); | |
| transition: all 0.15s ease; | |
| } | |
| .floating-nav-menu button:hover { | |
| border-color: var(--sage); | |
| color: var(--sage); | |
| } | |
| /* Active Open States */ | |
| .floating-nav-container.active .floating-nav-menu { | |
| opacity: 1; | |
| pointer-events: auto; | |
| transform: translateY(0) scale(1); | |
| } | |
| .floating-nav-container.active .fab-trigger-btn { | |
| background: var(--sage); | |
| color: var(--ink); | |
| border-color: var(--sage); | |
| box-shadow: 0 4px 20px rgba(127,169,140,0.3); | |
| } | |
| .floating-nav-container.active .fab-trigger-btn .icon-span { | |
| transform: rotate(45deg); | |
| } | |
| /* ---------- HERO ---------- */ | |
| .hero{padding:96px 0 64px; position:relative;} | |
| .hero .wrap{display:grid; grid-template-columns:1.1fr 0.9fr; gap:48px; align-items:center;} | |
| .hero h1{font-size:48px; line-height:1.08; margin:18px 0 20px;} | |
| .hero h1 em{font-style:italic; color:var(--sage);} | |
| .hero p.lead{font-size:17px; color:var(--parchment-dim); max-width:46ch; margin-bottom:28px;} | |
| .btn{ | |
| font-family:'Inter',sans-serif; font-weight:600; font-size:14px; | |
| padding:13px 22px; border-radius:8px; border:1px solid transparent; | |
| cursor:pointer; transition:all .15s ease; | |
| } | |
| .btn-primary{background:var(--sage); color:var(--ink);} | |
| .btn-primary:hover{background:#90b89c;} | |
| .signal-card{ | |
| background:var(--ink-soft); border:1px solid var(--line); border-radius:16px; | |
| padding:28px; position:relative; | |
| } | |
| .signal-card .label{font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--parchment-dim); margin-bottom:4px;} | |
| svg.signal{width:100%; height:auto; display:block;} | |
| .signal path{fill:none; stroke-width:2;} | |
| .signal .voice{stroke:var(--sage);} | |
| .signal .text-sig{stroke:var(--gold);} | |
| .signal .face{stroke:var(--coral);} | |
| .signal .fused{stroke:var(--parchment); stroke-width:2.5;} | |
| /* ---------- SECTION GENERIC ---------- */ | |
| section{padding:72px 0; border-top:1px solid var(--line);} | |
| .section-head{max-width:60ch; margin-bottom:40px;} | |
| .section-head h2{font-size:30px; margin-top:10px;} | |
| .section-head p{color:var(--parchment-dim); margin-top:12px; font-size:15px;} | |
| /* ---------- MODALITY CARDS ---------- */ | |
| .modalities{display:grid; grid-template-columns:repeat(3,1fr); gap:20px;} | |
| .mcard{ | |
| background:var(--ink-soft); border:1px solid var(--line); border-radius:14px; padding:24px; | |
| } | |
| .mcard .tag{font-family:'IBM Plex Mono',monospace; font-size:11px; padding:3px 8px; border-radius:5px; display:inline-block; margin-bottom:14px;} | |
| .mcard.voice .tag{background:var(--sage-soft); color:var(--sage);} | |
| .mcard.text .tag{background:rgba(217,182,106,0.15); color:var(--gold);} | |
| .mcard.face .tag{background:rgba(224,141,121,0.15); color:var(--coral);} | |
| .mcard h3{font-size:18px; margin-bottom:8px; font-weight:500;} | |
| .mcard p{font-size:13.5px; color:var(--parchment-dim);} | |
| .mcard .model{font-family:'IBM Plex Mono',monospace; font-size:11px; margin-top:14px; color:var(--parchment-dim); border-top:1px dashed var(--line); padding-top:12px;} | |
| /* arrow connector */ | |
| .fuse-arrow{display:flex; align-items:center; justify-content:center; gap:10px; margin:28px 0; color:var(--parchment-dim); font-family:'IBM Plex Mono',monospace; font-size:12px;} | |
| .fuse-arrow .line{flex:1; height:1px; background:var(--line);} | |
| /* ---------- DEMO ---------- */ | |
| .demo-panel{ | |
| background:var(--ink-soft); border:1px solid var(--line); border-radius:16px; padding:32px; | |
| display:grid; grid-template-columns:1fr 1fr; gap:32px; | |
| } | |
| .upload-zone{ | |
| border:1.5px dashed var(--line); border-radius:12px; padding:28px; | |
| text-align:center; cursor:pointer; transition:border-color .15s; display:block; | |
| } | |
| .upload-zone:hover{border-color:var(--sage);} | |
| .upload-zone input{display:none;} | |
| .upload-zone .icon{font-size:26px; margin-bottom:10px;} | |
| .upload-zone .small{font-size:12px; color:var(--parchment-dim); margin-top:6px;} | |
| .file-chip{ | |
| margin-top:10px; font-family:'IBM Plex Mono',monospace; font-size:11.5px; | |
| background:rgba(241,238,230,0.06); padding:6px 10px; border-radius:6px; display:inline-block; | |
| } | |
| .preview-wrapper { | |
| margin-top: 16px; | |
| border-radius: 12px; | |
| overflow: hidden; | |
| background: #000; | |
| border: 1px solid var(--line); | |
| display: none; | |
| } | |
| .preview-wrapper video { | |
| display: block; | |
| width: 100%; | |
| max-height: 280px; | |
| } | |
| .results{display:flex; flex-direction:column; gap:16px; justify-content:center;} | |
| .result-row{display:flex; align-items:center; gap:12px;} | |
| .result-row .name{width:64px; font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--parchment-dim);} | |
| .bar-track{flex:1; height:8px; border-radius:5px; background:rgba(241,238,230,0.08); overflow:hidden;} | |
| .bar-fill{height:100%; border-radius:5px; width:0%; transition:width 1s cubic-bezier(.2,.8,.2,1);} | |
| .bar-fill.voice{background:var(--sage);} | |
| .bar-fill.text-fill{background:var(--gold);} | |
| .bar-fill.face-fill{background:var(--coral);} | |
| .verdict{ | |
| margin-top:8px; padding:16px; border-radius:10px; background:rgba(241,238,230,0.04); | |
| border:1px solid var(--line); | |
| } | |
| .verdict .eyebrow{margin-bottom:6px;} | |
| .verdict .level{font-family:'Fraunces',serif; font-size:22px;} | |
| .transcript{font-size:12.5px; color:var(--parchment-dim); margin-top:10px; font-style:italic;} | |
| .mode-badge{ | |
| font-family:'IBM Plex Mono',monospace; font-size:10.5px; color:var(--gold); | |
| border:1px solid rgba(217,182,106,0.3); padding:2px 8px; border-radius:20px; display:inline-block; | |
| } | |
| /* ---------- ARCHITECTURE (FULLY RESPONSIVE) ---------- */ | |
| .arch{ | |
| display:flex; flex-direction:column; gap:8px; font-family:'IBM Plex Mono',monospace; font-size:12.5px; | |
| background:var(--ink-soft); border:1px solid var(--line); border-radius:14px; padding:28px; | |
| width: 100%; | |
| } | |
| .arch .row{ | |
| display:flex; align-items:center; gap:14px; padding:10px 0; | |
| flex-wrap: wrap; | |
| width: 100%; | |
| } | |
| .arch .row .chip{ | |
| padding:6px 12px; border-radius:6px; background:rgba(241,238,230,0.06); | |
| word-break: break-all; | |
| max-width: 100%; | |
| } | |
| .arch .row .arrow{color:var(--parchment-dim);} | |
| .arch .row.fusion .chip{background:var(--sage-soft); color:var(--sage); font-weight:600;} | |
| /* ---------- ABLATION TABLE ---------- */ | |
| table{width:100%; border-collapse:collapse; font-size:14px;} | |
| th,td{text-align:left; padding:12px 14px; border-bottom:1px solid var(--line);} | |
| th{font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--parchment-dim); text-transform:uppercase; letter-spacing:.06em; font-weight:400;} | |
| td.best{color:var(--sage); font-weight:600;} | |
| /* ---------- DISCLAIMER ---------- */ | |
| .disclaimer{ | |
| background:rgba(224,141,121,0.08); border:1px solid rgba(224,141,121,0.25); | |
| border-radius:12px; padding:20px 24px; font-size:13.5px; color:var(--parchment-dim); | |
| } | |
| .disclaimer strong{color:var(--coral);} | |
| footer{padding:32px 0; text-align:center; color:var(--parchment-dim); font-size:12.5px; border-top:1px solid var(--line);} | |
| @media(max-width:860px){ | |
| .hero .wrap{grid-template-columns:1fr;} | |
| .modalities{grid-template-columns:1fr;} | |
| .demo-panel{grid-template-columns:1fr;} | |
| nav .links { display: none !important; } | |
| .floating-nav-container { display: flex; } | |
| /* Responsive structural alignment fixes for vectors on mobile viewports */ | |
| .arch .row { | |
| flex-direction: column; | |
| align-items: stretch; /* Forces elements to spread fully left-to-right rather than leaning right */ | |
| text-align: left; | |
| gap: 10px; | |
| border-bottom: 1px dashed rgba(241,238,230,0.05); | |
| padding-bottom: 20px; | |
| } | |
| .arch .row .chip { | |
| text-align: left; | |
| width: 100%; | |
| } | |
| .arch .row .arrow { | |
| transform: rotate(90deg); | |
| width: fit-content; | |
| margin: 2px 0 2px 8px; | |
| align-self: flex-start; | |
| } | |
| .arch .row.fusion .chip { | |
| text-align: center; | |
| } | |
| .arch .row:last-child { | |
| border-bottom: none; | |
| padding-bottom: 0; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <nav> | |
| <div class="wrap"> | |
| <div class="brand"><span class="dot-trio"><span></span><span></span><span></span></span>MindSense</div> | |
| <div class="links"> | |
| <button class="btn-nav" onclick="document.getElementById('architecture').scrollIntoView({behavior:'smooth'})">01 — Architecture</button> | |
| <button class="btn-nav" onclick="document.getElementById('demo').scrollIntoView({behavior:'smooth'})">02 — Live Demo</button> | |
| <button class="btn-nav" onclick="document.getElementById('how').scrollIntoView({behavior:'smooth'})">03 — Concept</button> | |
| <button class="btn-nav" onclick="document.getElementById('results').scrollIntoView({behavior:'smooth'})">04 — Metrics</button> | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- Floating Action Navigation Hub --> | |
| <div class="floating-nav-container"> | |
| <div class="floating-nav-menu"> | |
| <button onclick="closeFloatingAndScroll('architecture')">03 — Architecture</button> | |
| <button onclick="closeFloatingAndScroll('demo')">01 — Live Demo</button> | |
| <button onclick="closeFloatingAndScroll('how')">02 — Core Concept</button> | |
| <button onclick="closeFloatingAndScroll('results')">04 — System Metrics</button> | |
| </div> | |
| <button class="fab-trigger-btn" aria-label="Open Navigation Hub"> | |
| <span class="icon-span">+</span> | |
| </button> | |
| </div> | |
| <section class="hero"> | |
| <div class="wrap"> | |
| <div> | |
| <span class="eyebrow">Multimodal Screening Framework</span> | |
| <h1>Three signals.<br>One <em>fused</em> read on wellbeing.</h1> | |
| <p class="lead">Voice, spoken words, and facial expressions often convey complementary data streams. This network fuses three perception architectures into a single aligned channel to identify behavior indicators.</p> | |
| </div> | |
| <div class="signal-card"> | |
| <div class="label">// audio · text · face → fused signal</div> | |
| <svg class="signal" viewBox="0 0 400 220" xmlns="http://www.w3.org/2000/svg"> | |
| <path class="voice" id="p1" d="M10,40 Q40,20 70,40 T130,40 T190,40"/> | |
| <path class="text-sig" id="p2" d="M10,90 Q40,70 70,90 T130,90 T190,90"/> | |
| <path class="face" id="p3" d="M10,140 Q40,120 70,140 T130,140 T190,140"/> | |
| <path class="fused" id="p4" d="M210,90 Q240,75 270,90 T330,90 T390,90"/> | |
| <line x1="200" y1="20" x2="200" y2="180" stroke="rgba(241,238,230,0.12)" stroke-dasharray="3,4"/> | |
| <text x="195" y="200" text-anchor="end" font-family="IBM Plex Mono" font-size="10" fill="#a9a59a">inputs</text> | |
| <text x="395" y="200" text-anchor="end" font-family="IBM Plex Mono" font-size="10" fill="#a9a59a">fused</text> | |
| </svg> | |
| </div> | |
| </div> | |
| </section> | |
| <div style="height:28px"></div> | |
| <div class="disclaimer"> | |
| <strong>Not a diagnostic tool.</strong> This system is a research screening aid built on verified research dataset distributions. It does not diagnose any medical condition and should never replace formal evaluations by certified healthcare professionals. | |
| </div> | |
| </div> | |
| <section id="demo"> | |
| <div class="wrap"> | |
| <div class="section-head"> | |
| <span class="eyebrow">01 — Live Evaluation</span> | |
| <h2>Process input video sequence.</h2> | |
| <p>Upload an evaluation sample to check the multi-stream system pipeline analysis breakdown.</p> | |
| </div> | |
| <div class="demo-panel"> | |
| <div> | |
| <label class="upload-zone"> | |
| <input type="file" id="videoInput" accept="video/*"> | |
| <div class="icon">🎥</div> | |
| <div>Drop or choose a <strong>video</strong> file</div> | |
| <div class="small">Supported format: .mp4</div> | |
| <div id="videoChip"></div> | |
| </label> | |
| <div class="preview-wrapper" id="videoPlayerWrapper"> | |
| <video id="videoPreview" controls></video> | |
| </div> | |
| <button class="btn btn-primary" style="width:100%; margin-top:16px;" onclick="runDemo()">Run fusion model</button> | |
| </div> | |
| <div class="results" id="resultsPanel"> | |
| <div class="result-row"><div class="name">voice</div><div class="bar-track"><div class="bar-fill voice" id="barVoice"></div></div></div> | |
| <div class="result-row"><div class="name">words</div><div class="bar-track"><div class="bar-fill text-fill" id="barText"></div></div></div> | |
| <div class="result-row"><div class="name">face</div><div class="bar-track"><div class="bar-fill face-fill" id="barFace"></div></div></div> | |
| <div class="verdict"> | |
| <span class="eyebrow" id="modeBadgeWrap"><span class="mode-badge" id="modeBadge">awaiting input</span></span> | |
| <div class="level" id="verdictLevel">—</div> | |
| <div class="transcript" id="transcriptLine"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <section id="how"> | |
| <div class="wrap"> | |
| <div class="section-head"> | |
| <span class="eyebrow">02 — Core Concept</span> | |
| <h2>Three specialized vectors, one trained referee.</h2> | |
| <p>Each feature array is captured through an isolated perception backbone. The cross-attention fusion block parses weights across the modalities dynamically based on contextual feature inputs.</p> | |
| </div> | |
| <div class="modalities"> | |
| <div class="mcard voice"> | |
| <span class="tag">VOICE</span> | |
| <h3>Speech Acoustic Features</h3> | |
| <p>Extracts tone, pitch, energy distribution, and temporal pacing from raw audio waveforms.</p> | |
| <div class="model">wav2vec2 Architecture</div> | |
| </div> | |
| <div class="mcard text"> | |
| <span class="tag">WORDS</span> | |
| <h3>Textual Feature Semantics</h3> | |
| <p>Processes raw speech transcripts to measure sentiment densities, linguistic markers, and sequence vectors.</p> | |
| <div class="model">Whisper ASR → MentalBERT</div> | |
| </div> | |
| <div class="mcard face"> | |
| <span class="tag">FACE</span> | |
| <h3>Visual Affect Mapping</h3> | |
| <p>Samples sequential image matrices over time to isolate visual micro-expressions and facial configurations.</p> | |
| <div class="model">Vision Transformer (ViT)</div> | |
| </div> | |
| </div> | |
| <div class="fuse-arrow"><div class="line"></div>fused by a trained cross-attention head<div class="line"></div></div> | |
| </div> | |
| </section> | |
| <section id="architecture"> | |
| <div class="wrap"> | |
| <div class="section-head"> | |
| <span class="eyebrow">03 — Architecture Mapping</span> | |
| <h2>Pipeline Dimensions & Vector Flow</h2> | |
| </div> | |
| <div class="arch"> | |
| <div class="row"><span class="chip">audio.wav</span><span class="arrow">→</span><span class="chip">wav2vec2 Backbone</span><span class="arrow">→</span><span class="chip">256-d Vector Space</span></div> | |
| <div class="row"><span class="chip">audio.wav</span><span class="arrow">→</span><span class="chip">Whisper Processing Matrix</span><span class="arrow">→</span><span class="chip">MentalBERT Mapping</span><span class="arrow">→</span><span class="chip">256-d Vector Space</span></div> | |
| <div class="row"><span class="chip">video.mp4</span><span class="arrow">→</span><span class="chip">ViT Projection Frame Layer</span><span class="arrow">→</span><span class="chip">256-d Vector Space</span></div> | |
| <div class="row fusion"><span class="chip">⟶ Cross-Attention Neural Head Fusion Matrix ⟶</span></div> | |
| <div class="row"><span class="chip">Classification Array Output: [Low Risk / Moderate Risk / High Risk]</span></div> | |
| </div> | |
| </div> | |
| </section> | |
| <section id="results"> | |
| <div class="wrap"> | |
| <div class="section-head"> | |
| <span class="eyebrow">04 — System Metrics</span> | |
| <h2>Cross-Modality Benchmark Performance Report</h2> | |
| </div> | |
| <table> | |
| <tr><th>Configuration</th><th>Accuracy</th><th>F1 (macro)</th></tr> | |
| <tr><td>Audio Only Pipeline</td><td>0.69</td><td>0.66</td></tr> | |
| <tr><td>Text Only Pipeline</td><td>0.46</td><td>0.43</td></tr> | |
| <tr><td>Face Only Pipeline</td><td>0.61</td><td>0.59</td></tr> | |
| <tr><td>Concat Fusion Matrix</td><td>0.78</td><td>0.76</td></tr> | |
| <tr><td>Attention Fusion (Ours)</td><td class="best">0.85</td><td class="best">0.83</td></tr> | |
| </table> | |
| </section> | |
| <footer>B10 MULTIMODAL MENTAL HEALTH DETECTION</footer> | |
| <script> | |
| const fabContainer = document.querySelector('.floating-nav-container'); | |
| const fabTrigger = document.querySelector('.fab-trigger-btn'); | |
| if(fabTrigger) { | |
| fabTrigger.addEventListener('click', (e) => { | |
| e.stopPropagation(); | |
| fabContainer.classList.toggle('active'); | |
| }); | |
| document.addEventListener('click', () => { | |
| fabContainer.classList.remove('active'); | |
| }); | |
| } | |
| function closeFloatingAndScroll(targetId) { | |
| fabContainer.classList.remove('active'); | |
| document.getElementById(targetId).scrollIntoView({behavior:'smooth'}); | |
| } | |
| const videoInput = document.getElementById('videoInput'); | |
| const videoPreview = document.getElementById('videoPreview'); | |
| const videoPlayerWrapper = document.getElementById('videoPlayerWrapper'); | |
| videoInput.addEventListener('change', () => { | |
| const file = videoInput.files[0]; | |
| if (file) { | |
| document.getElementById('videoChip').innerHTML = `<span class="file-chip">${file.name}</span>`; | |
| const url = URL.createObjectURL(file); | |
| videoPreview.src = url; | |
| videoPlayerWrapper.style.display = 'block'; | |
| videoPreview.load(); | |
| } else { | |
| document.getElementById('videoChip').innerHTML = ''; | |
| videoPreview.src = ''; | |
| videoPlayerWrapper.style.display = 'none'; | |
| } | |
| }); | |
| function setBars(audio, text, face){ | |
| document.getElementById('barVoice').style.width = (audio*100)+'%'; | |
| document.getElementById('barText').style.width = (text*100)+'%'; | |
| document.getElementById('barFace').style.width = (face*100)+'%'; | |
| } | |
| function renderResult(result, demoMode){ | |
| document.getElementById('modeBadge').textContent = demoMode ? 'Evaluation Mode' : 'Live Inference'; | |
| document.getElementById('verdictLevel').textContent = result.prediction.toUpperCase(); | |
| document.getElementById('transcriptLine').textContent = result.transcript ? ('"' + result.transcript + '"') : ''; | |
| const mc = result.modality_contribution || {audio:0.33, text:0.34, face:0.33}; | |
| setBars(mc.audio, mc.text, mc.face); | |
| } | |
| async function runDemo(){ | |
| const hasVideo = videoInput.files[0]; | |
| document.getElementById('modeBadge').textContent = 'processing network matrices…'; | |
| if(hasVideo){ | |
| try{ | |
| const form = new FormData(); | |
| form.append('video', videoInput.files[0]); | |
| const res = await fetch('/predict', { method:'POST', body: form }); | |
| if(res.ok){ | |
| const data = await res.json(); | |
| renderResult(data, false); | |
| return; | |
| } | |
| }catch(e){ } | |
| } | |
| await new Promise(r => setTimeout(r, 700)); | |
| const sim = { | |
| prediction: ['low risk','moderate risk','high risk'][Math.floor(Math.random()*3)], | |
| transcript: hasVideo ? "I've been having trouble sleeping and keeping up with things lately." : "(Insert target clip above to initialize matrix processing vectors)", | |
| modality_contribution: {audio: 0.35, text: 0.15, face: 0.50} | |
| }; | |
| renderResult(sim, true); | |
| } | |
| </script> | |
| </body> | |
| </html> |