Convert-it/Areas/AudioTools/Views/TextToSpeech/Index.cshtml
Ricardo Carneiro 724e03176e
All checks were successful
Deploy ASP.NET MVC to OCI / build-and-deploy (push) Successful in 21m10s
feat: conversor de audio
2026-01-25 14:47:46 -03:00

123 lines
4.8 KiB
Plaintext

@{
ViewData["Title"] = "Texto para Áudio (Voz)";
}
<div class="text-center mb-5">
<h1 class="display-4">@ViewData["Title"]</h1>
<p class="lead">Converta qualquer texto em fala usando vozes neurais de alta qualidade.</p>
</div>
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card shadow-custom p-4">
<div class="mb-4">
<label for="textInput" class="form-label h5">Digite ou cole seu texto</label>
<textarea class="form-control" id="textInput" rows="6" placeholder="Escreva aqui o que você deseja que seja lido..."></textarea>
</div>
<div class="row mb-4">
<div class="col-md-6">
<label for="voiceSelect" class="form-label">Escolher Voz</label>
<select id="voiceSelect" class="form-select"></select>
</div>
<div class="col-md-3">
<label for="rate" class="form-label">Velocidade</label>
<input type="range" class="form-range" min="0.5" max="2" step="0.1" id="rate" value="1">
</div>
<div class="col-md-3">
<label for="pitch" class="form-label">Tom</label>
<input type="range" class="form-range" min="0" max="2" step="0.1" id="pitch" value="1">
</div>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
<button type="button" class="btn btn-primary btn-lg px-5" onclick="speak()">
<i class="bi bi-play-fill me-2"></i>Ouvir
</button>
<button type="button" class="btn btn-outline-danger btn-lg" onclick="stop()">
<i class="bi bi-stop-fill me-2"></i>Parar
</button>
</div>
</div>
<div class="mt-4 alert alert-info">
<i class="bi bi-info-circle me-2"></i>
Esta ferramenta usa as vozes instaladas no seu dispositivo. No Android e Windows, você encontrará opções de vozes neurais muito naturais.
</div>
</div>
</div>
@section Scripts {
<script>
const synth = window.speechSynthesis;
const voiceSelect = document.querySelector('#voiceSelect');
const textInput = document.querySelector('#textInput');
const rate = document.querySelector('#rate');
const pitch = document.querySelector('#pitch');
let voices = [];
function populateVoiceList() {
voices = synth.getVoices().sort(function (a, b) {
const aname = a.name.toUpperCase();
const bname = b.name.toUpperCase();
if (aname < bname) return -1;
else if (aname > bname) return 1;
else return 0;
});
const selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;
voiceSelect.innerHTML = '';
for (let i = 0; i < voices.length; i++) {
const option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
if (voices[i].default) {
option.textContent += ' -- PADRÃO';
}
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
voiceSelect.appendChild(option);
}
voiceSelect.selectedIndex = selectedIndex;
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
function speak() {
if (synth.speaking) {
console.error('speechSynthesis.speaking');
return;
}
if (textInput.value !== '') {
const utterThis = new SpeechSynthesisUtterance(textInput.value);
utterThis.onend = function (event) {
console.log('SpeechSynthesisUtterance.onend');
}
utterThis.onerror = function (event) {
console.error('SpeechSynthesisUtterance.onerror');
}
const selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for (let i = 0; i < voices.length; i++) {
if (voices[i].name === selectedOption) {
utterThis.voice = voices[i];
break;
}
}
utterThis.pitch = pitch.value;
utterThis.rate = rate.value;
synth.speak(utterThis);
}
}
function stop() {
synth.cancel();
}
</script>
}