tx3bas commited on
Commit
8a6feed
verified
1 Parent(s): 63ee8e5

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +117 -67
index.html CHANGED
@@ -8,13 +8,33 @@
8
  textarea {
9
  width: 100%;
10
  height: 150px;
 
 
 
11
  }
12
  button {
13
- padding: 10px;
14
- margin: 10px 5px;
 
15
  cursor: pointer;
16
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  </style>
 
 
18
  </head>
19
  <body>
20
  <h3>Text to Speech - Google Espa帽ol</h3>
@@ -25,7 +45,8 @@
25
  <button id="pause">Pausar</button>
26
  <button id="resume">Reanudar</button>
27
  <button id="cancel">Cancelar</button>
28
- <button id="download" style="display:none;">Descargar Audio</button>
 
29
 
30
  <script>
31
  // Verifica si el navegador soporta las APIs necesarias
@@ -33,88 +54,117 @@
33
  alert("Tu navegador no soporta las APIs necesarias para esta funci贸n.");
34
  }
35
 
36
- let tts = new SpeechSynthesisUtterance();
37
- let voices = [];
38
- let audioChunks = [];
39
  let mediaRecorder;
40
- let audioBlob;
41
-
42
- // Cargar voces y seleccionar "Google espa帽ol" si est谩 disponible
43
- window.speechSynthesis.onvoiceschanged = () => {
44
- voices = window.speechSynthesis.getVoices();
45
- let selectedVoice = voices.find(voice => voice.lang === "es-ES" && voice.name.includes("Google"));
46
- if (selectedVoice) {
47
- tts.voice = selectedVoice;
48
- tts.volume = 1; // Volumen predeterminado
49
- tts.rate = 1; // Velocidad predeterminada
50
- tts.pitch = 1; // Tono predeterminado
51
- } else {
52
- alert("La voz 'Google espa帽ol' no est谩 disponible en este navegador.");
53
- }
54
- };
55
-
56
- // Inicializa MediaRecorder usando un AudioContext
57
- async function initMediaRecorder() {
58
- const audioContext = new (window.AudioContext || window.webkitAudioContext)();
59
- const dest = audioContext.createMediaStreamDestination();
60
- const source = audioContext.createMediaStreamSource(dest.stream);
61
-
62
- // Conecta la salida de speechSynthesis al AudioContext
63
- const synth = window.speechSynthesis;
64
- const synthNode = audioContext.createMediaStreamSource(dest.stream);
65
- synth.resume(); // Asegura que speechSynthesis est茅 activo
66
-
67
- // Crea MediaRecorder para grabar el audio
68
- mediaRecorder = new MediaRecorder(dest.stream);
69
- mediaRecorder.ondataavailable = (event) => {
70
- if (event.data.size > 0) {
71
- audioChunks.push(event.data);
72
  }
73
- };
74
- mediaRecorder.onstop = () => {
75
- audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
76
- const audioUrl = URL.createObjectURL(audioBlob);
77
- const downloadButton = document.getElementById("download");
78
- downloadButton.style.display = "inline";
79
- downloadButton.href = audioUrl;
80
- downloadButton.download = 'tts_audio.wav';
81
- };
82
- }
83
 
84
- // Funci贸n para reproducir el habla y grabar
85
- async function speakAndRecord(text) {
86
- await initMediaRecorder();
87
- mediaRecorder.start();
88
 
89
- tts.text = text;
90
- window.speechSynthesis.speak(tts);
 
 
 
91
 
92
- tts.onend = () => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  mediaRecorder.stop();
94
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
96
 
97
  // Manejo de eventos de los botones
98
- document.getElementById("speak").addEventListener("click", () => {
99
- const text = document.getElementById("lines").value;
100
- audioChunks = [];
101
- document.getElementById("download").style.display = "none";
102
- speakAndRecord(text);
 
103
  });
104
 
105
- document.getElementById("pause").addEventListener("click", () => {
106
  window.speechSynthesis.pause();
 
107
  });
108
 
109
- document.getElementById("resume").addEventListener("click", () => {
110
  window.speechSynthesis.resume();
 
111
  });
112
 
113
- document.getElementById("cancel").addEventListener("click", () => {
114
  window.speechSynthesis.cancel();
115
- if (mediaRecorder && mediaRecorder.state !== "inactive") {
116
- mediaRecorder.stop();
117
- }
118
  });
119
  </script>
120
  </body>
 
8
  textarea {
9
  width: 100%;
10
  height: 150px;
11
+ padding: 10px;
12
+ font-size: 16px;
13
+ box-sizing: border-box;
14
  }
15
  button {
16
+ padding: 10px 20px;
17
+ margin: 10px 5px 0 0;
18
+ font-size: 16px;
19
  cursor: pointer;
20
  }
21
+ #download {
22
+ display: none;
23
+ padding: 10px 20px;
24
+ background-color: #4CAF50;
25
+ color: white;
26
+ text-decoration: none;
27
+ border-radius: 5px;
28
+ margin-top: 10px;
29
+ display: inline-block;
30
+ }
31
+ #status {
32
+ margin-top: 10px;
33
+ font-weight: bold;
34
+ }
35
  </style>
36
+ <!-- Incluir ResponsiveVoice -->
37
+ <script src="https://code.responsivevoice.org/responsivevoice.js?key=PCQ3lKHt"></script>
38
  </head>
39
  <body>
40
  <h3>Text to Speech - Google Espa帽ol</h3>
 
45
  <button id="pause">Pausar</button>
46
  <button id="resume">Reanudar</button>
47
  <button id="cancel">Cancelar</button>
48
+ <a id="download" href="#" download="tts_audio.webm">Descargar Audio</a>
49
+ <div id="status"></div>
50
 
51
  <script>
52
  // Verifica si el navegador soporta las APIs necesarias
 
54
  alert("Tu navegador no soporta las APIs necesarias para esta funci贸n.");
55
  }
56
 
57
+ let chunks = [];
 
 
58
  let mediaRecorder;
59
+ let stream;
60
+
61
+ // Referencias a elementos del DOM
62
+ const speakBtn = document.getElementById("speak");
63
+ const pauseBtn = document.getElementById("pause");
64
+ const resumeBtn = document.getElementById("resume");
65
+ const cancelBtn = document.getElementById("cancel");
66
+ const downloadLink = document.getElementById("download");
67
+ const statusDiv = document.getElementById("status");
68
+
69
+ // Funci贸n para iniciar la captura de audio
70
+ async function startCapture() {
71
+ try {
72
+ statusDiv.textContent = "Solicitando permisos para capturar audio...";
73
+ // Solicitar captura de audio de la pesta帽a actual
74
+ stream = await navigator.mediaDevices.getDisplayMedia({
75
+ audio: true,
76
+ video: false // Intentar capturar solo audio
77
+ });
78
+
79
+ // Verificar si se captur贸 audio
80
+ if (stream.getAudioTracks().length === 0) {
81
+ throw new Error("No se captur贸 ning煤n audio.");
 
 
 
 
 
 
 
 
 
82
  }
 
 
 
 
 
 
 
 
 
 
83
 
84
+ // Crear MediaRecorder para capturar el audio
85
+ mediaRecorder = new MediaRecorder(stream, { mimeType: "audio/webm" });
 
 
86
 
87
+ mediaRecorder.ondataavailable = function(e) {
88
+ if (e.data.size > 0) {
89
+ chunks.push(e.data);
90
+ }
91
+ };
92
 
93
+ mediaRecorder.onstop = function() {
94
+ const blob = new Blob(chunks, { type: "audio/webm" });
95
+ const url = URL.createObjectURL(blob);
96
+ downloadLink.href = url;
97
+ downloadLink.style.display = "inline-block";
98
+ statusDiv.textContent = "Grabaci贸n completada. Puedes descargar el audio.";
99
+ // Limpiar chunks para futuras grabaciones
100
+ chunks = [];
101
+ // Detener todas las pistas de audio
102
+ stream.getAudioTracks().forEach(track => track.stop());
103
+ };
104
+
105
+ // Iniciar la grabaci贸n
106
+ mediaRecorder.start();
107
+ statusDiv.textContent = "Grabaci贸n iniciada. Generando audio...";
108
+
109
+ } catch (err) {
110
+ console.error("Error al capturar el audio:", err);
111
+ alert("No se pudo capturar el audio. Aseg煤rate de conceder los permisos necesarios.");
112
+ statusDiv.textContent = "Error al capturar el audio.";
113
+ }
114
+ }
115
+
116
+ // Funci贸n para detener la captura de audio
117
+ function stopCapture() {
118
+ if (mediaRecorder && mediaRecorder.state !== "inactive") {
119
  mediaRecorder.stop();
120
+ statusDiv.textContent = "Deteniendo la grabaci贸n...";
121
+ }
122
+ }
123
+
124
+ // Funci贸n para hablar y grabar
125
+ function hablarYGrabar() {
126
+ const text = document.getElementById("lines").value.trim();
127
+ if (text === "") {
128
+ alert("Por favor, ingresa alg煤n texto para convertir a voz.");
129
+ return;
130
+ }
131
+
132
+ // Iniciar la captura de audio
133
+ startCapture().then(() => {
134
+ // Iniciar la s铆ntesis de voz
135
+ statusDiv.textContent = "Reproduciendo el audio...";
136
+ responsiveVoice.speak(text, "Spanish Latin American Female", {
137
+ onend: function() {
138
+ // Detener la grabaci贸n al finalizar la s铆ntesis
139
+ stopCapture();
140
+ }
141
+ });
142
+ });
143
  }
144
 
145
  // Manejo de eventos de los botones
146
+ speakBtn.addEventListener("click", () => {
147
+ // Limpiar estados anteriores
148
+ downloadLink.style.display = "none";
149
+ downloadLink.href = "#";
150
+ statusDiv.textContent = "";
151
+ hablarYGrabar();
152
  });
153
 
154
+ pauseBtn.addEventListener("click", () => {
155
  window.speechSynthesis.pause();
156
+ statusDiv.textContent = "Grabaci贸n y reproducci贸n pausadas.";
157
  });
158
 
159
+ resumeBtn.addEventListener("click", () => {
160
  window.speechSynthesis.resume();
161
+ statusDiv.textContent = "Grabaci贸n y reproducci贸n reanudadas.";
162
  });
163
 
164
+ cancelBtn.addEventListener("click", () => {
165
  window.speechSynthesis.cancel();
166
+ stopCapture();
167
+ statusDiv.textContent = "Grabaci贸n y reproducci贸n canceladas.";
 
168
  });
169
  </script>
170
  </body>