From e94abbc2d76ae4baeef9ca26fded0f7d230c20f1 Mon Sep 17 00:00:00 2001 From: Ubaldo Porcheddu Date: Tue, 31 Dec 2024 12:39:52 +0000 Subject: [PATCH] improve text to speech web interface --- assets/static/script.js | 53 +------ assets/static/tts.html | 315 ++++++++++++++++++++++++++++++++++++++++ main.go | 2 +- web.go | 22 ++- 4 files changed, 336 insertions(+), 56 deletions(-) create mode 100644 assets/static/tts.html diff --git a/assets/static/script.js b/assets/static/script.js index 662166a..82dd64b 100644 --- a/assets/static/script.js +++ b/assets/static/script.js @@ -113,7 +113,11 @@ function displayResults(results, type) { divContent.className = 'ms-2 me-auto'; const titleLink = document.createElement('a'); - titleLink.href = `article?id=${result.article_id}`; + if ('speechSynthesis' in window) { + titleLink.href= `/static/tts.html?id=${result.article_id}&locale=${language}`; + } else { + titleLink.href = `article?id=${result.article_id}`; + } titleLink.className = 'text-decoration-none'; titleLink.textContent = result.title; @@ -133,44 +137,10 @@ function displayResults(results, type) { } } -function speakPageContent() { - const elementsToSpeak = document.querySelectorAll('h1, h2, h3, h4, h5, h6, p'); - const allText = Array.from(elementsToSpeak) - .map(el => el.textContent) - .join(". "); - - utterance = new SpeechSynthesisUtterance(allText); - utterance.lang = language; - utterance.rate = 1.0; - utterance.pitch = 1.0; - - speakIcon.classList.remove('bi-volume-up-fill'); - speakIcon.classList.add('bi-volume-mute-fill'); - isSpeaking = true; - - speechSynthesis.speak(utterance); - - utterance.onend = () => { - speakIcon.classList.remove('bi-volume-mute-fill'); - speakIcon.classList.add('bi-volume-up-fill'); - isSpeaking = false; - }; -} - - -let utterance; -let isSpeaking = false; - const speechInput = document.getElementById('speechInput'); const startSpeechButton = document.getElementById('startSpeech'); -const speakButton = document.querySelector('.speak-button'); -const speakIcon = document.querySelector('.speak-button i'); const searchForm = document.getElementById('searchForm'); -if (speakButton && (!'speechSynthesis' in window)) { - speakButton.style.display = 'none'; -} - if (startSpeechButton && !/Chrome/.test(navigator.userAgent)) { startSpeechButton.style.display = 'none'; } @@ -213,19 +183,6 @@ if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) { document.getElementById("startSpeech").style.display = "none"; } -if (speakButton) { - speakButton.addEventListener('click', () => { - if (isSpeaking) { - speechSynthesis.cancel(); - speakIcon.classList.remove('bi-volume-mute-fill'); - speakIcon.classList.add('bi-volume-up-fill'); - isSpeaking = false; - } else { - speakPageContent(); - } - }); -} - if (searchForm) { createSearchCheckboxes(); searchForm.addEventListener('submit', function (event) { diff --git a/assets/static/tts.html b/assets/static/tts.html new file mode 100644 index 0000000..4160473 --- /dev/null +++ b/assets/static/tts.html @@ -0,0 +1,315 @@ + + + + + + + + + + + + +
+

+
+
+
+
+ +
+
+ + + +
+
+ +
+
+ + + diff --git a/main.go b/main.go index 0aa11ed..8cae693 100644 --- a/main.go +++ b/main.go @@ -10,7 +10,7 @@ import ( "os" ) -const Version = "0.0.42" +const Version = "0.0.43" type Config struct { importPath string //https://dumps.wikimedia.org/other/enterprise_html/runs/... diff --git a/web.go b/web.go index 7b176a4..8901de3 100644 --- a/web.go +++ b/web.go @@ -47,7 +47,15 @@ func (s *WebServer) executeTemplate(w http.ResponseWriter, templateName string, return } } + func (s *WebServer) handleHTMLSearch(w http.ResponseWriter, r *http.Request) { + type TemplateData struct { + Query string + Results []SearchResult + HasQuery bool + Language string + } + if r.Method == "POST" { query := r.FormValue("query") results, err := Search(query, options.limit) @@ -57,21 +65,21 @@ func (s *WebServer) handleHTMLSearch(w http.ResponseWriter, r *http.Request) { return } - data := struct { - Query string - Results []SearchResult - HasQuery bool - Language string - }{ + data := TemplateData{ Query: query, Results: results, HasQuery: query != "", Language: options.language, } + log.Println(data) s.executeTemplate(w, "search.html", data) return } - s.executeTemplate(w, "search.html", nil) + + data := TemplateData{ + Language: options.language, + } + s.executeTemplate(w, "search.html", data) } func (s *WebServer) handleHTMLArticle(w http.ResponseWriter, r *http.Request) {