File size: 3,111 Bytes
aacfb92
bb48ecb
aacfb92
bb48ecb
aacfb92
bb48ecb
 
 
 
aacfb92
 
 
bb48ecb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aacfb92
bb48ecb
 
 
 
 
 
 
 
 
 
 
 
aacfb92
bb48ecb
50a4e0d
bb48ecb
 
aacfb92
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
<!DOCTYPE html>
<html>
<head>
    <title>Kokoro TTS - rapide FR/EN</title>
    <style>
        body { font-family: sans-serif; max-width: 600px; margin: auto; padding: 2rem; }
        textarea, select, input, button { width: 100%; margin: 0.5rem 0; padding: 0.5rem; }
        audio { width: 100%; margin-top: 1rem; }
        .status { margin-top: 1rem; color: gray; }
    </style>
</head>
<body>
    <h1>🗣️ Kokoro TTS (ultra rapide)</h1>
    <textarea id="text" rows="4">Bonjour, ceci est un test de Kokoro. La synthèse est très rapide et naturelle.</textarea>
    <select id="voice"></select>
    <select id="lang">
        <option value="fr">Français</option>
        <option value="en">Anglais</option>
    </select>
    <input type="range" id="speed" min="0.5" max="1.5" step="0.05" value="1.0">
    <span>Vitesse: <span id="speedVal">1.0</span></span>
    <button id="generate">🎤 Générer</button>
    <audio id="audio" controls></audio>
    <div id="status" class="status"></div>

    <script>
        const voiceSelect = document.getElementById('voice');
        const textarea = document.getElementById('text');
        const langSelect = document.getElementById('lang');
        const speedSlider = document.getElementById('speed');
        const speedVal = document.getElementById('speedVal');
        const generateBtn = document.getElementById('generate');
        const audioPlayer = document.getElementById('audio');
        const statusDiv = document.getElementById('status');

        speedSlider.oninput = () => speedVal.innerText = speedSlider.value;

        async function loadVoices() {
            const res = await fetch('/voices');
            const data = await res.json();
            const allVoices = [...data.builtin, ...data.cloned];
            voiceSelect.innerHTML = allVoices.map(v => `<option value="${v}">${v}</option>`).join('');
        }

        generateBtn.onclick = async () => {
            const text = textarea.value.trim();
            const voice = voiceSelect.value;
            const lang = langSelect.value;
            const speed = parseFloat(speedSlider.value);
            if (!text) return;

            statusDiv.innerText = '⏳ Génération en cours...';
            try {
                const response = await fetch('/tts', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ text, voice, speed, lang })
                });
                if (response.ok) {
                    const blob = await response.blob();
                    const url = URL.createObjectURL(blob);
                    audioPlayer.src = url;
                    audioPlayer.play();
                    statusDiv.innerText = '✅ Audio prêt';
                } else {
                    const err = await response.text();
                    statusDiv.innerText = `❌ Erreur: ${err}`;
                }
            } catch(e) {
                statusDiv.innerText = `❌ ${e.message}`;
            }
        };

        loadVoices();
    </script>
</body>
</html>