Ping Long
feat(ui): stabilize metrics state and expand language samples
d4f1e7c
Raw History Blame Contribute Delete
2.72 kB
/**
* SampleClips.jsx
* "Examples" UI โ€” lets the user click a language button to instantly load
* a sample audio clip, replicating the Hugging Face demo UX.
* Active selection "sticks" with highlighted styling.
*/
import { useState } from 'react';
const SAMPLES = [
{ name: 'english', label: '๐Ÿ‡บ๐Ÿ‡ธ English', file: '/samples/english.wav' },
{ name: 'chinese', label: '๐Ÿ‡จ๐Ÿ‡ณ Chinese', file: '/samples/chinese.wav' },
{ name: 'spanish', label: '๐Ÿ‡ช๐Ÿ‡ธ Spanish', file: '/samples/spanish.wav' },
{ name: 'french', label: '๐Ÿ‡ซ๐Ÿ‡ท French', file: '/samples/french.wav' },
{ name: 'german', label: '๐Ÿ‡ฉ๐Ÿ‡ช German', file: '/samples/german.wav' },
{ name: 'italian', label: '๐Ÿ‡ฎ๐Ÿ‡น Italian', file: '/samples/italian.wav' },
{ name: 'japanese', label: '๐Ÿ‡ฏ๐Ÿ‡ต Japanese', file: '/samples/japanese.wav' },
{ name: 'hindi', label: '๐Ÿ‡ฎ๐Ÿ‡ณ Hindi', file: '/samples/hindi.wav' },
];
export default function SampleClips({ onSampleSelect, disabled }) {
const [loading, setLoading] = useState(null);
const [selected, setSelected] = useState(null);
async function handleClick(sample) {
setLoading(sample.name);
try {
const response = await fetch(sample.file);
if (!response.ok) throw new Error(`Failed to fetch ${sample.file}`);
const blob = await response.blob();
// Detect actual audio format from magic bytes (servers may return
// application/octet-stream for .wav files, and some samples may be
// OGG-encoded despite the .wav extension).
const header = new Uint8Array(await blob.slice(0, 4).arrayBuffer());
const magic = String.fromCharCode(...header);
let mimeType = 'audio/wav';
if (magic === 'OggS') mimeType = 'audio/ogg';
else if (magic === 'fLaC') mimeType = 'audio/flac';
else if (magic.startsWith('\xff\xfb') || magic.startsWith('ID3')) mimeType = 'audio/mpeg';
const file = new File([blob], sample.file.split('/').pop(), { type: mimeType });
setSelected(sample.name);
onSampleSelect(file, sample.name);
} catch (err) {
console.error('Sample clip load failed:', err);
} finally {
setLoading(null);
}
}
return (
<div className="sample-clips">
<p className="sample-clips-hint">Try one of the sample clips.</p>
<div className="sample-clips-row">
{SAMPLES.map((s) => (
<button
key={s.name}
className={`btn ${selected === s.name ? 'btn-sample-active' : 'btn-secondary'}`}
onClick={() => handleClick(s)}
disabled={disabled || loading !== null}
>
{loading === s.name ? 'โ€ฆ' : s.label}
</button>
))}
</div>
</div>
);
}