Spaces:
Running
Running
Update public/index.html
Browse files- public/index.html +329 -216
public/index.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>
|
| 7 |
<link rel="icon" type="image/jpeg" href="https://africa.dlnlp.ai/simba/images/favicon.png">
|
| 8 |
|
| 9 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
@@ -13,118 +13,238 @@
|
|
| 13 |
|
| 14 |
<style>
|
| 15 |
:root {
|
| 16 |
-
/*
|
| 17 |
-
--bg-
|
| 18 |
-
--text-yellow: #fbbf24;
|
| 19 |
--text-white: #ffffff;
|
| 20 |
-
--text-mute: #94a3b8;
|
| 21 |
|
| 22 |
-
/* Gradients */
|
| 23 |
-
--grad-
|
| 24 |
-
--grad-
|
| 25 |
-
--grad-orange: linear-gradient(135deg, #f97316, #fb923c);
|
| 26 |
-
--grad-blue: linear-gradient(135deg, #3b82f6, #0ea5e9);
|
| 27 |
-
--grad-green: linear-gradient(135deg, #22c55e, #10b981);
|
| 28 |
|
| 29 |
-
|
| 30 |
-
--
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
}
|
| 32 |
|
| 33 |
body {
|
| 34 |
background-color: var(--bg-deep);
|
| 35 |
font-family: 'Inter', sans-serif;
|
| 36 |
-
color:
|
| 37 |
-
margin: 0;
|
| 38 |
-
padding: 0;
|
| 39 |
overflow-x: hidden;
|
| 40 |
}
|
| 41 |
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
}
|
| 47 |
-
.
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
}
|
| 50 |
|
| 51 |
-
/* ---
|
| 52 |
-
.
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
}
|
|
|
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
.
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
-
|
| 70 |
-
.
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
-
.
|
| 78 |
-
.
|
| 79 |
-
.
|
| 80 |
-
.
|
| 81 |
-
.
|
| 82 |
-
|
| 83 |
-
.
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
.leaderboard-section { background: #f8fafc; border-radius: 24px 24px 0 0; padding: 60px 40px; min-height: 100vh; }
|
| 91 |
-
.lb-container { max-width: 1300px; margin: 0 auto; }
|
| 92 |
|
| 93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
-
|
| 96 |
-
.
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
|
|
|
|
|
|
| 100 |
}
|
| 101 |
-
.tab-btn:hover { background: #f1f5f9; color: var(--
|
| 102 |
-
.tab-btn.active { background: var(--
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
/* Controls */
|
| 105 |
-
.controls {
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
|
| 114 |
-
|
| 115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
th:nth-child(2), td:nth-child(2) { text-align: left; }
|
| 117 |
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
|
|
|
| 127 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
</style>
|
| 129 |
</head>
|
| 130 |
<body>
|
|
@@ -132,137 +252,140 @@
|
|
| 132 |
<nav class="navbar">
|
| 133 |
<a href="#" class="nav-logo">
|
| 134 |
<img src="https://africa.dlnlp.ai/simba/images/favicon.png" alt="Logo">
|
| 135 |
-
|
|
|
|
|
|
|
|
|
|
| 136 |
</a>
|
| 137 |
<div class="nav-links">
|
| 138 |
-
<a href="https://arxiv.org/abs/2510.17998"
|
| 139 |
-
<a href="https://github.com/UBC-NLP/simba"
|
| 140 |
-
<a href="https://huggingface.co/datasets/UBC-NLP/simba"
|
| 141 |
-
<a href="#">Models</a>
|
| 142 |
-
<a href="#
|
| 143 |
-
<a href="#">Citation</a>
|
| 144 |
-
<a href="#" class="
|
| 145 |
-
<a href="#" class="login
|
| 146 |
</div>
|
| 147 |
</nav>
|
| 148 |
|
| 149 |
<div class="hero">
|
| 150 |
-
<div class="wave-
|
| 151 |
<div class="hero-content">
|
| 152 |
-
<div class="
|
| 153 |
-
<
|
| 154 |
-
<span style="font-size:12px; color:#555;">Suzhou, China</span>
|
| 155 |
</div>
|
|
|
|
| 156 |
<h1>Voice of a Continent</h1>
|
| 157 |
<h2>Mapping Africa’s Speech Technology</h2>
|
|
|
|
| 158 |
<p>
|
| 159 |
SimbaBench bridges the digital divide with a unified suite for African AI: the largest
|
| 160 |
open-source speech benchmark covering 61 languages, best-in-class multilingual models,
|
| 161 |
-
and an interactive leaderboard.
|
| 162 |
</p>
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
<a href="https://
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
<a href="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
</div>
|
| 170 |
</div>
|
| 171 |
<div class="hero-visual">
|
| 172 |
-
<img src="https://africa.dlnlp.ai/simba/images/simbabench_header.png" alt="Africa
|
| 173 |
</div>
|
| 174 |
</div>
|
| 175 |
|
| 176 |
-
<div class="
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
<div id="loader" style="text-align:center; padding:40px; color:#64748b;">
|
| 181 |
-
<i class="fa-solid fa-circle-notch fa-spin fa-2x"></i><br><br>Loading Leaderboard Data...
|
| 182 |
-
</div>
|
| 183 |
-
|
| 184 |
-
<div id="content" style="display:none;">
|
| 185 |
-
<div class="tabs">
|
| 186 |
-
<button class="tab-btn active" id="tab-btn-asr" onclick="setTab('asr')">Automatic Speech Recognition (ASR)</button>
|
| 187 |
-
<button class="tab-btn" id="tab-btn-tts" onclick="setTab('tts')">Text-to-Speech (TTS)</button>
|
| 188 |
-
<button class="tab-btn" id="tab-btn-slid" onclick="setTab('slid')">Spoken Language Identification (SLID)</button>
|
| 189 |
-
</div>
|
| 190 |
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
<div style="flex-grow:1; text-align:right;">
|
| 198 |
-
<div id="grp-fam" style="display:inline-block;">
|
| 199 |
-
<label>Select Family: </label>
|
| 200 |
-
<select id="asr-select-fam" onchange="renderASR()" style="padding:6px; border-radius:6px;"></select>
|
| 201 |
-
</div>
|
| 202 |
-
<div id="grp-mod" style="display:none;">
|
| 203 |
-
<label>Select Model: </label>
|
| 204 |
-
<select id="asr-select-mod" onchange="renderASR()" style="padding:6px; border-radius:6px;"></select>
|
| 205 |
-
</div>
|
| 206 |
-
</div>
|
| 207 |
-
</div>
|
| 208 |
-
<h3 id="asr-title" style="color:#d97706; font-size:18px;"></h3>
|
| 209 |
-
<div id="asr-legend" style="background:#f1f5f9; padding:10px; font-size:13px; border-radius:6px; margin-bottom:15px; display:none;"></div>
|
| 210 |
-
<div id="asr-table" class="table-wrap"></div>
|
| 211 |
-
</div>
|
| 212 |
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
<
|
|
|
|
| 221 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
|
|
|
| 226 |
</div>
|
|
|
|
|
|
|
|
|
|
| 227 |
</div>
|
| 228 |
|
| 229 |
-
<div
|
| 230 |
-
<
|
|
|
|
| 231 |
</div>
|
| 232 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
</div>
|
| 234 |
|
| 235 |
-
<
|
| 236 |
-
//
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
'Swahili': 'swa', 'Somali': 'som', 'Wolof': 'wol', 'Xhosa': 'xho'
|
| 241 |
-
};
|
| 242 |
|
|
|
|
| 243 |
let DATA = null;
|
| 244 |
let asrMode = 'family';
|
| 245 |
|
| 246 |
-
//
|
| 247 |
fetch('/api/data').then(r=>r.json()).then(d=>{
|
| 248 |
DATA = d;
|
| 249 |
document.getElementById('loader').style.display='none';
|
| 250 |
-
document.getElementById('content').style.display='block';
|
| 251 |
init();
|
| 252 |
-
}).catch(e=>{
|
| 253 |
-
document.getElementById('loader').innerHTML = `<span style="color:red">Failed to load data.</span>`;
|
| 254 |
});
|
| 255 |
|
| 256 |
function init() {
|
| 257 |
-
populate('asr-select
|
| 258 |
-
populate('asr-select-mod', DATA.metadata.models);
|
| 259 |
populate('tts-select', DATA.metadata.tts_models);
|
| 260 |
-
|
| 261 |
-
// Set Initial State Explicitly
|
| 262 |
-
setTab('asr');
|
| 263 |
-
renderASR();
|
| 264 |
-
renderTTS();
|
| 265 |
-
renderSLID();
|
| 266 |
}
|
| 267 |
|
| 268 |
function populate(id, list) {
|
|
@@ -270,41 +393,40 @@
|
|
| 270 |
list.forEach(i=>{ let o=document.createElement('option'); o.value=i; o.text=i; s.add(o); });
|
| 271 |
}
|
| 272 |
function fmt(n) { return (n==null)?'N/A':n.toFixed(2); }
|
| 273 |
-
function getIso(name) { return NAME_TO_ISO[name] || name.substring(0,3).toLowerCase(); }
|
| 274 |
|
| 275 |
-
// ---
|
| 276 |
function renderASR() {
|
|
|
|
| 277 |
const div = document.getElementById('asr-table');
|
| 278 |
const legend = document.getElementById('asr-legend');
|
| 279 |
let html='';
|
| 280 |
|
| 281 |
if(asrMode==='family'){
|
| 282 |
-
|
| 283 |
-
document.getElementById('asr-title').innerText = `Results for Family: ${val}`;
|
| 284 |
const d = DATA.asr.by_family[val];
|
| 285 |
if(!d) return;
|
| 286 |
|
|
|
|
| 287 |
legend.style.display = 'block';
|
| 288 |
-
legend.innerHTML = `<b>Codes:</b> ` + d.languages.map(l => `<span style="margin-right:
|
| 289 |
|
| 290 |
-
html = `<table><thead><tr><th>Model</th><th>Avg WER/CER <i class="fa-solid fa-arrow-down
|
| 291 |
-
d.languages.forEach(l => html += `<th>${
|
| 292 |
html += `</tr></thead><tbody>`;
|
| 293 |
|
| 294 |
d.data.forEach(r => {
|
| 295 |
html += `<tr><td>${r.Model}</td><td style="font-weight:bold; background:#f8fafc">${fmt(r.Avg_WER)} / ${fmt(r.Avg_CER)}</td>`;
|
| 296 |
d.languages.forEach(l => {
|
| 297 |
-
let w=r[`WER_${l}`], c=r[`CER_${l}`];
|
| 298 |
html += `<td>${(w!=null)?fmt(w)+'/'+fmt(c):'-'}</td>`;
|
| 299 |
});
|
| 300 |
html += `</tr>`;
|
| 301 |
});
|
| 302 |
} else {
|
| 303 |
-
|
| 304 |
-
document.getElementById('asr-title').innerText = `Results for Model: ${val}`;
|
| 305 |
legend.style.display = 'none';
|
| 306 |
const rows = DATA.asr.by_model[val];
|
| 307 |
-
html = `<table><thead><tr><th>Language</th><th>Family</th><th>WER (%)
|
| 308 |
rows.forEach(r => {
|
| 309 |
html += `<tr><td>${r.Language}</td><td>${r.Family}</td><td>${fmt(r.WER)}</td><td>${fmt(r.CER)}</td></tr>`;
|
| 310 |
});
|
|
@@ -312,32 +434,26 @@
|
|
| 312 |
div.innerHTML = html;
|
| 313 |
}
|
| 314 |
|
| 315 |
-
// ---
|
| 316 |
function renderTTS() {
|
| 317 |
const val = document.getElementById('tts-select').value;
|
| 318 |
-
document.getElementById('tts-title').innerText = `
|
| 319 |
const rows = DATA.tts[val];
|
| 320 |
if(!rows) return;
|
| 321 |
|
| 322 |
const metrics = [
|
| 323 |
-
{k:'wer', l:'WER', h:false}, {k:'mcd', l:'MCD', h:false},
|
| 324 |
-
{k:'
|
| 325 |
-
{k:'pesq', l:'PESQ', h:true}, {k:'utmos', l:'UTMOS', h:true},
|
| 326 |
-
{k:'speechbleu', l:'SpBLEU', h:true}, {k:'speechbert_score', l:'SpBERT', h:true}
|
| 327 |
];
|
| 328 |
|
| 329 |
let sums={}, c=0;
|
| 330 |
metrics.forEach(m=>sums[m.k]=0);
|
| 331 |
rows.forEach(r=>{ metrics.forEach(m=>sums[m.k]+=(r[m.k]||0)); c++; });
|
| 332 |
-
let
|
| 333 |
-
document.getElementById('tts-summary').innerHTML = "
|
| 334 |
|
| 335 |
let html = `<table><thead><tr><th>Language</th>`;
|
| 336 |
-
metrics.forEach(m => {
|
| 337 |
-
let icon = m.h ? 'up' : 'down';
|
| 338 |
-
let col = m.h ? 'green' : '#d97706';
|
| 339 |
-
html += `<th>${m.l} <i class="fa-solid fa-arrow-${icon}" style="color:${col}"></i></th>`;
|
| 340 |
-
});
|
| 341 |
html += `</tr></thead><tbody>`;
|
| 342 |
rows.forEach(r => {
|
| 343 |
html += `<tr><td>${r.language}</td>`;
|
|
@@ -347,41 +463,38 @@
|
|
| 347 |
document.getElementById('tts-table').innerHTML = html;
|
| 348 |
}
|
| 349 |
|
| 350 |
-
// ---
|
| 351 |
function renderSLID() {
|
| 352 |
-
let html = `<table><thead><tr><th>Language</th><th>MMS
|
| 353 |
DATA.slid.forEach(r => {
|
| 354 |
let m = r['MMS-LID-1024'], s = r['Simba-SLID'];
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
});
|
| 359 |
document.getElementById('slid-table').innerHTML = html;
|
| 360 |
}
|
| 361 |
|
| 362 |
-
// ---
|
| 363 |
-
window.setTab = (id) => {
|
| 364 |
-
// Hide all views
|
| 365 |
document.querySelectorAll('.view').forEach(e => e.classList.remove('active'));
|
| 366 |
document.querySelectorAll('.tab-btn').forEach(e => e.classList.remove('active'));
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
document.getElementById(id).classList.add('active');
|
| 370 |
-
document.getElementById(`tab-btn-${id}`).classList.add('active');
|
| 371 |
};
|
| 372 |
|
| 373 |
window.setASRMode = (m) => {
|
| 374 |
asrMode = m;
|
| 375 |
-
document.getElementById('grp-fam').style.display = m==='family'?'inline-block':'none';
|
| 376 |
-
document.getElementById('grp-mod').style.display = m==='model'?'inline-block':'none';
|
| 377 |
const b1 = document.getElementById('btn-fam');
|
| 378 |
const b2 = document.getElementById('btn-mod');
|
| 379 |
if(m==='family') {
|
| 380 |
-
b1.className
|
| 381 |
-
b2.className
|
|
|
|
| 382 |
} else {
|
| 383 |
-
b2.className
|
| 384 |
-
b1.className
|
|
|
|
| 385 |
}
|
| 386 |
renderASR();
|
| 387 |
}
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Voice of a Continent | SimbaBench</title>
|
| 7 |
<link rel="icon" type="image/jpeg" href="https://africa.dlnlp.ai/simba/images/favicon.png">
|
| 8 |
|
| 9 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
|
|
| 13 |
|
| 14 |
<style>
|
| 15 |
:root {
|
| 16 |
+
--bg-deep: #1e1b4b; /* Deep Navy */
|
| 17 |
+
--bg-lighter: #262357; /* Slightly lighter for cards */
|
| 18 |
+
--text-yellow: #fbbf24; /* Brand Yellow */
|
| 19 |
--text-white: #ffffff;
|
| 20 |
+
--text-mute: #94a3b8;
|
| 21 |
|
| 22 |
+
/* Buttons Gradients */
|
| 23 |
+
--grad-blue: linear-gradient(90deg, #3b82f6, #0ea5e9);
|
| 24 |
+
--grad-yellow: linear-gradient(90deg, #eab308, #ca8a04);
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
+
/* Hero Buttons */
|
| 27 |
+
--btn-red: #ef4444;
|
| 28 |
+
--btn-purple: #8b5cf6;
|
| 29 |
+
--btn-orange: #f97316;
|
| 30 |
+
--btn-blue: #3b82f6;
|
| 31 |
+
--btn-green: #22c55e;
|
| 32 |
}
|
| 33 |
|
| 34 |
body {
|
| 35 |
background-color: var(--bg-deep);
|
| 36 |
font-family: 'Inter', sans-serif;
|
| 37 |
+
color: var(--text-white);
|
| 38 |
+
margin: 0; padding: 0;
|
|
|
|
| 39 |
overflow-x: hidden;
|
| 40 |
}
|
| 41 |
|
| 42 |
+
a { text-decoration: none; transition: 0.2s; }
|
| 43 |
+
|
| 44 |
+
/* --- NAVBAR --- */
|
| 45 |
+
.navbar {
|
| 46 |
+
padding: 20px 40px;
|
| 47 |
+
display: flex;
|
| 48 |
+
justify-content: space-between;
|
| 49 |
+
align-items: center;
|
| 50 |
+
background: transparent;
|
| 51 |
+
z-index: 100;
|
| 52 |
+
position: relative;
|
| 53 |
+
}
|
| 54 |
+
.nav-logo {
|
| 55 |
+
color: white;
|
| 56 |
+
font-family: 'Rubik', sans-serif;
|
| 57 |
+
font-weight: 700;
|
| 58 |
+
font-size: 22px;
|
| 59 |
+
display: flex; align-items: center; gap: 12px;
|
| 60 |
+
}
|
| 61 |
+
.nav-logo img { height: 40px; }
|
| 62 |
+
.nav-text { display: flex; flex-direction: column; line-height: 1.1; }
|
| 63 |
+
.nav-text span:first-child { font-size: 14px; color: var(--text-yellow); }
|
| 64 |
+
|
| 65 |
+
.nav-links { display: flex; gap: 25px; align-items: center; }
|
| 66 |
+
.nav-link { color: #e2e8f0; font-size: 15px; font-weight: 500; }
|
| 67 |
+
.nav-link:hover { color: var(--text-yellow); }
|
| 68 |
+
|
| 69 |
+
.btn-submit {
|
| 70 |
+
background: var(--grad-blue);
|
| 71 |
+
color: white !important;
|
| 72 |
+
padding: 10px 24px;
|
| 73 |
+
border-radius: 30px;
|
| 74 |
+
font-weight: 600;
|
| 75 |
+
font-size: 14px;
|
| 76 |
+
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
|
| 77 |
}
|
| 78 |
+
.btn-login {
|
| 79 |
+
background: var(--text-yellow);
|
| 80 |
+
color: var(--bg-deep) !important;
|
| 81 |
+
padding: 10px 24px;
|
| 82 |
+
border-radius: 30px;
|
| 83 |
+
font-weight: 700;
|
| 84 |
+
font-size: 14px;
|
| 85 |
+
box-shadow: 0 4px 12px rgba(251, 191, 36, 0.4);
|
| 86 |
}
|
| 87 |
|
| 88 |
+
/* --- HERO --- */
|
| 89 |
+
.hero {
|
| 90 |
+
display: flex;
|
| 91 |
+
align-items: center;
|
| 92 |
+
max-width: 1400px;
|
| 93 |
+
margin: 60px auto 100px;
|
| 94 |
+
padding: 0 40px;
|
| 95 |
+
position: relative;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
.hero-content { flex: 1; z-index: 2; }
|
| 99 |
+
|
| 100 |
+
.conf-badge {
|
| 101 |
+
background: white;
|
| 102 |
+
color: black;
|
| 103 |
+
display: inline-flex;
|
| 104 |
+
align-items: center;
|
| 105 |
+
gap: 10px;
|
| 106 |
+
padding: 6px 16px;
|
| 107 |
+
border-radius: 8px;
|
| 108 |
+
margin-bottom: 30px;
|
| 109 |
+
font-weight: 700;
|
| 110 |
+
font-size: 14px;
|
| 111 |
}
|
| 112 |
+
.conf-badge i { color: #cc0000; font-size: 18px; }
|
| 113 |
|
| 114 |
+
.hero h1 {
|
| 115 |
+
font-family: 'Rubik', sans-serif;
|
| 116 |
+
font-size: 64px;
|
| 117 |
+
font-weight: 800;
|
| 118 |
+
margin: 0;
|
| 119 |
+
line-height: 1.1;
|
| 120 |
+
}
|
| 121 |
+
.hero h2 {
|
| 122 |
+
font-family: 'Rubik', sans-serif;
|
| 123 |
+
font-size: 32px;
|
| 124 |
+
color: var(--text-yellow);
|
| 125 |
+
margin: 15px 0 30px;
|
| 126 |
+
font-weight: 700;
|
| 127 |
+
}
|
| 128 |
+
.hero p {
|
| 129 |
+
color: #cbd5e1;
|
| 130 |
+
font-size: 18px;
|
| 131 |
+
line-height: 1.6;
|
| 132 |
+
max-width: 650px;
|
| 133 |
+
margin-bottom: 50px;
|
| 134 |
+
}
|
| 135 |
|
| 136 |
+
.hero-actions { display: flex; gap: 15px; flex-wrap: wrap; }
|
| 137 |
+
.action-btn {
|
| 138 |
+
display: flex; align-items: center; gap: 8px;
|
| 139 |
+
padding: 12px 24px;
|
| 140 |
+
border-radius: 30px;
|
| 141 |
+
color: white;
|
| 142 |
+
font-weight: 600;
|
| 143 |
+
font-size: 15px;
|
| 144 |
+
transition: transform 0.2s;
|
| 145 |
+
}
|
| 146 |
+
.action-btn:hover { transform: translateY(-3px); color: white; }
|
| 147 |
|
| 148 |
+
.bg-red { background: var(--btn-red); box-shadow: 0 8px 20px rgba(239, 68, 68, 0.3); }
|
| 149 |
+
.bg-purple { background: var(--btn-purple); box-shadow: 0 8px 20px rgba(139, 92, 246, 0.3); }
|
| 150 |
+
.bg-orange { background: var(--btn-orange); box-shadow: 0 8px 20px rgba(249, 115, 22, 0.3); }
|
| 151 |
+
.bg-blue { background: var(--btn-blue); box-shadow: 0 8px 20px rgba(59, 130, 246, 0.3); }
|
| 152 |
+
.bg-green { background: var(--btn-green); box-shadow: 0 8px 20px rgba(34, 197, 94, 0.3); }
|
| 153 |
+
|
| 154 |
+
.hero-visual {
|
| 155 |
+
flex: 1;
|
| 156 |
+
display: flex;
|
| 157 |
+
justify-content: flex-end;
|
| 158 |
+
position: relative;
|
| 159 |
+
}
|
| 160 |
+
.hero-visual img { max-width: 100%; height: auto; z-index: 1; }
|
|
|
|
|
|
|
| 161 |
|
| 162 |
+
/* Wave */
|
| 163 |
+
.wave-container {
|
| 164 |
+
position: absolute;
|
| 165 |
+
top: 20%;
|
| 166 |
+
left: 0;
|
| 167 |
+
right: 0;
|
| 168 |
+
height: 400px;
|
| 169 |
+
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNDQwIDMyMCI+PHBhdGggZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjAzIiBkPSJNMCwxNjBMMzAsMTQ5LjNDNjAsMTM5LDEyMCwxMTcsMTgwLDExN0MyNDAsMTE3LDMwMCwxMzksMzYwLDE0NCxDNDIwLDE0OSw0ODAsMTM5LDU0MCwxMjIuN0M2MDAsMTA3LDY2MCw4NSw3MjAsODUuM0M3ODAsODUsODQwLDEwNyw5MDAsMTI4Qzk2MCwxNDksMTAyMCwxNzEsMTA4MCwxNzAuN0MxMTQwLDE3MSwxMjAwLDE0OSwxMjYwLDEzOC43QzEzMjAsMTI4LDEzODAsMTI4LDE0MTAsMTI4TDE0NDAsMTI4TDE0NDAsMzIwTDE0MTAsMzIwQzEzODAsMzIwLDEzMjAsMzIwLDEyNjAsMzIwQzEyMDAsMzIwLDExNDAsMzIwLDEwODAsMzIwQzEwMjAsMzIwLDk2MCwzMjAsOTAwLDMyMEM4NDAsMzIwLDc4MCwzMjAsNzIwLDMyMEM2NjAsMzIwLDYwMCwzMjAsNTQwLDMyMEM0ODAsMzIwLDQyMCwzMjAsMzYwLDMyMEMzMDAsMzIwLDI0MCwzMjAsMTgwLDMyMEMxMjAsMzIwLDYwLDMyMCwzMCwzMjBMMCwzMjBaIj48L3BhdGg+PC9zdmc+');
|
| 170 |
+
background-size: cover;
|
| 171 |
+
opacity: 0.5;
|
| 172 |
+
z-index: 0;
|
| 173 |
+
pointer-events: none;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
/* --- MAIN CONTENT AREA --- */
|
| 177 |
+
.main-card {
|
| 178 |
+
background: white;
|
| 179 |
+
border-radius: 24px;
|
| 180 |
+
margin: 0 40px 60px;
|
| 181 |
+
padding: 40px;
|
| 182 |
+
color: #0f172a;
|
| 183 |
+
min-height: 600px;
|
| 184 |
+
}
|
| 185 |
|
| 186 |
+
.tabs { display: flex; gap: 15px; border-bottom: 2px solid #e2e8f0; margin-bottom: 30px; padding-bottom: 10px; }
|
| 187 |
+
.tab-btn {
|
| 188 |
+
background: none; border: none;
|
| 189 |
+
font-size: 16px; font-weight: 600; color: #64748b;
|
| 190 |
+
padding: 10px 20px; cursor: pointer;
|
| 191 |
+
transition: 0.3s;
|
| 192 |
+
border-radius: 8px;
|
| 193 |
}
|
| 194 |
+
.tab-btn:hover { background: #f1f5f9; color: var(--bg-deep); }
|
| 195 |
+
.tab-btn.active { background: var(--bg-deep); color: white; }
|
| 196 |
+
|
| 197 |
+
.view { display: none; animation: fadeIn 0.4s; }
|
| 198 |
+
.view.active { display: block; }
|
| 199 |
|
| 200 |
/* Controls */
|
| 201 |
+
.controls {
|
| 202 |
+
background: #f8fafc; padding: 20px; border-radius: 12px;
|
| 203 |
+
display: flex; gap: 20px; align-items: center; margin-bottom: 20px; flex-wrap: wrap;
|
| 204 |
+
}
|
| 205 |
+
select {
|
| 206 |
+
padding: 10px; border-radius: 8px; border: 1px solid #cbd5e1;
|
| 207 |
+
font-size: 14px; min-width: 250px;
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
/* Table */
|
| 211 |
+
.table-wrap { overflow-x: auto; border: 1px solid #e2e8f0; border-radius: 12px; }
|
| 212 |
+
table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
| 213 |
+
th {
|
| 214 |
+
background: #f1f5f9; color: #0f172a; font-weight: 700;
|
| 215 |
+
padding: 16px; text-align: center; border-bottom: 2px solid #e2e8f0;
|
| 216 |
+
white-space: nowrap; vertical-align: middle;
|
| 217 |
+
}
|
| 218 |
+
td {
|
| 219 |
+
padding: 14px; border-bottom: 1px solid #e2e8f0; text-align: center; color: #334155;
|
| 220 |
+
}
|
| 221 |
+
tr:hover td { background: #f8fafc; }
|
| 222 |
|
| 223 |
+
/* Sticky First Column */
|
| 224 |
+
th:first-child, td:first-child {
|
| 225 |
+
position: sticky; left: 0; background: white; z-index: 2;
|
| 226 |
+
text-align: left; font-weight: 700; color: #0f172a;
|
| 227 |
+
border-right: 2px solid #f1f5f9;
|
| 228 |
+
}
|
| 229 |
+
thead th:first-child { background: #f1f5f9; z-index: 3; }
|
| 230 |
th:nth-child(2), td:nth-child(2) { text-align: left; }
|
| 231 |
|
| 232 |
+
/* Citation Box */
|
| 233 |
+
.citation-box {
|
| 234 |
+
background: #0f172a;
|
| 235 |
+
color: #cbd5e1;
|
| 236 |
+
padding: 20px;
|
| 237 |
+
border-radius: 12px;
|
| 238 |
+
font-family: monospace;
|
| 239 |
+
white-space: pre-wrap;
|
| 240 |
+
margin-top: 20px;
|
| 241 |
+
text-align: left;
|
| 242 |
}
|
| 243 |
+
|
| 244 |
+
/* Footer */
|
| 245 |
+
.footer { text-align: center; padding-bottom: 40px; color: #94a3b8; font-size: 14px; }
|
| 246 |
+
|
| 247 |
+
@keyframes fadeIn { from{opacity:0; transform:translateY(10px)} to{opacity:1; transform:translateY(0)} }
|
| 248 |
</style>
|
| 249 |
</head>
|
| 250 |
<body>
|
|
|
|
| 252 |
<nav class="navbar">
|
| 253 |
<a href="#" class="nav-logo">
|
| 254 |
<img src="https://africa.dlnlp.ai/simba/images/favicon.png" alt="Logo">
|
| 255 |
+
<div class="nav-text">
|
| 256 |
+
<span>Voice of a</span>
|
| 257 |
+
Continent
|
| 258 |
+
</div>
|
| 259 |
</a>
|
| 260 |
<div class="nav-links">
|
| 261 |
+
<a href="https://arxiv.org/abs/2510.17998" class="nav-link">Paper</a>
|
| 262 |
+
<a href="https://github.com/UBC-NLP/simba" class="nav-link">Pipeline</a>
|
| 263 |
+
<a href="https://huggingface.co/datasets/UBC-NLP/simba" class="nav-link">Dataset</a>
|
| 264 |
+
<a href="#" class="nav-link">Models</a>
|
| 265 |
+
<a href="#" class="nav-link" style="color:var(--text-yellow)">Leaderboard</a>
|
| 266 |
+
<a href="#citation" class="nav-link">Citation</a>
|
| 267 |
+
<a href="#" class="btn-submit">Submit New Results</a>
|
| 268 |
+
<a href="#" class="btn-login">Login</a>
|
| 269 |
</div>
|
| 270 |
</nav>
|
| 271 |
|
| 272 |
<div class="hero">
|
| 273 |
+
<div class="wave-container"></div>
|
| 274 |
<div class="hero-content">
|
| 275 |
+
<div class="conf-badge">
|
| 276 |
+
<i class="fa-solid fa-location-dot"></i> EMNLP 2025 · Suzhou, China
|
|
|
|
| 277 |
</div>
|
| 278 |
+
|
| 279 |
<h1>Voice of a Continent</h1>
|
| 280 |
<h2>Mapping Africa’s Speech Technology</h2>
|
| 281 |
+
|
| 282 |
<p>
|
| 283 |
SimbaBench bridges the digital divide with a unified suite for African AI: the largest
|
| 284 |
open-source speech benchmark covering 61 languages, best-in-class multilingual models,
|
| 285 |
+
and an interactive leaderboard driving the future of speech technology.
|
| 286 |
</p>
|
| 287 |
+
|
| 288 |
+
<div class="hero-actions">
|
| 289 |
+
<a href="https://arxiv.org/abs/2510.17998" target="_blank" class="action-btn bg-red">
|
| 290 |
+
<i class="fa-regular fa-file-pdf"></i> Read Paper
|
| 291 |
+
</a>
|
| 292 |
+
<a href="https://github.com/UBC-NLP/simba" target="_blank" class="action-btn bg-purple">
|
| 293 |
+
<i class="fa-solid fa-code-branch"></i> Pipeline
|
| 294 |
+
</a>
|
| 295 |
+
<a href="https://huggingface.co/datasets/UBC-NLP/simba" target="_blank" class="action-btn bg-orange">
|
| 296 |
+
<i class="fa-solid fa-database"></i> Dataset
|
| 297 |
+
</a>
|
| 298 |
+
<a href="#" class="action-btn bg-blue">
|
| 299 |
+
<i class="fa-solid fa-bolt"></i> Models
|
| 300 |
+
</a>
|
| 301 |
+
<a href="#board" class="action-btn bg-green">
|
| 302 |
+
<i class="fa-solid fa-trophy"></i> Leaderboard
|
| 303 |
+
</a>
|
| 304 |
</div>
|
| 305 |
</div>
|
| 306 |
<div class="hero-visual">
|
| 307 |
+
<img src="https://africa.dlnlp.ai/simba/images/simbabench_header.png" alt="Africa Map">
|
| 308 |
</div>
|
| 309 |
</div>
|
| 310 |
|
| 311 |
+
<div class="main-card" id="board">
|
| 312 |
+
|
| 313 |
+
<div id="loader"><i class="fa-solid fa-circle-notch fa-spin fa-2x" style="color:#0f172a"></i><br>Loading Data...</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 314 |
|
| 315 |
+
<div id="app-content" style="display:none;">
|
| 316 |
+
<div class="tabs">
|
| 317 |
+
<button class="tab-btn active" onclick="setTab('asr', this)">Automatic Speech Recognition (ASR)</button>
|
| 318 |
+
<button class="tab-btn" onclick="setTab('tts', this)">Text-to-Speech (TTS)</button>
|
| 319 |
+
<button class="tab-btn" onclick="setTab('slid', this)">Spoken Language Identification (SLID)</button>
|
| 320 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 321 |
|
| 322 |
+
<div id="asr" class="view active">
|
| 323 |
+
<div class="controls">
|
| 324 |
+
<span style="font-weight:700;">View Mode:</span>
|
| 325 |
+
<button id="btn-fam" class="action-btn bg-blue" style="padding:8px 16px; font-size:12px; box-shadow:none;" onclick="setASRMode('family')">By Family</button>
|
| 326 |
+
<button id="btn-mod" class="action-btn" style="padding:8px 16px; font-size:12px; background:#e2e8f0; color:#334155;" onclick="setASRMode('model')">By Model</button>
|
| 327 |
+
|
| 328 |
+
<div style="flex-grow:1; text-align:right;">
|
| 329 |
+
<span style="font-weight:600; margin-right:10px;">Select:</span>
|
| 330 |
+
<select id="asr-select" onchange="renderASR()"></select>
|
| 331 |
</div>
|
| 332 |
+
</div>
|
| 333 |
+
|
| 334 |
+
<h3 id="asr-title" style="color:#d97706; margin-bottom:15px;"></h3>
|
| 335 |
+
<div id="asr-legend" style="margin-bottom:15px; font-size:13px; color:#64748b; line-height:1.6;"></div>
|
| 336 |
+
<div id="asr-table" class="table-wrap"></div>
|
| 337 |
+
</div>
|
| 338 |
|
| 339 |
+
<div id="tts" class="view">
|
| 340 |
+
<div class="controls">
|
| 341 |
+
<span style="font-weight:600;">Select Model:</span>
|
| 342 |
+
<select id="tts-select" onchange="renderTTS()"></select>
|
| 343 |
</div>
|
| 344 |
+
<h3 id="tts-title" style="color:#d97706; margin-bottom:10px;"></h3>
|
| 345 |
+
<div id="tts-summary" style="margin-bottom:20px; font-weight:600; color:#0f172a;"></div>
|
| 346 |
+
<div id="tts-table" class="table-wrap"></div>
|
| 347 |
</div>
|
| 348 |
|
| 349 |
+
<div id="slid" class="view">
|
| 350 |
+
<h3 style="color:#d97706;">Spoken Language Identification Leaderboard</h3>
|
| 351 |
+
<div id="slid-table" class="table-wrap"></div>
|
| 352 |
</div>
|
| 353 |
</div>
|
| 354 |
+
|
| 355 |
+
<div id="citation" style="margin-top:60px;">
|
| 356 |
+
<h3>Citation</h3>
|
| 357 |
+
<p>If you use Simba, please cite our <a href="https://africa.dlnlp.ai/sahara/" style="color:#d97706; font-weight:bold;">ACL2025 paper</a>.</p>
|
| 358 |
+
<div class="citation-box">@inproceedings{simba2025,
|
| 359 |
+
title={Simba: A Unified Benchmark for Speech Tasks in African Languages},
|
| 360 |
+
author={Put Authors Here},
|
| 361 |
+
booktitle={ACL},
|
| 362 |
+
year={2025}
|
| 363 |
+
}</div>
|
| 364 |
+
</div>
|
| 365 |
</div>
|
| 366 |
|
| 367 |
+
<div class="footer">
|
| 368 |
+
<img src="https://africa.dlnlp.ai/sahara//img/sahara_web_sponsers.jpg" width="250" style="opacity:0.8; margin-bottom:15px;">
|
| 369 |
+
<br>
|
| 370 |
+
© 2025 Simba Benchmark.
|
| 371 |
+
</div>
|
|
|
|
|
|
|
| 372 |
|
| 373 |
+
<script>
|
| 374 |
let DATA = null;
|
| 375 |
let asrMode = 'family';
|
| 376 |
|
| 377 |
+
// Fetch Data
|
| 378 |
fetch('/api/data').then(r=>r.json()).then(d=>{
|
| 379 |
DATA = d;
|
| 380 |
document.getElementById('loader').style.display='none';
|
| 381 |
+
document.getElementById('app-content').style.display='block';
|
| 382 |
init();
|
|
|
|
|
|
|
| 383 |
});
|
| 384 |
|
| 385 |
function init() {
|
| 386 |
+
populate('asr-select', DATA.metadata.families); // Default family
|
|
|
|
| 387 |
populate('tts-select', DATA.metadata.tts_models);
|
| 388 |
+
renderASR(); renderTTS(); renderSLID();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 389 |
}
|
| 390 |
|
| 391 |
function populate(id, list) {
|
|
|
|
| 393 |
list.forEach(i=>{ let o=document.createElement('option'); o.value=i; o.text=i; s.add(o); });
|
| 394 |
}
|
| 395 |
function fmt(n) { return (n==null)?'N/A':n.toFixed(2); }
|
|
|
|
| 396 |
|
| 397 |
+
// --- ASR ---
|
| 398 |
function renderASR() {
|
| 399 |
+
const val = document.getElementById('asr-select').value;
|
| 400 |
const div = document.getElementById('asr-table');
|
| 401 |
const legend = document.getElementById('asr-legend');
|
| 402 |
let html='';
|
| 403 |
|
| 404 |
if(asrMode==='family'){
|
| 405 |
+
document.getElementById('asr-title').innerText = `Family: ${val}`;
|
|
|
|
| 406 |
const d = DATA.asr.by_family[val];
|
| 407 |
if(!d) return;
|
| 408 |
|
| 409 |
+
// Use the ISO from data directly (languages is array of {name, iso})
|
| 410 |
legend.style.display = 'block';
|
| 411 |
+
legend.innerHTML = `<b>Codes:</b> ` + d.languages.map(l => `<span style="margin-right:12px"><b>${l.iso}</b>=${l.name}</span>`).join("");
|
| 412 |
|
| 413 |
+
html = `<table><thead><tr><th>Model</th><th>Avg WER/CER <i class="fa-solid fa-arrow-down" style="font-size:10px; color:#d97706"></i></th>`;
|
| 414 |
+
d.languages.forEach(l => html += `<th>${l.iso}</th>`);
|
| 415 |
html += `</tr></thead><tbody>`;
|
| 416 |
|
| 417 |
d.data.forEach(r => {
|
| 418 |
html += `<tr><td>${r.Model}</td><td style="font-weight:bold; background:#f8fafc">${fmt(r.Avg_WER)} / ${fmt(r.Avg_CER)}</td>`;
|
| 419 |
d.languages.forEach(l => {
|
| 420 |
+
let w=r[`WER_${l.name}`], c=r[`CER_${l.name}`];
|
| 421 |
html += `<td>${(w!=null)?fmt(w)+'/'+fmt(c):'-'}</td>`;
|
| 422 |
});
|
| 423 |
html += `</tr>`;
|
| 424 |
});
|
| 425 |
} else {
|
| 426 |
+
document.getElementById('asr-title').innerText = `Model: ${val}`;
|
|
|
|
| 427 |
legend.style.display = 'none';
|
| 428 |
const rows = DATA.asr.by_model[val];
|
| 429 |
+
html = `<table><thead><tr><th>Language</th><th>Family</th><th>WER (%)</th><th>CER (%)</th></tr></thead><tbody>`;
|
| 430 |
rows.forEach(r => {
|
| 431 |
html += `<tr><td>${r.Language}</td><td>${r.Family}</td><td>${fmt(r.WER)}</td><td>${fmt(r.CER)}</td></tr>`;
|
| 432 |
});
|
|
|
|
| 434 |
div.innerHTML = html;
|
| 435 |
}
|
| 436 |
|
| 437 |
+
// --- TTS ---
|
| 438 |
function renderTTS() {
|
| 439 |
const val = document.getElementById('tts-select').value;
|
| 440 |
+
document.getElementById('tts-title').innerText = `Model: ${val}`;
|
| 441 |
const rows = DATA.tts[val];
|
| 442 |
if(!rows) return;
|
| 443 |
|
| 444 |
const metrics = [
|
| 445 |
+
{k:'wer', l:'WER', h:false}, {k:'mcd', l:'MCD', h:false}, {k:'logf0rmse', l:'LogF0', h:false},
|
| 446 |
+
{k:'pesq', l:'PESQ', h:true}, {k:'utmos', l:'UTMOS', h:true}, {k:'speechbleu', l:'BLEU', h:true}
|
|
|
|
|
|
|
| 447 |
];
|
| 448 |
|
| 449 |
let sums={}, c=0;
|
| 450 |
metrics.forEach(m=>sums[m.k]=0);
|
| 451 |
rows.forEach(r=>{ metrics.forEach(m=>sums[m.k]+=(r[m.k]||0)); c++; });
|
| 452 |
+
let sumH = metrics.map(m=> `${m.l}: <b>${fmt(sums[m.k]/c)}</b>`).join(" | ");
|
| 453 |
+
document.getElementById('tts-summary').innerHTML = "Averages: " + sumH;
|
| 454 |
|
| 455 |
let html = `<table><thead><tr><th>Language</th>`;
|
| 456 |
+
metrics.forEach(m => html += `<th>${m.l} <i class="fa-solid fa-arrow-${m.h?'up':'down'}" style="color:${m.h?'green':'orange'};font-size:10px"></i></th>`);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 457 |
html += `</tr></thead><tbody>`;
|
| 458 |
rows.forEach(r => {
|
| 459 |
html += `<tr><td>${r.language}</td>`;
|
|
|
|
| 463 |
document.getElementById('tts-table').innerHTML = html;
|
| 464 |
}
|
| 465 |
|
| 466 |
+
// --- SLID ---
|
| 467 |
function renderSLID() {
|
| 468 |
+
let html = `<table><thead><tr><th>Language</th><th>MMS</th><th>Simba</th></tr></thead><tbody>`;
|
| 469 |
DATA.slid.forEach(r => {
|
| 470 |
let m = r['MMS-LID-1024'], s = r['Simba-SLID'];
|
| 471 |
+
html += `<tr><td>${r.Language}</td>
|
| 472 |
+
<td style="color:${m>s?'green':'#333'}; font-weight:${m>s?'bold':'normal'}">${fmt(m)}</td>
|
| 473 |
+
<td style="color:${s>m?'green':'#333'}; font-weight:${s>m?'bold':'normal'}">${fmt(s)}</td></tr>`;
|
| 474 |
});
|
| 475 |
document.getElementById('slid-table').innerHTML = html;
|
| 476 |
}
|
| 477 |
|
| 478 |
+
// --- UI ---
|
| 479 |
+
window.setTab = (id, btn) => {
|
|
|
|
| 480 |
document.querySelectorAll('.view').forEach(e => e.classList.remove('active'));
|
| 481 |
document.querySelectorAll('.tab-btn').forEach(e => e.classList.remove('active'));
|
| 482 |
+
document.getElementById(id).classList.add('active');
|
| 483 |
+
btn.classList.add('active');
|
|
|
|
|
|
|
| 484 |
};
|
| 485 |
|
| 486 |
window.setASRMode = (m) => {
|
| 487 |
asrMode = m;
|
|
|
|
|
|
|
| 488 |
const b1 = document.getElementById('btn-fam');
|
| 489 |
const b2 = document.getElementById('btn-mod');
|
| 490 |
if(m==='family') {
|
| 491 |
+
b1.className="action-btn bg-blue"; b1.style.color="white"; b1.style.background="";
|
| 492 |
+
b2.className="action-btn"; b2.style.background="#e2e8f0"; b2.style.color="#334155";
|
| 493 |
+
populate('asr-select', DATA.metadata.families);
|
| 494 |
} else {
|
| 495 |
+
b2.className="action-btn bg-blue"; b2.style.color="white"; b2.style.background="";
|
| 496 |
+
b1.className="action-btn"; b1.style.background="#e2e8f0"; b1.style.color="#334155";
|
| 497 |
+
populate('asr-select', DATA.metadata.models);
|
| 498 |
}
|
| 499 |
renderASR();
|
| 500 |
}
|