[+] refactor book1
1. move book1 into a private repo;
This commit is contained in:
parent
584b4b652f
commit
136b5709b0
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -21,4 +21,4 @@
|
|||||||
url = https://gitea.fxreader.online/nartes/com.github.aiortc.aiortc
|
url = https://gitea.fxreader.online/nartes/com.github.aiortc.aiortc
|
||||||
[submodule "deps/online.fxreader.nartes.books"]
|
[submodule "deps/online.fxreader.nartes.books"]
|
||||||
path = deps/online.fxreader.nartes.books
|
path = deps/online.fxreader.nartes.books
|
||||||
url = https://gitea.fxreader.online/nartes/books
|
url = ssh://gitea@127.0.0.1:19000/nartes/books.git
|
||||||
|
2
d2/book1/NoSleep.min.js
vendored
2
d2/book1/NoSleep.min.js
vendored
File diff suppressed because one or more lines are too long
4756
d2/book1/book.js
4756
d2/book1/book.js
File diff suppressed because it is too large
Load Diff
@ -1,78 +0,0 @@
|
|||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<script
|
|
||||||
src="https://code.jquery.com/jquery-3.6.0.slim.min.js"
|
|
||||||
integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI="
|
|
||||||
crossorigin="anonymous"
|
|
||||||
></script>
|
|
||||||
|
|
||||||
<title>Speech synthesiser</title>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
window.context = {};
|
|
||||||
window.context.loading = {};
|
|
||||||
window.context.books = [];
|
|
||||||
</script>
|
|
||||||
<script src="NoSleep.min.js"></script>
|
|
||||||
<script src="script.js"></script>
|
|
||||||
<script src="book.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<!--[if lt IE 9]>
|
|
||||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
||||||
<![endif]-->
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class=voice-settings>
|
|
||||||
<h1>Speech synthesiser</h1>
|
|
||||||
|
|
||||||
<p>Enter some text in the input below and press return or the "play" button to hear it. change voices using the dropdown menu.</p>
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<input type="text" class="txt">
|
|
||||||
<div>
|
|
||||||
<label for="rate">Rate</label><input type="range" min="0.5" max="2" value="1" step="0.1" id="rate">
|
|
||||||
<div class="rate-value">1</div>
|
|
||||||
<div class="clearfix"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="pitch">Pitch</label><input type="range" min="0" max="2" value="1" step="0.1" id="pitch">
|
|
||||||
<div class="pitch-value">1</div>
|
|
||||||
<div class="clearfix"></div>
|
|
||||||
</div>
|
|
||||||
<select class=voice-select>
|
|
||||||
</select>
|
|
||||||
<div class="controls">
|
|
||||||
<button id="play" type="submit">Play</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class=screen>
|
|
||||||
<div class=widget>
|
|
||||||
<select name=book>
|
|
||||||
<!--<option value=0>Death of a Hear</option>-->
|
|
||||||
</select>
|
|
||||||
<br/>
|
|
||||||
<span>Current Sentence: </span>
|
|
||||||
<input type=input name=current-sentence></input>
|
|
||||||
<span>Total Sentences: </span>
|
|
||||||
<input type=input name=total-sentences disabled>
|
|
||||||
</input>
|
|
||||||
<br/>
|
|
||||||
<input type=button name=add-book value="Add Book">
|
|
||||||
<input type=button name=read-aloud value="Read Aloud">
|
|
||||||
<input type=button name=debug value="Debug">
|
|
||||||
</input>
|
|
||||||
<br/>
|
|
||||||
</div>
|
|
||||||
<pre class=status>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,550 +0,0 @@
|
|||||||
class Future {
|
|
||||||
constructor() {
|
|
||||||
let self = this;
|
|
||||||
|
|
||||||
self.promise = new Promise(
|
|
||||||
(resolve, reject) => {
|
|
||||||
self.resolve = resolve;
|
|
||||||
self.reject = reject;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.loading.script = new Future();
|
|
||||||
|
|
||||||
$(window).on('load', async () => {
|
|
||||||
|
|
||||||
var synth = window.speechSynthesis;
|
|
||||||
|
|
||||||
var inputForm = document.querySelector('form');
|
|
||||||
var inputTxt = document.querySelector('.txt');
|
|
||||||
var voiceSelect = document.querySelector('select');
|
|
||||||
|
|
||||||
var pitch = document.querySelector('#pitch');
|
|
||||||
var pitchValue = document.querySelector('.pitch-value');
|
|
||||||
var rate = document.querySelector('#rate');
|
|
||||||
var rateValue = document.querySelector('.rate-value');
|
|
||||||
|
|
||||||
var voices = [];
|
|
||||||
|
|
||||||
|
|
||||||
context.nosleep_timer = null;
|
|
||||||
|
|
||||||
context.ui = {
|
|
||||||
voice_settings_div: $('.voice-settings'),
|
|
||||||
voice_select: $('.voice-select'),
|
|
||||||
status_pre: $('.status'),
|
|
||||||
books_select: $('.screen .widget select[name=book]'),
|
|
||||||
current_sentence_input:
|
|
||||||
$('.screen .widget input[name=current-sentence]'),
|
|
||||||
total_sentences_input:
|
|
||||||
$('.screen .widget input[name=total-sentences]'),
|
|
||||||
read_aloud:
|
|
||||||
$('.screen .widget input[name=read-aloud]'),
|
|
||||||
add_book:
|
|
||||||
$('.screen .widget input[name=add-book]'),
|
|
||||||
debug:
|
|
||||||
$('.screen .widget input[name=debug]'),
|
|
||||||
};
|
|
||||||
context.update_books = () => {
|
|
||||||
context.ui.books_select.empty();
|
|
||||||
window.context.books.map(
|
|
||||||
(o, i) =>
|
|
||||||
$('<option>')
|
|
||||||
.attr('value', '' + i)
|
|
||||||
.attr('url', o.url || '')
|
|
||||||
.text(o.text.slice(0, 10))
|
|
||||||
).forEach((o) => context.ui.books_select.append(o))
|
|
||||||
}
|
|
||||||
|
|
||||||
context.update_books();
|
|
||||||
|
|
||||||
context.sentences = null;
|
|
||||||
context.pending_stop = false;
|
|
||||||
context.current_book = null;
|
|
||||||
context.nosleep = new NoSleep();
|
|
||||||
context.is_debug = false;
|
|
||||||
context.log = {
|
|
||||||
error: [],
|
|
||||||
info: [],
|
|
||||||
};
|
|
||||||
context.callbacks = {
|
|
||||||
log_error: (msg) => {
|
|
||||||
if (context.is_debug)
|
|
||||||
{
|
|
||||||
console.error(msg);
|
|
||||||
context.log.error.push(msg);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
enable_no_sleep: () => {
|
|
||||||
if (context.nosleep_timer != null)
|
|
||||||
{
|
|
||||||
context.callbacks.log_error('running already');
|
|
||||||
}
|
|
||||||
|
|
||||||
context.nosleep_timer = setInterval(
|
|
||||||
() => {
|
|
||||||
location.hash = 'nosleep' + Math.random();
|
|
||||||
context.callbacks.update_status();
|
|
||||||
/*
|
|
||||||
if ('vibrate' in window.navigator)
|
|
||||||
{
|
|
||||||
window.navigator.vibrate(200);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}, 1000
|
|
||||||
);
|
|
||||||
},
|
|
||||||
get_state: () => {
|
|
||||||
let t1 = localStorage['state'];
|
|
||||||
if (t1)
|
|
||||||
{
|
|
||||||
return JSON.parse(t1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
get_cookie: (key) => {
|
|
||||||
/*
|
|
||||||
return document.cookie.split('; ').map(
|
|
||||||
(o) => o.split('=')
|
|
||||||
).reduce(
|
|
||||||
(b, a) => {
|
|
||||||
if (a.length == 2) {b[a[0]] = a[1]};
|
|
||||||
return b
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
)[key];
|
|
||||||
*/
|
|
||||||
let t1 = localStorage['state'];
|
|
||||||
if (t1 != undefined)
|
|
||||||
{
|
|
||||||
let t2 = JSON.parse(t1);
|
|
||||||
return t2[key];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
set_cookie: (key, value) => {
|
|
||||||
let state = context.callbacks.get_state('state');
|
|
||||||
|
|
||||||
state[key] = value;
|
|
||||||
|
|
||||||
//document.cookie = `${key}=${value};`;
|
|
||||||
localStorage['state'] = JSON.stringify(state);
|
|
||||||
|
|
||||||
context.callbacks.update_status();
|
|
||||||
},
|
|
||||||
disable_no_sleep: () => {
|
|
||||||
if (context.nosleep_timer == null)
|
|
||||||
{
|
|
||||||
context.callbacks.log_error('nothing is running');
|
|
||||||
}
|
|
||||||
clearInterval(context.nosleep_timer);
|
|
||||||
location.hash = '';
|
|
||||||
context.nosleep_timer = null;
|
|
||||||
synth.cancel();
|
|
||||||
},
|
|
||||||
continuous_reading: async() => {
|
|
||||||
if (context.is_reading)
|
|
||||||
{
|
|
||||||
context.pending_stop = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
context.is_reading = true;
|
|
||||||
context.nosleep.enable();
|
|
||||||
context.callbacks.enable_no_sleep();
|
|
||||||
context.ui.voice_settings_div.addClass('hidden');
|
|
||||||
context.ui.current_sentence_input.attr(
|
|
||||||
'disabled',
|
|
||||||
'disabled'
|
|
||||||
);
|
|
||||||
|
|
||||||
while (
|
|
||||||
context.callbacks.get_cookie('sentence_id') < context.sentences.length &&
|
|
||||||
!context.pending_stop
|
|
||||||
)
|
|
||||||
{
|
|
||||||
let sentence =
|
|
||||||
context.sentences[context.callbacks.get_cookie('sentence_id')];
|
|
||||||
//context.callbacks.log_error('start');
|
|
||||||
try {
|
|
||||||
await context.read_aloud(
|
|
||||||
context.sentences[
|
|
||||||
context.callbacks.get_cookie('sentence_id')
|
|
||||||
]
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
context.callbacks.log_error(e);
|
|
||||||
}
|
|
||||||
//context.callbacks.log_error('finished');
|
|
||||||
if (!context.pending_stop)
|
|
||||||
{
|
|
||||||
context.callbacks.set_cookie(
|
|
||||||
'sentence_id',
|
|
||||||
context.callbacks.get_cookie('sentence_id') + 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
context.pending_stop = false;
|
|
||||||
context.ui.current_sentence_input.removeAttr('disabled');
|
|
||||||
context.nosleep.disable();
|
|
||||||
context.ui.voice_settings_div.removeClass('hidden');
|
|
||||||
context.callbacks.disable_no_sleep();
|
|
||||||
context.is_reading = false;
|
|
||||||
},
|
|
||||||
update_status: () => {
|
|
||||||
let data = {};
|
|
||||||
data.state = context.callbacks.get_state();
|
|
||||||
if (
|
|
||||||
context.callbacks.get_cookie('sentence_id') != null &&
|
|
||||||
context.sentences != null &&
|
|
||||||
context.callbacks.get_cookie('sentence_id') < context.sentences.length
|
|
||||||
)
|
|
||||||
{
|
|
||||||
data.sentence = context.sentences[context.callbacks.get_cookie('sentence_id')];
|
|
||||||
}
|
|
||||||
data.pending_stop = context.pending_stop;
|
|
||||||
data.is_reading = context.is_reading;
|
|
||||||
data.log = context.log;
|
|
||||||
context.ui.current_sentence_input.val(
|
|
||||||
context.callbacks.get_cookie('sentence_id')
|
|
||||||
);
|
|
||||||
data.timestamp = (new Date());
|
|
||||||
data.version = 'v0.1.7';
|
|
||||||
data.speech_synthesis = {
|
|
||||||
paused: synth.paused,
|
|
||||||
pending: synth.pending,
|
|
||||||
speaking: synth.speaking,
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
if (!synth.speaking && context.is_reading)
|
|
||||||
{
|
|
||||||
synth.cancel();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
context.ui.status_pre.text(
|
|
||||||
JSON.stringify(
|
|
||||||
data,
|
|
||||||
null,
|
|
||||||
4,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
ui_read_aloud_on_click: async() => {
|
|
||||||
let book_id = parseInt(context.ui.books_select.val());
|
|
||||||
if (context.current_book != book_id)
|
|
||||||
{
|
|
||||||
if (context.books[book_id].url)
|
|
||||||
{
|
|
||||||
context.callbacks.set_cookie(
|
|
||||||
'book_url',
|
|
||||||
context.books[book_id].url,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.current_book = book_id;
|
|
||||||
context.sentences =
|
|
||||||
context.books[
|
|
||||||
context.current_book
|
|
||||||
].text.replaceAll(/([\.\?\!])\s+/g,'$1\n')
|
|
||||||
.split('\n');
|
|
||||||
context.ui.total_sentences_input.val(
|
|
||||||
context.sentences.length,
|
|
||||||
);
|
|
||||||
{
|
|
||||||
let state = context.callbacks.get_state();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
context.ui.current_sentence_input.val() != ''
|
|
||||||
)
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
let sentence_id = parseInt(
|
|
||||||
context.ui.current_sentence_input.val()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
sentence_id >= 0 &&
|
|
||||||
sentence_id < context.sentences.length
|
|
||||||
)
|
|
||||||
{
|
|
||||||
context.callbacks.set_cookie(
|
|
||||||
'sentence_id',
|
|
||||||
sentence_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
context.callbacks.log_error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (context.is_reading && !context.pending_stop)
|
|
||||||
{
|
|
||||||
context.pending_stop = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context.callbacks.continuous_reading();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
book_add: async (url) => {
|
|
||||||
let book = await (
|
|
||||||
(await fetch(url)).text()
|
|
||||||
);
|
|
||||||
//let book = prompt('enter text', '');
|
|
||||||
//let title = prompt('enter title', '');
|
|
||||||
//window.context.books.push(title + '\n' + book);
|
|
||||||
window.context.books.push({
|
|
||||||
text: book, url
|
|
||||||
});
|
|
||||||
window.context.update_books();
|
|
||||||
},
|
|
||||||
populateVoiceList: () => {
|
|
||||||
voices = synth.getVoices().sort(function (a, b) {
|
|
||||||
const aname = a.name.toUpperCase(), bname = b.name.toUpperCase();
|
|
||||||
if ( aname < bname ) return -1;
|
|
||||||
else if ( aname == bname ) return 0;
|
|
||||||
else return +1;
|
|
||||||
});
|
|
||||||
//var selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;
|
|
||||||
voiceSelect.innerHTML = '';
|
|
||||||
for(i = 0; i < voices.length ; i++) {
|
|
||||||
var option = document.createElement('option');
|
|
||||||
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
|
|
||||||
|
|
||||||
if(voices[i].default) {
|
|
||||||
option.textContent += ' -- DEFAULT';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
let voice = context.callbacks.get_cookie('voice');
|
|
||||||
if (voice && option.textContent == voice)
|
|
||||||
{
|
|
||||||
$(option).attr('selected', 'selected');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
option.setAttribute('data-lang', voices[i].lang);
|
|
||||||
option.setAttribute('data-name', voices[i].name);
|
|
||||||
voiceSelect.appendChild(option);
|
|
||||||
}
|
|
||||||
|
|
||||||
//voiceSelect.selectedIndex = selectedIndex;
|
|
||||||
},
|
|
||||||
init: async () => {
|
|
||||||
let state = context.callbacks.get_state();
|
|
||||||
context.ui.voice_select.val(state.voice);
|
|
||||||
if (!state.book_id)
|
|
||||||
{
|
|
||||||
context.callbacks.set_cookie(
|
|
||||||
'book_id',
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!state.sentence_id)
|
|
||||||
{
|
|
||||||
context.callbacks.set_cookie(
|
|
||||||
'sentence_id',
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (state.book_url)
|
|
||||||
{
|
|
||||||
await context.callbacks.book_add(state.book_url);
|
|
||||||
state.book_id = context.books.length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.book_id)
|
|
||||||
{
|
|
||||||
context.ui.books_select.find(
|
|
||||||
'>option',
|
|
||||||
).eq(state.book_id).attr('selected', 'selected');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.sentence_id)
|
|
||||||
{
|
|
||||||
context.ui.current_sentence_input.val(
|
|
||||||
state.sentence_id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
context.callbacks.populateVoiceList();
|
|
||||||
if (speechSynthesis.onvoiceschanged !== undefined) {
|
|
||||||
speechSynthesis.onvoiceschanged = context.callbacks.populateVoiceList;
|
|
||||||
}
|
|
||||||
|
|
||||||
await context.callbacks.init();
|
|
||||||
|
|
||||||
context.ui.add_book.on(
|
|
||||||
'click',
|
|
||||||
async () => {
|
|
||||||
// alert('fuck');
|
|
||||||
let url = 'books/' + prompt('enter book file', '1.txt');
|
|
||||||
|
|
||||||
await context.callbacks.book_add(url);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
context.ui.read_aloud.on(
|
|
||||||
'click',
|
|
||||||
context.callbacks.ui_read_aloud_on_click,
|
|
||||||
);
|
|
||||||
context.ui.voice_select.on(
|
|
||||||
'change',
|
|
||||||
() => {
|
|
||||||
context.callbacks.set_cookie(
|
|
||||||
'voice',
|
|
||||||
context.ui.voice_select.val()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
context.ui.debug.on(
|
|
||||||
'click',
|
|
||||||
() => {
|
|
||||||
if (context.is_debug)
|
|
||||||
{
|
|
||||||
context.is_debug = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context.is_debug = true;
|
|
||||||
}
|
|
||||||
context.callbacks.update_status();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
context.read_aloud = async (raw_line) => {
|
|
||||||
line = raw_line.trim();
|
|
||||||
if (line.length == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let sleep_detect = null;
|
|
||||||
let exit = () => {
|
|
||||||
if (sleep_detect != null)
|
|
||||||
{
|
|
||||||
clearInterval(sleep_detect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Promise((response, reject) => {
|
|
||||||
if (synth.speaking) {
|
|
||||||
context.callbacks.log_error('speechSynthesis.speaking');
|
|
||||||
if (reject != undefined)
|
|
||||||
{
|
|
||||||
reject('error');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let utterThis = new SpeechSynthesisUtterance(line);
|
|
||||||
utterThis.onend = function (event) {
|
|
||||||
exit();
|
|
||||||
context.callbacks.log_error(
|
|
||||||
'SpeechSynthesisUtterance.onend ' + event.error
|
|
||||||
);
|
|
||||||
if (response != undefined)
|
|
||||||
{
|
|
||||||
response('done ' + event.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
utterThis.onpause = function (event) {
|
|
||||||
exit();
|
|
||||||
context.callbacks.log_error('SpeechSynthesisUtterance.onpause');
|
|
||||||
if (reject != undefined)
|
|
||||||
{
|
|
||||||
reject('paused ' + event.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
utterThis.onerror = function (event) {
|
|
||||||
exit();
|
|
||||||
context.callbacks.log_error(
|
|
||||||
'SpeechSynthesisUtterance.onerror ' + event.error
|
|
||||||
);
|
|
||||||
if (reject != undefined)
|
|
||||||
{
|
|
||||||
reject('error ' + event.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
|
|
||||||
for(i = 0; i < voices.length ; i++) {
|
|
||||||
if(voices[i].name === selectedOption) {
|
|
||||||
utterThis.voice = voices[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//window.alert('fuck3');
|
|
||||||
utterThis.pitch = pitch.value;
|
|
||||||
utterThis.rate = rate.value;
|
|
||||||
synth.speak(utterThis);
|
|
||||||
let silence_count = 0;
|
|
||||||
sleep_detect = setInterval(
|
|
||||||
() => {
|
|
||||||
if (!synth.speaking)
|
|
||||||
{
|
|
||||||
context.callbacks.log_error(
|
|
||||||
'silence count is ' + silence_count
|
|
||||||
)
|
|
||||||
|
|
||||||
++silence_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (silence_count == 3 || context.pending_stop)
|
|
||||||
{
|
|
||||||
exit();
|
|
||||||
if (context.pending_stop)
|
|
||||||
{
|
|
||||||
synth.cancel();
|
|
||||||
reject('pending stop');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context.callbacks.log_error('phone is sleeping, retry');
|
|
||||||
response('utterance is not present');
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
context.read_aloud(
|
|
||||||
line
|
|
||||||
).then(response).catch(reject);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
},
|
|
||||||
100,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function speak(){
|
|
||||||
let line = inputTxt.value;
|
|
||||||
if (line !== '') {
|
|
||||||
context.read_aloud(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inputForm.onsubmit = function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
speak();
|
|
||||||
|
|
||||||
inputTxt.blur();
|
|
||||||
}
|
|
||||||
|
|
||||||
pitch.onchange = function() {
|
|
||||||
pitchValue.textContent = pitch.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
rate.onchange = function() {
|
|
||||||
rateValue.textContent = rate.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
voiceSelect.onchange = function(){
|
|
||||||
speak();
|
|
||||||
}
|
|
||||||
|
|
||||||
context.loading.script.resolve(true);
|
|
||||||
});
|
|
@ -1,84 +0,0 @@
|
|||||||
body, html {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
height: 90%;
|
|
||||||
max-width: 800px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1, p {
|
|
||||||
font-family: sans-serif;
|
|
||||||
text-align: center;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.txt, select, form > div {
|
|
||||||
display: block;
|
|
||||||
margin: 0 auto;
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.txt {
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
width: 83%;
|
|
||||||
}
|
|
||||||
|
|
||||||
form > div {
|
|
||||||
width: 81%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.txt, form > div {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clearfix {
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
float: left;
|
|
||||||
width: 10%;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rate-value, .pitch-value {
|
|
||||||
float: right;
|
|
||||||
width: 5%;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
#rate, #pitch {
|
|
||||||
float: right;
|
|
||||||
width: 81%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls button {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden
|
|
||||||
{
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
word-break: break-all;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
2
deps/com.github.aiortc.aiortc
vendored
2
deps/com.github.aiortc.aiortc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit f94ded8fbfe62bea6e96827312eb25853990ecd3
|
Subproject commit e27d400c07ddbe66e1ef73da1a5754c28cfec157
|
1
deps/online.fxreader.nartes.books
vendored
Submodule
1
deps/online.fxreader.nartes.books
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 7cc59533c0eddbe04e3b58109d1d861a6f92f40d
|
Loading…
Reference in New Issue
Block a user