HirCoir commited on
Commit
ef29570
1 Parent(s): 33f5214

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +95 -0
  2. index.html +190 -0
app.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, jsonify, after_this_request
2
+ from io import BytesIO
3
+ import base64
4
+ import subprocess
5
+ import os
6
+ import random
7
+ import string
8
+ import re
9
+ import shlex
10
+
11
+ app = Flask(__name__)
12
+
13
+ # Define the folder where files are saved
14
+ file_folder = '/home/app/'
15
+
16
+ # Models with specific character replacements
17
+ models_replacements = {
18
+ "Español México | Claude": {
19
+ "model_path": "es_MX-claude-14947-epoch-high.onnx",
20
+ "replacements": [('(', ','), (')', ','), ('?', ','), ('¿', ','), (':', ','), ('\n', ' ')]
21
+ },
22
+ "Español México | Cortana Infinnity": {
23
+ "model_path": "es_MX-cortana-19669-epoch-high.onnx",
24
+ "replacements": [('(', ','), (')', ','), ('?', ','), ('¿', ','), (':', ','), ('\n', ' ')]
25
+ },
26
+ "Español México | TheGevy": {
27
+ "model_path": "es_MX-gevy-10196-epoch-high.onnx",
28
+ "replacements": [('(', ','), (')', ','), ('?', ','), ('¿', ','), (':', ','), ('\n', ' ')]
29
+ },
30
+ "English US | Voice": {
31
+ "model_path": "en_US-ljspeech-high.onnx",
32
+ "replacements": [('(', ','), (')', ','), ('?', ','), ('¿', ','), (':', ','), ('\n', ' ')]
33
+ }
34
+ }
35
+
36
+ def filter_text(text):
37
+ # Escapa caracteres especiales
38
+ escaped_text = shlex.quote(text)
39
+ return escaped_text
40
+
41
+ def convert_text_to_speech(parrafo, model):
42
+ # Limit text to 500 characters
43
+ parrafo = parrafo[:10000]
44
+
45
+ model_info = models_replacements.get(model)
46
+ if model_info:
47
+ model_path = model_info.get("model_path")
48
+ parrafo_filtrado = filter_text(parrafo)
49
+ random_name = ''.join(random.choices(string.ascii_letters + string.digits, k=8)) + '.wav'
50
+ output_file = os.path.join(file_folder, random_name)
51
+ app.logger.info("Audio file created at: %s", output_file)
52
+ piper_exe = os.path.join(file_folder, 'piper') # Adjusted the path for piper
53
+
54
+ if os.path.isfile(piper_exe):
55
+ comando = f'echo {parrafo_filtrado} | "{piper_exe}" -m {model_path} -f {output_file}'
56
+ subprocess.run(comando, shell=True)
57
+ return output_file
58
+ else:
59
+ return "The piper.exe file was not found in the correct directory."
60
+ else:
61
+ return "Model not found."
62
+
63
+ @app.route('/')
64
+ def index():
65
+ model_options = list(models_replacements.keys())
66
+ # Log the contents of the current folder
67
+ app.logger.info("Contents of current folder: %s", os.listdir(file_folder))
68
+ return render_template('index.html', model_options=model_options)
69
+
70
+ @app.route('/convert', methods=['POST'])
71
+ def convert_text():
72
+ text = request.form['text']
73
+ model = request.form['model']
74
+ output_file = convert_text_to_speech(text, model)
75
+
76
+ @after_this_request
77
+ def remove_file(response):
78
+ try:
79
+ os.remove(output_file)
80
+ app.logger.info("Audio file deleted: %s", output_file)
81
+ except Exception as error:
82
+ app.logger.error("Error deleting file: %s", error)
83
+ return response
84
+
85
+ with open(output_file, 'rb') as audio_file:
86
+ audio_content = audio_file.read()
87
+
88
+ audio_base64 = base64.b64encode(audio_content).decode('utf-8')
89
+
90
+ response = jsonify({'audio_base64': audio_base64})
91
+
92
+ return response
93
+
94
+ if __name__ == '__main__':
95
+ app.run(host='0.0.0.0', port=7860, debug=False)
index.html ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Convertidor de Texto a Audio</title>
7
+ <style>
8
+ body {
9
+ background-color: #222;
10
+ color: #eee;
11
+ font-family: Arial, sans-serif;
12
+ text-align: center;
13
+ margin: 0;
14
+ padding: 0;
15
+ }
16
+ h1 {
17
+ margin-top: 50px;
18
+ }
19
+ form {
20
+ margin-top: 20px;
21
+ display: flex;
22
+ flex-direction: column;
23
+ align-items: center;
24
+ }
25
+ label, select, textarea {
26
+ margin: 5px;
27
+ font-size: 16px;
28
+ color: #eee;
29
+ }
30
+ textarea {
31
+ background-color: #333;
32
+ color: #eee;
33
+ border: 1px solid #666;
34
+ border-radius: 5px;
35
+ padding: 10px;
36
+ width: 90%;
37
+ height: 100px;
38
+ }
39
+ select {
40
+ background-color: #333;
41
+ color: #eee;
42
+ border: 1px solid #666;
43
+ border-radius: 5px;
44
+ padding: 5px;
45
+ width: 80%;
46
+ height: 30px;
47
+ }
48
+ button {
49
+ background-color: #007bff;
50
+ color: #eee;
51
+ border: none;
52
+ border-radius: 5px;
53
+ padding: 10px 20px;
54
+ cursor: pointer;
55
+ transition: background-color 0.3s ease;
56
+ }
57
+ button:hover {
58
+ background-color: #0056b3;
59
+ }
60
+ #audio-container {
61
+ margin-top: 20px;
62
+ }
63
+ .animated-button {
64
+ position: relative;
65
+ display: flex;
66
+ align-items: center;
67
+ gap: 4px;
68
+ padding: 16px 36px;
69
+ border: 4px solid;
70
+ border-color: transparent;
71
+ font-size: 16px;
72
+ background-color: inherit;
73
+ border-radius: 100px;
74
+ font-weight: 600;
75
+ color: greenyellow;
76
+ box-shadow: 0 0 0 2px greenyellow;
77
+ cursor: pointer;
78
+ overflow: hidden;
79
+ transition: all 0.6s cubic-bezier(0.23, 1, 0.32, 1);
80
+ }
81
+ .animated-button svg {
82
+ position: absolute;
83
+ width: 24px;
84
+ fill: greenyellow;
85
+ z-index: 9;
86
+ transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
87
+ }
88
+ .animated-button .arr-1 {
89
+ right: 16px;
90
+ }
91
+ .animated-button .arr-2 {
92
+ left: -25%;
93
+ }
94
+ .animated-button .circle {
95
+ position: absolute;
96
+ top: 50%;
97
+ left: 50%;
98
+ transform: translate(-50%, -50%);
99
+ width: 20px;
100
+ height: 20px;
101
+ background-color: rgb(208, 162, 246);
102
+ border-radius: 50%;
103
+ opacity: 0;
104
+ transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
105
+ }
106
+ .animated-button .text {
107
+ position: relative;
108
+ z-index: 1;
109
+ transform: translateX(-12px);
110
+ transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
111
+ }
112
+ .animated-button:hover {
113
+ box-shadow: 0 0 0 12px transparent;
114
+ color: #212121;
115
+ border-radius: 12px;
116
+ }
117
+ .animated-button:hover .arr-1 {
118
+ right: -25%;
119
+ }
120
+ .animated-button:hover .arr-2 {
121
+ left: 16px;
122
+ }
123
+ .animated-button:hover .text {
124
+ transform: translateX(12px);
125
+ }
126
+ .animated-button:hover svg {
127
+ fill: #212121;
128
+ }
129
+ .animated-button:active {
130
+ scale: 0.95;
131
+ box-shadow: 0 0 0 4px rgb(47, 196, 255);
132
+ }
133
+ .animated-button:hover .circle {
134
+ width: 220px;
135
+ height: 220px;
136
+ opacity: 1;
137
+ }
138
+ #audio-container {
139
+ margin-top: 20px;
140
+ }
141
+ </style>
142
+ </head>
143
+ <body>
144
+ <h1>Convertidor de Texto a Audio</h1>
145
+ <form action="/convert" method="post">
146
+ <label for="model">Selecciona el modelo ONNX:</label><br>
147
+ <div> <p>Prueba nuevos modelos avanzados en HirLab:</p> <a href="https://tts.hircoir.eu.org" style="color: #ADD8E6;" target="_blank"> Modelos disponibles: Sora Español México, Voz HirCoir, Kamora Español México </a> <p>Try new advanced models at HirLab:</p> <a href="https://tts.hircoir.eu.org" style="color: #ADD8E6;" target="_blank"> Available models: Sora Spanish Mexico, Voz HirCoir, Kamora Spanish Mexico </a> </div> <select id="model" name="model">
148
+ {% for model in model_options %}
149
+ <option value="{{ model }}">{{ model }}</option>
150
+ {% endfor %}
151
+ </select><br>
152
+ <label for="text">Texto:</label><br>
153
+ <textarea placeholder="Escribe tu texto aquí, solo se tomará los primeros 500 carácteres." id="text" name="text" rows="4"></textarea>
154
+ <button class="animated-button">
155
+ <svg viewBox="0 0 24 24" class="arr-2" xmlns="http://www.w3.org/2000/svg">
156
+ <path
157
+ d="M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z"
158
+ ></path>
159
+ </svg>
160
+ <span class="text">Generar audio</span>
161
+ <span class="circle"></span>
162
+ <svg viewBox="0 0 24 24" class="arr-1" xmlns="http://www.w3.org/2000/svg">
163
+ <path
164
+ d="M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z"
165
+ ></path>
166
+ </svg>
167
+ </button>
168
+
169
+ </form>
170
+ <div id="audio-container"></div>
171
+
172
+ <script>
173
+ document.querySelector('form').addEventListener('submit', async function (e) {
174
+ e.preventDefault();
175
+ const formData = new FormData(e.target);
176
+ const response = await fetch('/convert', {
177
+ method: 'POST',
178
+ body: formData
179
+ });
180
+ const data = await response.json();
181
+ const audioContent = data.audio_base64;
182
+ const audioElement = document.createElement('audio');
183
+ audioElement.src = 'data:audio/wav;base64,' + audioContent;
184
+ audioElement.controls = true;
185
+ audioElement.autoplay = true; // Autoreproducción del audio
186
+ document.getElementById('audio-container').innerHTML = '';
187
+ document.getElementById('audio-container').appendChild(audioElement);
188
+ });
189
+ </script>
190
+ </body>