Add the demo (#163)
This commit is contained in:
@@ -4,7 +4,7 @@ weights_path: hf://kyutai/pocket-tts/languages/french_24l/model.safetensors@3959
|
||||
weights_path_without_voice_cloning: hf://kyutai/pocket-tts-without-voice-cloning/languages/french_24l/model.safetensors@d29db7978e464fb90cb3359ee0c69a273b9142cc
|
||||
|
||||
remove_semicolons: true
|
||||
model_recommended_frames_after_eos: 12
|
||||
model_recommended_frames_after_eos: 8
|
||||
|
||||
flow_lm:
|
||||
insert_bos_before_voice: true
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
weights_path: hf://kyutai/pocket-tts/languages/german/model.safetensors@39592ff23c9ef80098bb74895d104c26275fe2c9
|
||||
weights_path_without_voice_cloning: hf://kyutai/pocket-tts-without-voice-cloning/languages/german/model.safetensors@d29db7978e464fb90cb3359ee0c69a273b9142cc
|
||||
|
||||
remove_semicolons: true
|
||||
|
||||
flow_lm:
|
||||
insert_bos_before_voice: true
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
weights_path: hf://kyutai/pocket-tts/languages/german_24l/model.safetensors@39592ff23c9ef80098bb74895d104c26275fe2c9
|
||||
weights_path_without_voice_cloning: hf://kyutai/pocket-tts-without-voice-cloning/languages/german_24l/model.safetensors@d29db7978e464fb90cb3359ee0c69a273b9142cc
|
||||
|
||||
remove_semicolons: true
|
||||
|
||||
flow_lm:
|
||||
insert_bos_before_voice: true
|
||||
|
||||
@@ -7,3 +7,43 @@ DEFAULT_EOS_THRESHOLD = -4.0
|
||||
DEFAULT_FRAMES_AFTER_EOS = None
|
||||
# TODO: make this dynamic since english_2026-04 supports bigger chunks
|
||||
MAX_TOKEN_PER_CHUNK = 50
|
||||
|
||||
DEFAULT_TEXT_FOR_LANGUAGE = {
|
||||
"english": (
|
||||
"Hello world. I am Kyutai's Pocket TTS. "
|
||||
"I'm fast enough to run on small CPUs. "
|
||||
"I hope you'll like me."
|
||||
),
|
||||
"french": (
|
||||
"Bonjour le monde. Je suis le TTS de poche de Kyutai. "
|
||||
"Je suis assez rapide pour fonctionner sur de petits CPU. "
|
||||
"J'espère que vous m'aimerez."
|
||||
),
|
||||
"german": (
|
||||
"Hallo Welt. Ich bin Kyutais Pocket TTS. "
|
||||
"Ich bin schnell genug, um auf kleinen CPUs zu laufen. "
|
||||
"Ich hoffe, du wirst mich mögen."
|
||||
),
|
||||
"portuguese": (
|
||||
"Olá mundo. Eu sou o Pocket TTS da Kyutai. "
|
||||
"Sou rápido o suficiente para rodar em CPUs pequenas. "
|
||||
"Espero que você goste de mim."
|
||||
),
|
||||
"italian": (
|
||||
"Ciao mondo. Sono il Pocket TTS di Kyutai. "
|
||||
"Sono abbastanza veloce da funzionare su piccole CPU. "
|
||||
"Spero che ti piacerò."
|
||||
),
|
||||
"spanish": (
|
||||
"Hola mundo. Soy el Pocket TTS de Kyutai. "
|
||||
"Soy lo suficientemente rápido para funcionar en pequeñas CPU. "
|
||||
"Espero que te guste."
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def get_default_text_for_language(language: str | None) -> str:
|
||||
for key, text in DEFAULT_TEXT_FOR_LANGUAGE.items():
|
||||
if language is not None and key in language:
|
||||
return text
|
||||
return DEFAULT_TEXT_FOR_LANGUAGE[DEFAULT_LANGUAGE]
|
||||
|
||||
+13
-6
@@ -11,7 +11,7 @@ import typer
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, File, Form, HTTPException, UploadFile
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import FileResponse, StreamingResponse
|
||||
from fastapi.responses import HTMLResponse, StreamingResponse
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from pocket_tts.data.audio import stream_audio_chunks
|
||||
@@ -23,6 +23,7 @@ from pocket_tts.default_parameters import (
|
||||
DEFAULT_NOISE_CLAMP,
|
||||
DEFAULT_TEMPERATURE,
|
||||
MAX_TOKEN_PER_CHUNK,
|
||||
get_default_text_for_language,
|
||||
)
|
||||
from pocket_tts.models.tts_model import TTSModel, export_model_state
|
||||
from pocket_tts.utils.logging_utils import enable_logging
|
||||
@@ -58,11 +59,17 @@ web_app.add_middleware(
|
||||
)
|
||||
|
||||
|
||||
@web_app.get("/")
|
||||
@web_app.get("/", response_class=HTMLResponse)
|
||||
async def root():
|
||||
"""Serve the frontend."""
|
||||
static_path = Path(__file__).parent / "static" / "index.html"
|
||||
return FileResponse(static_path)
|
||||
content = static_path.read_text()
|
||||
# Replace the placeholder with the actual default text prompt
|
||||
print(str(tts_model.origin))
|
||||
content = content.replace(
|
||||
"DEFAULT_TEXT_PROMPT", get_default_text_for_language(str(tts_model.origin))
|
||||
)
|
||||
return content
|
||||
|
||||
|
||||
@web_app.get("/health")
|
||||
@@ -214,9 +221,7 @@ def serve(
|
||||
|
||||
@cli_app.command()
|
||||
def generate(
|
||||
text: Annotated[
|
||||
str, typer.Option(help="Text to generate")
|
||||
] = "Hello world. I am Kyutai's Pocket TTS. I'm fast enough to run on small CPUs. I hope you'll like me.",
|
||||
text: Annotated[str, typer.Option(help="Text to generate")] = None,
|
||||
voice: Annotated[
|
||||
str, typer.Option(help="Path to audio conditioning file (voice to clone)")
|
||||
] = DEFAULT_AUDIO_PROMPT,
|
||||
@@ -268,6 +273,8 @@ def generate(
|
||||
"""Generate speech using Kyutai Pocket TTS."""
|
||||
log_level = logging.ERROR if quiet else logging.INFO
|
||||
with enable_logging("pocket_tts", log_level):
|
||||
if text is None:
|
||||
text = get_default_text_for_language(language)
|
||||
if text == "-":
|
||||
# Read text from stdin
|
||||
text = sys.stdin.read()
|
||||
|
||||
@@ -293,6 +293,10 @@ class TTSModel(nn.Module):
|
||||
if config is None and language is None:
|
||||
language = DEFAULT_LANGUAGE
|
||||
if language is not None:
|
||||
if language == "french":
|
||||
raise ValueError(
|
||||
"The french model is not ready yet, please use 'french_24l' instead."
|
||||
)
|
||||
config = CONFIGS_DIR / f"{language}.yaml"
|
||||
config = Path(config)
|
||||
if config.suffix not in (".yaml", ".yml"):
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
class="w-full border rounded p-2"
|
||||
placeholder="Enter your text here..."
|
||||
rows="4"
|
||||
>Hello world. I am Kyutai's Pocket TTS. I'm fast enough to run on small CPUs. I hope you'll like me.</textarea>
|
||||
>DEFAULT_TEXT_PROMPT</textarea>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-4 rounded-lg shadow">
|
||||
@@ -314,7 +314,9 @@
|
||||
formData.append('voice_url', voiceUrl);
|
||||
}
|
||||
|
||||
const response = await fetch('/tts', {
|
||||
const ttsEndpoint = `${window.location.pathname.replace(/\/+$/, '')}/tts`;
|
||||
|
||||
const response = await fetch(ttsEndpoint, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
@@ -392,4 +394,4 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user