<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>APP para Reproducir texto en notas de voz</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/shoelace-css/1.0.0-beta16/shoelace.css">
<style>
ul {
list-style: none;
padding: 0;
}
p {
color: #444;
}
a {
color: #2a8d3a;
}
button:focus {
outline: 0;
}
.button, button {
background-color: #2a8d3a;
}
.button:hover, button:hover {
background-color: #333;
}
.container {
max-width: 700px;
margin: 0 auto;
padding: 20px 50px;
text-align: center;
}
.container h1 {
margin-bottom: 20px;
}
.page-description {
font-size: 1.1rem;
margin: 0 auto;
}
.enlace-inicio {
font-size: 1em;
color: #888;
text-decoration: none;
}
.enlace-inicio:hover {
color: #2a8d3a;
}
.no-browser-support {
display: none;
font-size: 1.2rem;
color: #e64427;
margin-top: 35px;
}
.app {
margin: 40px auto;
}
#note-textarea {
margin: 20px 0;
border: 1px solid #ccc;
}
#recording-instructions {
margin: 15px auto 20px;
}
#notes {
padding-top: 2px;
}
.note .header {
font-size: 0.9em;
color: #888;
margin-bottom: 10px;
}
.note .delete-note,
.note .listen-note {
text-decoration: none;
margin-left: 15px;
}
.note .content {
margin-bottom: 40px;
}
@media (max-width: 768px) {
.container {
padding: 50px 25px;
}
button {
margin-bottom: 10px;
}
}
</style>
</head>
<body>
<div class="container">
<h1>Hacer una APP de texto-audio</h1>
<p class="page-description">APP para Reproducir texto en notas de voz usando HTML y JavaScript, esta APP te permitira reproducir el texto que agregues en notas de voz para escuchar instantáneamente.</p>
<p><a class="enlace-inicio" href="https://internetedadinero.com/">Ver el tutorial completo en InterneTedaDinero.com</a></p>
<h3 class="no-browser-support">Disculpa, tu navegador no soprta el Web Speech API. Intenta usando Google Chrome.</h3>
<div class="app">
<h3>Agregar una nota de voz</h3>
<div class="input-single">
<textarea id="note-textarea" placeholder="Escribe el texto para crear una nota de voz..." rows="6"></textarea>
</div>
<button id="start-record-btn" title="Start Recording">Iniciar Reconocimento</button>
<button id="pause-record-btn" title="Pause Recording">Pausar Reconocimento</button>
<button id="save-note-btn" title="Save Note">Guardar Nota y Escuchar</button>
<p id="recording-instructions">Oprime el boton <strong>Iniciar Reconocimento</strong> para empezar.</p>
<hr>
<h3>Mis notas de voz - Escuchar</h3>
<ul id="notes">
<li>
<p class="no-notes">Tu no tienes ninguna nota de voz.</p>
</li>
</ul>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="script.js"></script>
</body>
</html>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
try {
var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
var recognition = new SpeechRecognition();
}
catch(e) {
console.error(e);
$('.no-browser-support').show();
$('.app').hide();
}
var noteTextarea = $('#note-textarea');
var instructions = $('#recording-instructions');
var notesList = $('ul#notes');
var noteContent = '';
// Toma todas las notas de sesiones anteriores y las muestra.
var notes = getAllNotes();
renderNotes(notes);
/*-----------------------------
Reconocimiento de voz
------------------------------*/
// Si se deja - false, la grabacion se detiene despues de unos segundos de silencio.
// Si se deja - true, la grabacion se detiene despues de 15 segundos aprox, dando tiempo para que el usuario pause.
recognition.continuous = true;
// Este bloque es llamado cada vez que el Speech APi captura una linea.
recognition.onresult = function(event) {
// event es el objeto SpeechRecognitionEvent.
// Guarda las lineas capturadas.
// Solo es necesaria la que esta activa.
var current = event.resultIndex;
// Toma una transcripcion de lo que se dijo.
var transcript = event.results[current][0].transcript;
// Añadir la trasncripcion actual al contenido de la nota.
// Hay un bug en moviles, todo se repite 2 veces.
// No hay una solucion oficial, hasta ahora has servido esta.
var mobileRepeatBug = (current == 1 && transcript == event.results[0][0].transcript);
if(!mobileRepeatBug) {
noteContent += transcript;
noteTextarea.val(noteContent);
}
};
recognition.onstart = function() {
instructions.text('Voice recognition activated. Try speaking into the microphone.');
}
recognition.onspeechend = function() {
instructions.text('You were quiet for a while so voice recognition turned itself off.');
}
recognition.onerror = function(event) {
if(event.error == 'no-speech') {
instructions.text('No speech was detected. Try again.');
};
}
/*-----------------------------
Botones de App y input
------------------------------*/
$('#start-record-btn').on('click', function(e) {
if (noteContent.length) {
noteContent += ' ';
}
recognition.start();
});
$('#pause-record-btn').on('click', function(e) {
recognition.stop();
instructions.text('Reconocimiento Pausado.');
});
// Sincroniza el texto dentro del area de texto con la variable noteContent
noteTextarea.on('input', function() {
noteContent = $(this).val();
})
$('#save-note-btn').on('click', function(e) {
recognition.stop();
if(!noteContent.length) {
instructions.text('No pudimos guardar la nota de voz. Por favor agrega un mensaje en tu nota.');
}
else {
// Guarda la nota en localStorage.
// key es la fecha, value es el contenido de la nota.
saveNote(new Date().toLocaleString(), noteContent);
// Reninicia variables y actualiza UI.
noteContent = '';
renderNotes(getAllNotes());
noteTextarea.val('');
instructions.text('Nota guardada satisfactoriamente');
}
})
notesList.on('click', function(e) {
e.preventDefault();
var target = $(e.target);
// Escuchar la nota de voz actual.
if(target.hasClass('listen-note')) {
var content = target.closest('.note').find('.content').text();
readOutLoud(content);
}
// Eliminar nota.
if(target.hasClass('delete-note')) {
var dateTime = target.siblings('.date').text();
deleteNote(dateTime);
target.closest('.note').remove();
}
});
/*-----------------------------
Sintesis de discurso
------------------------------*/
function readOutLoud(message) {
var speech = new SpeechSynthesisUtterance();
// Configura los atributos de texto y voz.
speech.text = message;
speech.volume = 1;
speech.rate = 1;
speech.pitch = 1;
window.speechSynthesis.speak(speech);
}
/*-----------------------------
Helper Functions
------------------------------*/
function renderNotes(notes) {
var html = '';
if(notes.length) {
notes.forEach(function(note) {
html+= `<li class="note">
<p class="header">
<span class="date">${note.date}</span>
<a href="#" class="listen-note" title="Listen to Note">Escuchar nota de voz</a>
<a href="#" class="delete-note" title="Delete">Eliminar</a>
</p>
<p class="content">${note.content}</p>
</li>`;
});
}
else {
html = '<li><p class="content">Tu no tienes ninguna nota de voz.</p></li>';
}
notesList.html(html);
}
function saveNote(dateTime, content) {
localStorage.setItem('note-' + dateTime, content);
}
function getAllNotes() {
var notes = [];
var key;
for (var i = 0; i < localStorage.length; i++) {
key = localStorage.key(i);
if(key.substring(0,5) == 'note-') {
notes.push({
date: key.replace('note-',''),
content: localStorage.getItem(localStorage.key(i))
});
}
}
return notes;
}
function deleteNote(dateTime) {
localStorage.removeItem('note-' + dateTime);
}
</script>
Puedes encontrar un ejemplo de estos dos archivos en http://internetedadinero.com/hacer-una-app-de-texto-audio/