File size: 7,536 Bytes
2feeb4f
 
 
d88d8e3
 
 
 
 
2feeb4f
d88d8e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2feeb4f
 
d88d8e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2feeb4f
d88d8e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d5b1881
d88d8e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162


import numpy as np
from scipy.io import wavfile
import torch
from parler_tts import ParlerTTSForConditionalGeneration
from transformers import AutoTokenizer
import gradio as gr
import re
from num2words import num2words 

# Vérification de la disponibilité de CUDA
device = "cuda:0" if torch.cuda.is_available() else "cpu"

# Chargement du modèle et du tokenizer
try:
    model = ParlerTTSForConditionalGeneration.from_pretrained("Moustapha91/parler-tts-mutli-wolof", torch_dtype=torch.float16).to(device)
    tokenizer = AutoTokenizer.from_pretrained("Moustapha91/parler-tts-mutli-wolof")
except Exception as e:
    raise RuntimeError(f"Erreur lors du chargement du modèle : {e}")




# Normalisation des nombres
class EnglishNumberNormalizer:
    def __call__(self, text):
        # Trouver tous les nombres dans le texte
        numbers = re.findall(r'\d+', text)
        for number in numbers:
            # Convertir le nombre en mots
            text = text.replace(number, num2words(int(number), lang='fr'))
        return text

number_normalizer = EnglishNumberNormalizer()

# Fonction de prétraitement
def preprocess(text):
    # Normaliser les nombres
    text = number_normalizer(text).strip()
    
    # Remplacer les tirets par des espaces
    text = text.replace("-", " ")
    
    # Ajouter un point à la fin si le texte ne se termine pas par une ponctuation
    if not text.endswith(('.', '!', '?')):
        text += "."
    
    # Traiter les abréviations
    abbreviations_pattern = r'\b[A-Z][A-Z\.]+\b'
    abbreviations = re.findall(abbreviations_pattern, text)
    for abv in abbreviations:
        # Séparer les lettres des abréviations (par exemple, "U.S.A." -> "U S A")
        separated_abv = " ".join(abv.replace(".", ""))
        text = text.replace(abv, separated_abv)
    
    return text

# Texte et description par défaut
default_prompt = "Entreprenariat ci Senegal dafa am solo lool ci yokkuteg koom-koom, di gëna yokk liggéey ak indi gis-gis yu bees ci dëkk bi."
default_description = """A crystal clear and distinct voice, with a moderate reading rate that facilitates understanding. The tone is monotonous, without variations or inflections, which provides a uniform listening experience. The voice is free of background noise and allows for continuous reading, without inappropriate pauses, thus ensuring a constant and pleasant flow."""



# Fonction pour générer l'audio sans segmentation
def generate_audio(prompt, description):
    # Prétraiter le texte
    prompt = preprocess(prompt)
    
    # Génération des IDs d'entrée
    input_ids = tokenizer(description.strip(), return_tensors="pt").input_ids.to(device)
    prompt_input_ids = tokenizer(prompt, return_tensors="pt").input_ids.to(device)

    # Générer l'audio
    generation_config = {
    "temperature": 0.8,           # Contrôle la variabilité de la sortie
    "max_new_tokens": 1000,       # Longueur maximale de la séquence générée
    "do_sample": True,            # Active l'échantillonnage aléatoire
    "top_k": 50,                  # Limite le nombre de tokens considérés
    "repetition_penalty": 1.2,    # Pénalise la répétition de tokens
    }

    generation = model.generate(
        input_ids=input_ids,
        prompt_input_ids=prompt_input_ids,
        **generation_config
    )

    #generation = model.generate(input_ids=input_ids, prompt_input_ids=prompt_input_ids)
    audio_arr = generation.cpu().numpy().squeeze()  # Transformer en tableau numpy

    # Taux d'échantillonnage
    sampling_rate = model.config.sampling_rate

    # Normaliser l'audio
    audio_arr = audio_arr / np.max(np.abs(audio_arr))
    torch.cuda.empty_cache()
    return sampling_rate, audio_arr

# Fonction pour mettre à jour le compteur de caractères
def update_char_counter(text):
    remaining_chars = 180 - len(text)
    return f"Caractères restants : {remaining_chars}"

# Interface Gradio trest
def create_interface():
    with gr.Blocks() as demo:
        # Ajouter une image ou un logo
        gr.Markdown("![Logo](https://huggingface.co/spaces/CONCREE/Adia_TTS/resolve/main/adia.png)") 

        # Titre et description
        gr.Markdown("# 🌟 Bienvenue sur Adia TTS 🌟")
        gr.Markdown(f"[Adia TTS](https://huggingface.co/CONCREE/Adia_TTS) est un modèle de génération audio en wolof. Cette interface vous permet de générer des fichiers audio à partir de textes en wolof. Vous pouvez choisir une description pour personnaliser la voix générée.")

        with gr.Row():
            with gr.Column():
                prompt_input = gr.Textbox(label="Entrez votre texte en wolof", placeholder="Adia TTS xeetu audio wolof la buy jàppale boroom këru liggéey yi ñu mëna def seen projet", value=default_prompt, max_length=180)
                char_counter = gr.Label(value=update_char_counter(default_prompt))
                description_input = gr.Textbox(label="Entrez une description pour la voix", value=default_description)
                generate_button = gr.Button("Générer l'audio", variant="primary")

            with gr.Column():
                audio_output = gr.Audio(label="Audio généré", type="numpy")

        # Section des exemples
        gr.Markdown("## Exemples de textes et descriptions")
        gr.Examples(
            examples=[
                [
                 """Yeneen jumtukaay yuy dimbal mooy yi ñeel saytu xaalis, comptabilite ak yoriinu liggéey administratif. Marketing digital itam doon na jumtukaay bu am solo ngir yokk sa gis-gis.""",
                    "A warm, natural, and friendly voice with a steady pace and clear pronunciation. The audio is crisp with no background noise, and the delivery is expressive but calm, giving a conversational feel.",
                 
                 
                   ],
                [
                     """Liggéeyukaay ci wàllu mbay mi ci Senegal dafa am solo lool ci wàllu kaaraange dundu ak sos liggéey, ndax dafay boole xeeti liggéey yu bees yu melni agroecologie.""",
                    "A crystal clear and distinct voice, with a moderate reading rate that facilitates understanding. The tone is monotonous, without variations or inflections, which provides a uniform listening experience. The voice is free of background noise and allows for continuous reading, without inappropriate pauses, thus ensuring a constant and pleasant flow.",
                  ],
                [
                     """Politigu Senegaal, doxalinu demokraasi bu dëgër la, am wote yuy faral di am, te askan wi di ci bokk bu baax. Waaye, waxtaan yi am ci wàllu nguur, leer ak coppite yi am ci liggéeyuk""",
                    "Adia's voice is very clear with a slight hint of expressiveness. The recording quality is moderate, with some background noise.",
                  ],
            ],
            inputs=[prompt_input, description_input],
            outputs=audio_output,
            fn=generate_audio,  # Fonction à appeler lors du clic sur un exemple
            label="Cliquez sur un exemple pour générer l'audio",
            cache_examples=False,  
        )

        # Mettre à jour le compteur de caractères à chaque saisie
        prompt_input.change(fn=update_char_counter, inputs=prompt_input, outputs=char_counter)

        generate_button.click(fn=generate_audio, inputs=[prompt_input, description_input], outputs=audio_output)

    return demo

# Lancement de l'interface
if __name__ == "__main__":
    interface = create_interface()
    interface.launch()