Refactor into a single package
This commit is contained in:
parent
02c3e4c908
commit
5e866e4fca
94 changed files with 198 additions and 2867 deletions
254
mimic3_http/templates/index.html
Normal file
254
mimic3_http/templates/index.html
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="Mimic 3 text to speech server">
|
||||
<meta name="author" content="Michael Hansen">
|
||||
<link rel="icon" type="image/png" href="img/favicon.png" />
|
||||
|
||||
<title>Mimic 3</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<style>
|
||||
body {
|
||||
padding-top: 0;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
body {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#mimic-logo {
|
||||
height: 5rem;
|
||||
}
|
||||
|
||||
#mycroft-logo {
|
||||
height: 2rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Page Content -->
|
||||
<div id="main" class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h1>
|
||||
<img id="mimic-logo" src="img/Mimic_color.png" />
|
||||
Mimic 3
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<textarea id="text" placeholder="Type here..." class="form-control" rows="3" name="text" alt="Text to generate speech from"></textarea>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button id="speak-button" name="speak" class="btn btn-lg btn-primary" alt="Generate speech">Speak</button>
|
||||
|
||||
{% if show_openapi %}
|
||||
<br/><br />
|
||||
<a href="/openapi/" title="OpenAPI page" target="_blank" class="badge badge-info">API</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-auto">
|
||||
<label for="voice-list" title="Voice name">Voice:</label>
|
||||
<select id="voice-list" name="voices">
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<label for="speaker" title="Name of speaker">Speaker:</label>
|
||||
<select id="speaker-list" name="speaker">
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input type="checkbox" id="ssml">
|
||||
<label class="ml-1" for="ssml">SSML</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="audio-message" class="row mt-3" hidden>
|
||||
<div class="col">
|
||||
<audio id="audio" preload="none" controls autoplay hidden></audio>
|
||||
<p id="message"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-auto">
|
||||
<label for="noise-scale" title="Voice volatility">Noise:</label>
|
||||
<input type="number" id="noise-scale" name="noiseScale" size="5" min="0" max="1" step="0.001" value="0.667">
|
||||
<label for="noise-w" class="ml-2" title="Voice volatility 2">Noise W:</label>
|
||||
<input type="number" id="noise-w" name="noiseW" size="5" min="0" max="1" step="0.001" value="0.8">
|
||||
<label for="length-scale" class="ml-2" title="Voice speed (< 1 is faster)">Length:</label>
|
||||
<input type="number" id="length-scale" name="lengthScale" size="5" min="0" step="0.001" value="1">
|
||||
</div>
|
||||
</div>
|
||||
<hr class="mt-5" />
|
||||
<div class="row mt-5 justify-content-center">
|
||||
<a href="https://mycroft.ai" title="Mycroft AI">
|
||||
<img id="mycroft-logo" src="img/Mycroft_logo_two_typeonly.png" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="row mt-3 justify-content-center">
|
||||
<a href="https://www.gnu.org/licenses/agpl-3.0.en.html" title="AGPLv3">License</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap core JavaScript -->
|
||||
<script>
|
||||
var voicesInfo = {}
|
||||
|
||||
function q(selector) {return document.querySelector(selector)}
|
||||
q('#text').focus()
|
||||
|
||||
function do_tts(e) {
|
||||
text = q('#text').value
|
||||
if (text) {
|
||||
q('#message').textContent = 'Synthesizing...'
|
||||
q('#speak-button').disabled = true
|
||||
q('#audio').hidden = true
|
||||
synthesize(text)
|
||||
}
|
||||
e.preventDefault()
|
||||
return false
|
||||
}
|
||||
|
||||
q('#speak-button').addEventListener('click', do_tts)
|
||||
|
||||
async function synthesize(text) {
|
||||
var voiceList = q('#voice-list')
|
||||
var voice = voiceList.options[voiceList.selectedIndex].value
|
||||
|
||||
var noiseScale = q('#noise-scale').value || '0.667'
|
||||
var noiseW = q('#noise-w').value || '0.8'
|
||||
var lengthScale = q('#length-scale').value || '1.0'
|
||||
|
||||
var speakerList = q('#speaker-list')
|
||||
var speaker = speakerList.options[speakerList.selectedIndex].value
|
||||
if (speaker.length > 0) {
|
||||
voice = voice + "#" + speaker
|
||||
}
|
||||
|
||||
var ssml = q('#ssml').value || 'false'
|
||||
|
||||
q('#audio-message').hidden = false
|
||||
|
||||
var startTime = performance.now()
|
||||
|
||||
res = await fetch(
|
||||
'api/tts?text=' + encodeURIComponent(text) +
|
||||
'&voice=' + encodeURIComponent(voice) +
|
||||
'&noiseScale=' + encodeURIComponent(noiseScale) +
|
||||
'&noiseW=' + encodeURIComponent(noiseW) +
|
||||
'&lengthScale=' + encodeURIComponent(lengthScale) +
|
||||
'&ssml=' + encodeURIComponent(ssml),
|
||||
{cache: 'no-cache'})
|
||||
|
||||
if (res.ok) {
|
||||
blob = await res.blob()
|
||||
var elapsedTime = performance.now() - startTime
|
||||
|
||||
q('#message').textContent = (elapsedTime / 1000) + ' second(s)'
|
||||
q('#speak-button').disabled = false
|
||||
q('#audio').src = URL.createObjectURL(blob)
|
||||
q('#audio').hidden = false
|
||||
} else {
|
||||
message = await res.text()
|
||||
q('#message').textContent = message
|
||||
q('#speak-button').disabled = false
|
||||
}
|
||||
}
|
||||
|
||||
function voiceChanged() {
|
||||
var voiceList = q('#voice-list')
|
||||
|
||||
// Reset audio
|
||||
q('#audio-message').hidden = true
|
||||
q('#message').textContent = ''
|
||||
q('#audio').hidden = true
|
||||
q('#audio').autoplay = true
|
||||
|
||||
// Reset speakers
|
||||
var speakerList = q('#speaker-list')
|
||||
for (var i = speakerList.options.length - 1; i >= 0; i--) {
|
||||
speakerList.options[i].remove()
|
||||
}
|
||||
|
||||
var voiceKey = voiceList.options[voiceList.selectedIndex].value
|
||||
var voice = voicesInfo[voiceKey]
|
||||
|
||||
if (voice.speakers && voice.speakers.length > 0) {
|
||||
voice.speakers.forEach(function(speaker) {
|
||||
speakerList.insertAdjacentHTML(
|
||||
'beforeend', '<option value="' + speaker + '">' + speaker + '</option>'
|
||||
)
|
||||
})
|
||||
|
||||
} else {
|
||||
// Add default speaker
|
||||
speakerList.insertAdjacentHTML(
|
||||
'beforeend', '<option value="">default</option>'
|
||||
)
|
||||
}
|
||||
|
||||
// Update inference settings
|
||||
if (voice.properties) {
|
||||
q('#length-scale').value = voice.properties.length_scale || 1.0
|
||||
q('#noise-scale').value = voice.properties.noise_scale || 0.667
|
||||
q('#noise-w').value = voice.properties.noise_w || 0.8
|
||||
}
|
||||
}
|
||||
|
||||
q('#voice-list').addEventListener('change', voiceChanged)
|
||||
|
||||
function loadVoices() {
|
||||
voicesInfo = {}
|
||||
|
||||
// Remove previous voices
|
||||
var voiceList = q('#voice-list')
|
||||
for (var i = voiceList.options.length - 1; i >= 0; i--) {
|
||||
voiceList.options[i].remove()
|
||||
}
|
||||
|
||||
fetch('api/voices')
|
||||
.then(function(res) {
|
||||
if (!res.ok) throw Error(res.statusText)
|
||||
return res.json()
|
||||
}).then(function(voices) {
|
||||
voicesInfo = {}
|
||||
|
||||
// Populate select
|
||||
var indexToSelect = -1
|
||||
|
||||
voices.forEach(function(voice) {
|
||||
voicesInfo[voice.key] = voice
|
||||
voiceList.insertAdjacentHTML(
|
||||
'beforeend', '<option value="' + voice.key + '">' + voice.language + '/' + voice.name + '</option>'
|
||||
)
|
||||
})
|
||||
|
||||
voiceChanged()
|
||||
}).catch(function(err) {
|
||||
q('#message').textContent = 'Error: ' + err.message
|
||||
q('#speak-button').disabled = false
|
||||
})
|
||||
}
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
loadVoices()
|
||||
})
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue