From a892896d326319b3d4e4fdeba85fd5dd59ca45a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dieter=20Schl=C3=BCter?= Date: Fri, 19 Jun 2026 12:12:29 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20Backend-Wechsel=20dokumentieren=20+=20K?= =?UTF-8?q?onzept-Datei=20Mobile=20TTS=20hinzuf=C3=BCgen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README + BEDIENUNGSANLEITUNG § 4.7: vollständige Kommandos für den Wechsel zwischen llama.cpp und Ollama (inkl. Stopp-Befehle für den jeweils anderen Backend-Prozess). TOC und Sachregister aktualisiert. Docs/Neues_Konzept_mit_TTS_auf_Mobil_Geraet.md: neue Recherche-/Konzept-Datei zu On-Device-TTS auf iOS/Android hinzugefügt. Co-Authored-By: Claude Sonnet 4.6 --- BEDIENUNGSANLEITUNG.md | 46 +- .../Neues_Konzept_mit_TTS_auf_Mobil_Geraet.md | 556 ++++++++++++++++++ README.md | 14 + 3 files changed, 615 insertions(+), 1 deletion(-) create mode 100644 Docs/Neues_Konzept_mit_TTS_auf_Mobil_Geraet.md diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md index 3e50498..3640eec 100644 --- a/BEDIENUNGSANLEITUNG.md +++ b/BEDIENUNGSANLEITUNG.md @@ -35,7 +35,7 @@ funktioniert trotzdem, die Ausgabe ist dann unformatiert. 1. [Was ist dieses System?](#1-was-ist-dieses-system) 2. [Installation und Einrichtung](#2-installation-und-einrichtung) 3. [Betriebsprofile wählen](#3-betriebsprofile-wählen) -4. [Starten und Stoppen](#4-starten-und-stoppen) — [4.5 llama.cpp](#45-llamacpp-server-für-profil-hybridlocal-dev) · [4.6 Ollama](#46-ollama-alternative-zu-llamacpp-kein-docker-nötig) +4. [Starten und Stoppen](#4-starten-und-stoppen) — [4.5 llama.cpp](#45-llamacpp-server-für-profil-hybridlocal-dev) · [4.6 Ollama](#46-ollama-alternative-zu-llamacpp-kein-docker-nötig) · [4.7 Wechseln](#47-zwischen-llamacpp-und-ollama-wechseln) **Bedienung** 5. [Das System benutzen](#5-das-system-benutzen) @@ -533,6 +533,49 @@ VA_PROFILE=local-dev make run # alles lokal (STT/TTS in-process, LLM via Ollam --- +### 4.7 Zwischen llama.cpp und Ollama wechseln + +Beide Server können nicht gleichzeitig auf demselben GPU-Speicher laufen. Vor dem +Wechsel muss der jeweils andere Backend-Prozess beendet werden. + +**Merkhilfe:** +- llama.cpp = Docker-Container `va_llm` → stoppen mit `make llm-down` +- Ollama = systemd-Dienst → stoppen mit `sudo systemctl stop ollama` + +#### Von Ollama → llama.cpp wechseln + +```bash +# 1) Ollama stoppen +sudo systemctl stop ollama +# falls manuell gestartet (ollama serve im Vordergrund): +pkill -f "ollama serve" 2>/dev/null || true + +# 2) llama.cpp starten und warten +make llm-up +make llm-status # warten bis „Modell bereit" + HTTP OK erscheint + +# 3) Gateway starten +VA_PROFILE=hybrid make run +``` + +#### Von llama.cpp → Ollama wechseln + +```bash +# 1) llama.cpp stoppen +make llm-down +# alternativ direkt: +docker rm -f va_llm + +# 2) Ollama starten +sudo systemctl start ollama +ollama ps # prüfen ob Modell aktiv (oder leer — wird beim ersten Request geladen) + +# 3) Gateway starten +VA_PROFILE=hybrid make run +``` + +--- + ## 5. Das System benutzen > 👤 Endnutzer @@ -1894,6 +1937,7 @@ in `app/dependencies.py` + Implementierung in `app/providers/`. → [Architektur | llama.cpp | § 4.5, § 3.2, § 3.3 | | local-dev-Profil | § 3.3 | | Ollama starten | § 4.6 | +| Ollama ↔ llama.cpp wechseln | § 4.7 | | Metriken / Monitoring | § 9.2, Anhang B.1 | | Mikrofon → Audio-Geräte | § 6.7 | | Notfall-Erkennung | § 10 | diff --git a/Docs/Neues_Konzept_mit_TTS_auf_Mobil_Geraet.md b/Docs/Neues_Konzept_mit_TTS_auf_Mobil_Geraet.md new file mode 100644 index 0000000..1bf7932 --- /dev/null +++ b/Docs/Neues_Konzept_mit_TTS_auf_Mobil_Geraet.md @@ -0,0 +1,556 @@ + + +# Voice Assistant, Ubuntu 24.04, Python, iPhone, Andoid-Handsy: + +Ich habe mit Python unter Linux einen Voice Assistenten Programmiert, mit dem sich der User unterhalten kann. Das System soll für Senioren stundenlangen Smalltalk mit KI ermöglichen (gegen Einsamkeit, multiuserfähig, mit Gedächtnis). Es funktioniert vereinfacht so: Das System wandelt Sprache in Text um (STT), gibt den Text an ein LLM-KI-Tool weiter. Das LLM formuliert eine adäquate Text-Antwort. Die wird angezeigt und in Sprache umgewandelt (TTS) und abgespielt. + +Das funktioniert am Desktop und auf Handys sowie auf Tablets im Browser, am Server auch im Terminal. Aber die Umwandlung von Text to Speech (TTS) in sehr guter Sprachqualität (also nicht mit Piper oder chatterbox via Python, die auch implementiert sind) ist einerseits teuer (Google-TTS-Tool via OpenRouter kostet ca. 2 Cent pro Minute Sound) , andererseits kommt der Ton verzögert auf dem Handy an, weil im Vergleich zum reinen Text große Sounddateien übers Netz zum Handy geschickt werden müssen. + +Nun stellt sich die Frage, ob es für IOS- und Android-Geräte die Möglichkeit gibt, den gesendeten Text erst auf dem Handy in Sprache mit professioneller Qualität umwandeln zu lassen. Das könnte unmittelbar passieren (Siri oder Ängliches) oder über Flat-Rate-Apps, die Cloud-Anbindung haben. + +1. Geht das? +2. Wie teuer wäre das? +3. Wie schnell sind die Tools? +4. Könnte man eventuell auch sogar die TTS-Umwandlung auf dem Handy laufen lassen? + +Ja, **das geht** sehr gut – und für Ihr Szenario ist „Text vom Server ans Handy schicken, TTS lokal auf dem Handy ausführen“ wahrscheinlich die beste Architektur, zumindest als Standardpfad für iPhone und viele Android-Geräte. iPhone und Android bringen eigene TTS-Engines mit, die direkt auf dem Gerät sprechen können; dadurch entfallen große Audiodateien über das Netz, die Latenz sinkt stark, und die laufenden Kosten für TTS können auf nahezu null fallen.[^1_1][^1_2] + +## Machbarkeit + +Auf dem iPhone kann eine App oder eine Weboberfläche Text an die systemeigene Sprachausgabe übergeben; Apple stellt dafür `AVSpeechSynthesizer` bereit, und Nutzer können in den Bedienungshilfen Stimmen auswählen, inklusive herunterladbarer „Enhanced Quality“-Stimmen. Diese erweiterten Stimmen sind lokal auf dem Gerät nutzbar und laut Apple oft 100 MB oder größer, was klar darauf hindeutet, dass die hochwertige Ausgabe zumindest nach dem Download lokal erfolgt.[^1_3][^1_1] + +Auf Android gibt es ebenfalls eine eingebaute `TextToSpeech`-API mit `speak()`, also genau den Mechanismus, den man für eine lokale oder systemnahe Ausgabe braucht. In der Praxis hängt die Qualität dort stärker vom installierten TTS-Engine-Provider ab, etwa Google Speech Services oder Samsung, aber grundsätzlich ist On-Device-TTS auf Android ein Standard-Use-Case.[^1_4][^1_5][^1_2] + +## Qualität und Geschwindigkeit + +Für **Geschwindigkeit** ist lokales TTS auf dem Handy fast immer besser als serverseitig erzeugtes Audio, weil Sie nur Text übertragen statt MP3/Opus/WAV-Dateien. Das spart Netzlast und vermeidet den zusätzlichen Schritt „Audio generieren → speichern → übertragen → puffern → abspielen“; bei lokaler TTS beginnt die Wiedergabe oft quasi sofort nach Erhalt des Textes.[^1_2][^1_3] + +Bei der **Qualität** ist iPhone derzeit meist der dankbarere Pfad, weil Apple hochwertige Systemstimmen und Enhanced-Varianten anbietet. Android kann ebenfalls gut klingen, aber dort ist die Qualität weniger homogen, weil sie vom Hersteller, der Android-Version und der installierten Engine abhängt.[^1_5][^1_1][^1_2] + +## Kosten + +Wenn Sie die System-TTS des Handys nutzen, sind die direkten TTS-Kosten typischerweise **null**, abgesehen von der einmaligen Datenmenge für den Download hochwertiger Stimmen und eventuell App-Entwicklung. Das ist für ein Senioren-Smalltalk-System wirtschaftlich sehr attraktiv, weil lange Gespräche nicht linear TTS-Kosten erzeugen.[^1_1][^1_2] + +Zum Vergleich: Cloud-TTS kostet je nach Anbieter und Qualitätsstufe weiter spürbar Geld. Google Cloud verlangt zum Beispiel für Neural2-Stimmen 16 US-Dollar pro 1 Mio. Zeichen, für WaveNet 4 US-Dollar pro 1 Mio. Zeichen und für HD-Stimmen 30 US-Dollar pro 1 Mio. Zeichen; OpenAI listet für GPT-Realtime-Translate 0,034 US-Dollar pro Minute und für Realtime-Whisper 0,017 US-Dollar pro Minute, während die Realtime-Audioausgabe tokenbasiert abgerechnet wird. Ihr genannter Wert von etwa 2 Cent pro Minute liegt also durchaus in einer realistischen Größenordnung für hochwertige Cloud-Audio-Pipelines, besonders wenn noch ein Vermittler wie OpenRouter dazwischenliegt.[^1_6][^1_7] + +## Sinnvolle Architektur + +Für Ihr Projekt würde ich drei Betriebsmodi unterscheiden: + + +| Modus | Technik | Kosten | Latenz | Qualität | Eignung | +| :-- | :-- | --: | --: | :-- | :-- | +| Browser/App mit lokaler System-TTS | Text an iPhone/Android, dort sprechen | Nahe 0 [^1_1][^1_2] | Sehr gut [^1_2][^1_3] | iPhone meist gut bis sehr gut, Android geräteabhängig [^1_1][^1_2] | **Standardfall** | +| Cloud-TTS als Premium-Fallback | Server erzeugt Audio | Laufend nutzungsabhängig [^1_6][^1_7] | Mittel bis schwankend | Sehr hoch | Für Spezialstimmen | +| Komplett lokal auf Handy | Native App mit OS-TTS | Nahe 0 [^1_1][^1_2] | Sehr gut [^1_2][^1_3] | Gut, aber nicht völlig frei wählbar [^1_1][^1_2] | Beste mobile UX | + +Der Knackpunkt ist: Im **Browser** ist das auf Android meist einfacher, weil Web Speech / systemnahe TTS dort oft besser nutzbar ist; auf iOS ist Browser-TTS funktional möglich, aber Apple ist restriktiver, und für eine robuste Produktlösung ist eine kleine native App oder ein WebView-Wrapper oft verlässlicher. Wenn Sie Multiuser, Gedächtnis und lange Sessions sauber betreiben wollen, wäre daher ein Server für STT/LLM/State plus mobile App für Playback eine sehr saubere Trennung.[^1_2][^1_3] + +## Konkrete Antwort auf Ihre 4 Fragen + +1. **Geht das?** +Ja. Sowohl iPhone als auch Android können empfangenen Text lokal in Sprache umwandeln; iPhone über Apples Sprachsynthese und Android über `TextToSpeech`.[^1_3][^1_1][^1_2] +2. **Wie teuer wäre das?** +Mit lokaler Geräte-TTS meist praktisch kostenlos im Betrieb. Cloud-TTS dagegen kostet je nach Stimme und Anbieter etwa von wenigen Dollar bis deutlich höheren Beträgen pro 1 Mio. Zeichen oder minutenbasiert bei Realtime-Angeboten.[^1_7][^1_6] +3. **Wie schnell sind die Tools?** +Lokale TTS ist in der Regel schneller wahrnehmbar, weil nur Text übertragen wird und keine Audiodatei gepuffert werden muss. Für Ihr Problem „Ton kommt verzögert aufs Handy“ ist das genau der Hauptvorteil.[^1_2][^1_3] +4. **Kann die TTS-Umwandlung auf dem Handy laufen?** +Ja, und genau das würde ich empfehlen. Auf iPhone ist das mit den Apple-Stimmen besonders interessant, auf Android ebenfalls gut machbar, aber mit etwas mehr Varianz bei der Stimmqualität.[^1_1][^1_2] + +Für Ihr Seniorensystem würde ich praktisch so bauen: Server liefert nur Text, Metadaten und Steuerkommandos; die mobile App spricht lokal mit System-TTS; Cloud-TTS nur optional für „Premium-Stimme“ oder wenn eine ganz bestimmte Persona gebraucht wird. Soll ich Ihnen als Nächstes eine konkrete Zielarchitektur skizzieren – einmal als reine Browserlösung und einmal als robuste native iPhone/Android-App?[^1_7][^1_1][^1_2] +[^1_10][^1_11][^1_12][^1_13][^1_14][^1_15][^1_16][^1_17][^1_18][^1_19][^1_20][^1_21][^1_22][^1_23][^1_24][^1_25][^1_26][^1_27][^1_28][^1_29][^1_8][^1_9] + +
+ +[^1_1]: https://support.apple.com/en-lb/111798 + +[^1_2]: https://developer.android.com/reference/android/speech/tts/TextToSpeech + +[^1_3]: https://a11y-guidelines.orange.com/en/mobile/ios/wwdc/2018/236/ + +[^1_4]: https://support.google.com/accessibility/android/answer/6006983?hl=en + +[^1_5]: https://play.google.com/store/apps/details?id=com.google.android.tts + +[^1_6]: https://medium.com/@john.goodstadt/artificial-intelligence-from-an-ios-app-1-a880f3dd4323 + +[^1_7]: https://www.oreateai.com/blog/unlocking-androids-voice-a-deep-dive-into-texttospeech-api/7b5fcae54518ca663c26d61df106c6df + +[^1_8]: https://www.finout.io/blog/openai-pricing-in-2026 + +[^1_9]: https://www.youtube.com/watch?v=_UD_dhuUozs + +[^1_10]: https://cloud.google.com/text-to-speech/pricing + +[^1_11]: https://www.pcmag.com/how-to/how-to-use-the-iphone-text-to-speech-feature + +[^1_12]: https://android-developers.googleblog.com/2024/03/introducing-new-text-to-speech-engine-wear-os.html + +[^1_13]: https://openai.com/api/pricing/ + +[^1_14]: https://www.youtube.com/watch?v=SXuTWmmTQwU + +[^1_15]: https://medium.com/@mrizqi070502/speak-up-implement-text-to-speech-in-android-3ad0f7f2580 + +[^1_16]: https://crazyrouter.com/en/blog/text-to-speech-api-comparison-2026 + +[^1_17]: https://medium.com/google-cloud/how-to-integrate-google-cloud-text-to-speech-api-into-your-ios-app-140ab7be42ae + +[^1_18]: https://the-rogue-marketing.github.io/google-gemini-tts-speech-audio-api-pricing-may-2026/ + +[^1_19]: https://devstreaming-cdn.apple.com/videos/wwdc/2018/236mwbxbxjfsvns4jan/236/236_avspeechsynthesizer_making_ios_talk.pdf?dl=1 + +[^1_20]: https://wildandfreetools.com/blog/text-to-speech-iphone-ios-complete-guide-free/ + +[^1_21]: https://android-developers.googleblog.com/2009/09/introduction-to-text-to-speech-in.html + +[^1_22]: https://stackoverflow.com/questions/60116322/availability-of-installed-voices-for-use-by-avspeechsynthesis-in-ios + +[^1_23]: https://sustainablecomputing.net/2024/01/29/speak-text-on-the-screen/ + +[^1_24]: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/speech/tts/TextToSpeech.java + +[^1_25]: https://github.com/NSHipster/articles/blob/master/2014-03-31-avspeechsynthesizer.md + +[^1_26]: https://discussions.apple.com/thread/255707687 + +[^1_27]: https://stackoverflow.com/questions/22189778/can-we-give-a-custom-voice-to-avspeechsynthesizer + +[^1_28]: https://www.youtube.com/watch?v=22mdFf4aLmI + +[^1_29]: http://opensource.hcltechsw.com/volt-mx-native-function-docs/Android/android.speech.tts-Android-10.0/ + + +--- + +# ja + +Dann skizziere ich dir zwei Zielarchitekturen: + +1) „Nur Browser“ (ohne App), +2) „saubere“ native iOS-/Android-App, die dein bestehendes Python-Backend nutzt. + +*** + +## 1. Reine Browser‑Lösung (Web Speech / System‑TTS) + +### Grundidee + +- Dein Python‑Backend liefert nur Text (LLM‑Antwort + Metadaten). +- Im Browser rufst du per JavaScript die **Web Speech / SpeechSynthesis API** auf, die wiederum die **jeweilige Geräte‑TTS** nutzt (auf Android typischerweise Google TTS, auf iOS die lokalen Apple‑Stimmen).[^2_1][^2_2] +- Du überträgst also keinen Audiostream mehr, sondern nur Text → minimale Latenz, praktisch keine TTS‑Kosten.[^2_2][^2_1] + + +### Browser‑Support und Stolpersteine + +- Die SpeechSynthesis‑API ist in modernen Desktop‑Browsern und auf iOS Safari, Chrome/Firefox Android weitgehend unterstützt.[^2_3][^2_4][^2_1] +- Android: + - Chrome für Android hat volle SpeechSynthesis‑Unterstützung, Firefox Android ebenfalls.[^2_4][^2_3] + - Die Stimmen kommen i.d.R. vom Google‑TTS‑Dienst bzw. vom OS‑TTS; Qualität ist je nach Gerät und Sprache ziemlich ordentlich.[^2_5][^2_6][^2_7] +- iOS: + - Safari auf iOS unterstützt SpeechSynthesis, aber mit Besonderheiten: erste Ausgabe muss aus einem echten User‑Event (Button‑Klick o.ä.) kommen, Hintergrundwiedergabe ist eingeschränkt und es gibt Bugs beim Voice‑Wechsel.[^2_8][^2_9][^2_10] + - Praktisch heißt das: Du brauchst am Anfang der Session einen expliziten „Audio aktivieren“-Button, der einmalig eine Dummy‑Utterance abspielt, danach kannst du programmatisch sprechen.[^2_11][^2_10] + + +### Bewertung für dein Use Case + +**Vorteile** + +- Kein App‑Store‑Deployment nötig. +- Minimaler Netzwerk‑Traffic, TTS praktisch kostenlos.[^2_1][^2_2] +- Für Android‑Tablets/Phones mit Chrome läuft das erstaunlich robust und performant.[^2_3][^2_4] + +**Nachteile** + +- iOS Safari ist launisch: kein Background‑Audio, TTS stoppt teils beim Wechsel in andere Apps und erfordert Workarounds.[^2_12][^2_10][^2_8] +- Du hast relativ wenig Kontrolle über Voice‑Auswahl, Lautstärke, Audio‑Routing etc., alles ist vom Browser/OS abhängig.[^2_9][^2_1] + +Wenn du Senior:innen ein **„immer an, immer verfügbar“‑Gefühl** geben willst, das auch beim Display‑Lock oder App‑Wechsel noch halbwegs stabil reagiert, kommst du auf iOS mit einer **App** deutlich entspannter ans Ziel. + +*** + +## 2. Architektur mit nativer iOS‑ und Android‑App + +Hier nutzt du dein Linux‑/Python‑Backend weiter wie bisher (STT→LLM→Text), verschiebst aber TTS vollständig ins Handy. + +### Backend (Python / Ubuntu / Server) + +- Bleibt weitgehend wie heute: + - WebSocket oder HTTP(s) für Text‑Nachrichten. + - Session‑Management (User‑ID, Gesprächskontext, Gedächtnis). + - STT entweder serverseitig (z.B. Whisper) oder auch schon lokal, falls du später native STT am Handy nutzen willst. +- Erweiterung: + - Statt Audio sendest du **nur Text + Steuerinfos**: z.B. `{ text, speakerId, emotion, priority }`. + - Optional: „SSML‑Marken“ für Pausen, Betonung, etc. (einige mobile TTS‑Engines verstehen das).[^2_7][^2_13] + + +### iOS‑App + +- Spricht Text über **AVSpeechSynthesizer**: + - `AVSpeechUtterance(string:)` + `AVSpeechSynthesizer().speak(utterance)`.[^2_14][^2_15] + - Nutzer:innen können im System „Sprachausgabe“/„Spoken Content“ die Stimme (auch „Enhanced Quality“) und Sprache auswählen.[^2_16] + - Diese Stimmen sind nach Download lokal verfügbar und bieten sehr hohe Qualität.[^2_16] +- Vorteile: + - Zuverlässige Audioausgabe, Hintergrund‑Audio lässt sich sauber konfigurieren (AVAudioSession, Background Modes).[^2_12][^2_14] + - Du umgehst alle Safari/Web‑Speech‑Eigenheiten komplett – die App kontrolliert Wiedergabe, Lautstärke, Unterbrechung durch Telefonate etc. + + +### Android‑App + +- Nutzt die `TextToSpeech`‑API: + - `TextToSpeech(context, OnInitListener)`, danach `tts.speak(text, QUEUE_ADD, params, utteranceId)`.[^2_13][^2_7] + - TTS‑Engine: Google Speech Services (Standard) oder andere Engines, die Nutzer installieren.[^2_6][^2_5] + - Ab Android‑Seite kannst du Geschwindigkeit, Tonhöhe und ggf. Voice auswählen.[^2_7] +- Vorteile: + - Gute Latenz, da komplett lokal.[^2_7] + - Hintergrund‑Speech ist in nativen Apps deutlich besser handhabbar als im Browser.[^2_7] + + +### Netzwerk‑Protokoll zwischen Handy und Backend + +- Idealerweise **WebSocket**, weil du eh schon längere Sessions fährst. +Einfaches Schema: + - Client → Server: + - `user_audio_chunk` (falls STT serverseitig), + - `user_text` (falls STT in der App), + - `control` (Pause, Stop, etc.). + - Server → Client: + - `assistant_text` (LLM‑Antwort), + - optional `assistant_meta` (Emotion, Sprechtempo), + - keine Audiodaten mehr. +- Auf dem Client: + - Für jede eingehende Antwort wird direkt ein `utterance` erzeugt und in die lokale TTS‑Queue gestellt. + + +### Kosten, Geschwindigkeit, Qualität im Vergleich + +| Variante | TTS‑Ort | Laufende TTS‑Kosten | Latenz bis Ton | Qualitäts‑Kontrolle | Bemerkung | +| :-- | :-- | :-- | :-- | :-- | :-- | +| Heute (Cloud‑TTS über OpenRouter) | Server | Cents pro Minute, summiert sich [^2_17][^2_18] | Audio über Netz → spürbare Verzögerung | Sehr hoch, aber Provider‑abhängig [^2_17][^2_18] | Problem: Kosten + Latenz | +| Web‑only mit SpeechSynthesis | Handy / Browser | Praktisch 0 [^2_1][^2_2] | Sehr gut, nur Text übertragen [^2_1][^2_2] | gut, aber Browser‑abhängig [^2_3][^2_4] | Android sehr gut, iOS okay mit Workarounds | +| Native App + System‑TTS | Handy / OS | Praktisch 0 [^2_16][^2_7] | Sehr gut, offlinefähig [^2_7][^2_14] | iOS sehr gut, Android gut [^2_16][^2_7] | Beste Kontrolle und UX | + + +*** + +## 3. Lokale TTS‑Engines auf dem Handy (ohne Cloud) + +Deine Frage 4 zielte noch einmal extra darauf ab, ob die gesamte TTS‑Umwandlung direkt auf dem Handy laufen kann – also ohne Cloud. + +- iOS: + - Die herunterladbaren „hochwertigen Stimmen“ in Spoken Content/VoiceOver sind genau dafür gedacht: hochwertige Sprachausgabe, lokal, nachdem die Stimme einmal geladen wurde.[^2_16] + - Du nutzt sie transparent über AVSpeechSynthesizer; du musst keinen separaten TTS‑Dienst ansprechen.[^2_14] +- Android: + - Google Speech Services („Speech Recognition \& Synthesis“) liefern lokale Text‑zu‑Sprache‑Funktionalität für Apps.[^2_5][^2_6] + - Die `TextToSpeech`‑API arbeitet i.d.R. auch offline, solange die entsprechende Sprach‑Engine und Sprachpakete installiert sind.[^2_13][^2_7] + +Damit hast du eine **vollständig lokale TTS‑Pipeline auf dem Endgerät**, mit sehr wenig Netzbedarf und in vielen Fällen guter Qualität. + +*** + +## Was ich dir konkret vorschlagen würde + +Für deinen Senior:innen‑Assistenten würde ich: + +1. **Kurzfristig**: + - In der bestehenden Web‑UI Web Speech / SpeechSynthesis integrieren (also im Browser TTS starten statt Audio vom Server zu spielen). + - Sicheren „Audio aktivieren“-Button implementieren (wegen iOS‑Restrictions).[^2_10][^2_8] + - Logging/Telemetry einbauen, um zu sehen, bei welchen Geräten/Browsern es hakt. +2. **Mittelfristig**: + - Eine sehr schlanke native iOS‑ und Android‑App bauen: + - UI im Wesentlichen ein WebView/eine im Browser bereits bestehende Oberfläche, + - aber TTS und ggf. STT per nativen APIs (`AVSpeechSynthesizer` / `TextToSpeech`). + - Dein Python‑Backend bleibt unverändert, liefert nur Text. + +Wenn du mir sagst, ob du eher **Web‑Only** bleiben willst oder mittelfristig **echte Apps** für iOS/Android planst, kann ich dir im nächsten Schritt sehr konkret Pseudocode/Architektur‑Snippets (inkl. Beispiel‑WebSocket‑Protokoll und Swift/Kotlin‑Skizzen) formulieren. +[^2_19][^2_20][^2_21][^2_22][^2_23][^2_24] + +
+ +[^2_1]: https://wiki.selfhtml.org/wiki/Web_Speech + +[^2_2]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API + +[^2_3]: https://www.lambdatest.com/web-technologies/speech-synthesis + +[^2_4]: https://caniuse.com/speech-synthesis + +[^2_5]: https://support.google.com/accessibility/android/answer/6006983?hl=en + +[^2_6]: https://play.google.com/store/apps/details?id=com.google.android.tts + +[^2_7]: https://developer.android.com/reference/android/speech/tts/TextToSpeech + +[^2_8]: https://weboutloud.io/bulletin/speech_synthesis_in_safari/ + +[^2_9]: https://elliotbentley.com/blog/html5-speech-synthesis-api/ + +[^2_10]: https://stackoverflow.com/questions/67655133/when-will-speechsynthesis-speak-work-on-ios-safari/72199291 + +[^2_11]: https://www.reddit.com/r/learnjavascript/comments/1smimrx/help_mobile_safari_web_speech_api_silent_failure/ + +[^2_12]: https://developer.apple.com/forums/thread/771040 + +[^2_13]: https://android-developers.googleblog.com/2009/09/introduction-to-text-to-speech-in.html + +[^2_14]: https://a11y-guidelines.orange.com/en/mobile/ios/wwdc/2018/236/ + +[^2_15]: https://github.com/NSHipster/articles/blob/master/2014-03-31-avspeechsynthesizer.md + +[^2_16]: https://support.apple.com/en-lb/111798 + +[^2_17]: https://medium.com/@john.goodstadt/artificial-intelligence-from-an-ios-app-1-a880f3dd4323 + +[^2_18]: https://www.oreateai.com/blog/unlocking-androids-voice-a-deep-dive-into-texttospeech-api/7b5fcae54518ca663c26d61df106c6df + +[^2_19]: https://developer.mozilla.org/fr/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API + +[^2_20]: https://developer.chrome.com/blog/web-apps-that-talk-introduction-to-the-speech-synthesis-api + +[^2_21]: https://dzone.com/articles/the-developers-guide-to-web-speech-api-what-is-it + +[^2_22]: http://devdoc.net/web/developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API.html + +[^2_23]: https://developer.chrome.com/blog/voice-driven-web-apps-introduction-to-the-web-speech-api + +[^2_24]: https://blog.addpipe.com/a-deep-dive-into-the-web-speech-api/ + + +--- + +# Könnte man eventuell auch sogar die STT-Umwandlung auf dem Handy laufen lassen? + +Ja – **STT auf dem Handy** laufen zu lassen ist grundsätzlich möglich, und technisch sogar sehr attraktiv für dein System. Sowohl iPhone als auch Android bieten Wege für lokale bzw. gerätenahe Spracherkennung; im Browser ist das aber deutlich unzuverlässiger als in nativen Apps.[^3_1][^3_2][^3_3] + +## Native Apps + +Auf iPhone unterstützt Apples Speech-Framework On-Device-Erkennung; seit iOS 13 gibt es dafür die Option `requiresOnDeviceRecognition`, also echte lokale Transkription ohne Serverpflicht, sofern Sprache und Gerät das unterstützen. Zusätzlich kann Apple auch Diktat- und Siri-nahe Funktionen teilweise offline ausführen, was zeigt, dass Sprachverarbeitung auf dem Gerät inzwischen ein normaler Pfad ist.[^3_4][^3_5][^3_6][^3_1] + +Auf Android gibt es mit `SpeechRecognizer` die systemeigene API für Spracherkennung. Offline-Erkennung ist dort grundsätzlich möglich, wenn die passende Engine und die Offline-Sprachpakete installiert sind; die praktische Qualität hängt aber stärker als bei iOS von Hersteller, Android-Version und installierter Sprach-Engine ab.[^3_7][^3_8][^3_3] + +## Browser + +Im **mobilen Browser** ist STT die deutlich schwierigere Baustelle als TTS. Die Web Speech API unterstützt Spracherkennung zwar grundsätzlich, aber der Support ist laut aktuellen Kompatibilitätsübersichten nur partiell: Chrome auf Android und Safari auf iOS teilweise, Firefox Android gar nicht. Für ein Seniorenprodukt mit langen Gesprächen und Multiuser-Betrieb ist das zu fragil, wenn du eine verlässliche Hauptlösung willst.[^3_9][^3_10] + +Es gibt zwar inzwischen in der Web Speech API auch einen Pfad für **On-Device-Speech-Recognition** über `processLocally = true`, inklusive Sprachpaket-Download via `SpeechRecognition.available()` und `SpeechRecognition.install()`. Aber das ist browserabhängig und noch weit davon entfernt, plattformübergreifend so robust zu sein wie native APIs.[^3_2][^3_9] + +## Architekturfolgen + +Wenn du STT aufs Handy verlagerst, sendet das Gerät nur noch **Text** oder kleine Transkriptions-Events an deinen Python-Server, statt kontinuierlich Audiodaten hochzuladen. Das senkt Bandbreite, reduziert Datenschutzrisiken und kann die wahrgenommene Reaktionszeit verbessern, weil das erste erkannte Textstück früher beim Backend ankommt.[^3_3][^3_1][^3_2] + +Für deine Architektur ergeben sich damit drei sinnvolle Varianten: + +- **STT lokal, TTS lokal, LLM am Server** – wahrscheinlich der beste Zielzustand für mobile Apps.[^3_5][^3_1][^3_3] +- **STT serverseitig, TTS lokal** – guter Zwischenschritt, wenn du am Backend wenig ändern willst.[^3_11][^3_12] +- **STT und TTS im Browser lokal** – machbar als Experiment oder Android-first-Weblösung, aber nicht robust genug als alleinige Senioren-Produktionslösung.[^3_2][^3_9] + + +## Empfehlung + +Für dein Szenario würde ich STT auf dem Handy **ja, aber vorzugsweise nativ** einplanen. iPhone ist dafür besonders interessant, weil Apple On-Device-Recognition offiziell unterstützt. Android geht ebenfalls gut, braucht aber mehr Tests pro Gerätekategorie und Sprachpaket-Setup.[^3_1][^3_7][^3_5][^3_3] + +Die pragmatische Reihenfolge wäre: + +- Erst **TTS lokal aufs Handy** verlagern, weil das sofort Kosten und Latenz spart.[^3_12][^3_11] +- Danach **STT nativ mobil** ergänzen. +- Browser-STT nur als optionalen Fallback oder Prototyp betrachten.[^3_9][^3_2] + +Für deine Produktidee wäre also eine sehr plausible Endarchitektur: +**Mobiles Gerät:** STT lokal + TTS lokal.[^3_3][^3_1] +**Server unter Ubuntu/Python:** Session-Logik, Memory, Benutzerverwaltung, LLM-Orchestrierung.[^3_1][^3_3] + +Soll ich dir als Nächstes eine konkrete **Soll-Architektur mit Komponentenliste** skizzieren – getrennt nach Web-only, Android-App und iPhone-App? +[^3_13][^3_14][^3_15][^3_16][^3_17] + +
+ +[^3_1]: https://stackoverflow.com/questions/42900254/is-there-a-way-to-use-ios-speech-recognition-in-offline-mode/57047665 + +[^3_2]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API + +[^3_3]: https://developer.android.com/reference/android/speech/SpeechRecognizer + +[^3_4]: https://plymouth.libguides.com/tech/voicerecognition + +[^3_5]: https://9to5mac.com/2019/11/07/new-dictation-app-brings-advanced-offline-transcription-capabilities-to-iphone-and-ipad/ + +[^3_6]: https://www.idownloadblog.com/2021/06/08/ios-15-siri-offline-features/ + +[^3_7]: https://stackoverflow.com/questions/31562229/offline-speech-recognition-in-android + +[^3_8]: https://www.oreateai.com/blog/whispers-in-your-pocket-making-android-speechtotext-work-offline/7a0284926c7c184dd6483638a755f963 + +[^3_9]: https://www.lambdatest.com/web-technologies/speech-recognition + +[^3_10]: https://blog.addpipe.com/a-deep-dive-into-the-web-speech-api/ + +[^3_11]: https://support.apple.com/en-lb/111798 + +[^3_12]: https://developer.android.com/reference/android/speech/tts/TextToSpeech + +[^3_13]: https://soniqo.audio/getting-started/android + +[^3_14]: https://devdoc.net/web/developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API.html + +[^3_15]: https://apps.apple.com/us/app/speech-to-text-offline/id6756486902 + +[^3_16]: https://www.reddit.com/r/androiddev/comments/w3lm92/offline_streaming_speech_to_text/ + +[^3_17]: https://towardsdatascience.com/web-speech-api-what-works-what-doesnt-and-how-to-improve-it-by-linking-it-to-a-gpt-language-dc1afde54ced/ + + +--- + +# ja + +Ja. Für dein System würde ich drei Soll-Architekturen unterscheiden: **Web-only**, **Android nativ zuerst**, und **iPhone nativ**. Die technische Kernidee ist in allen Fällen gleich: STT und TTS möglichst nahe ans Endgerät, während dein Ubuntu/Python-Server nur noch Orchestrierung, Gedächtnis, Benutzerverwaltung und LLM-Antworten übernimmt.[^4_1][^4_2][^4_3] + +## Web-only + +Bei einer reinen Weblösung läuft TTS über `speechSynthesis`, und STT über die Web Speech API. Neuere Web-API-Dokumentation beschreibt dafür sogar `processLocally = true` sowie Sprachpaket-Prüfung per `SpeechRecognition.available()` und Installation per `SpeechRecognition.install()`, also grundsätzlich einen Pfad zu lokaler Erkennung im Browser.[^4_2][^4_4][^4_5] + +Für Produktion wäre das aber nur als **Best-Effort**-Variante sinnvoll, weil Browser-Support und Verhalten je nach Plattform stark schwanken. Deshalb sollte dein Server in dieser Variante immer auch einen Fallback haben: Browser-STT lokal, sonst Browser-/Server-STT; TTS lokal im Browser, sonst notfalls Audio vom Server.[^4_4][^4_5][^4_2] + +### Komponenten + +- Browser-UI: Aufnahme, Push-to-talk oder VAD, Textanzeige, lokale TTS/STT.[^4_2][^4_4] +- Python-Backend: Session-State, Multiuser, Gedächtnis, LLM, WebSocket-Transport. +- Fallback-Logik: erkennt, ob lokales STT/TTS verfügbar ist, und schaltet sonst auf Serverpfade um.[^4_5] + + +### Datenfluss + +1. Browser startet lokale Erkennung, wenn verfügbar.[^4_2] +2. Browser sendet nur Text-Teilresultate oder Final-Text zum Server. +3. Server antwortet mit Text. +4. Browser spricht den Text lokal aus. + +## Android nativ + +Android ist als erster nativer Schritt besonders sinnvoll, weil `SpeechRecognizer` offiziell für App-seitige Spracherkennung vorgesehen ist und Offline-Betrieb mit installierten Sprachpaketen möglich ist. Für vollständig lokale Alternativen gibt es zudem erprobte Bibliotheken wie Vosk für Android, falls du dich nicht an die jeweilige System-Engine binden willst.[^4_6][^4_7][^4_3] + +Damit könntest du auf Android **STT lokal + TTS lokal + LLM am Server** umsetzen. Das reduziert Netztraffic stark, verbessert Privatsphäre und senkt die laufenden Sprachkosten praktisch auf null.[^4_7][^4_3][^4_6] + +### Komponenten + +- Android-App: + - `SpeechRecognizer` für STT, primär lokal/offline wenn Sprachpakete vorhanden sind.[^4_3][^4_6] + - `TextToSpeech` für TTS. + - WebSocket-Client für Serveranbindung. + - Lokale Audio-/Sessionsteuerung. +- Python-Backend: + - Auth, Multiuser, Gedächtnis, Gesprächslogik, LLM. + + +### Datenfluss + +1. Mikrofon geht an, Android-App transkribiert lokal.[^4_3] +2. Partials und Final-Text gehen per WebSocket an den Server. +3. Server generiert Antworttext. +4. Android-App spielt Antwort über lokale TTS. + +### Praktische Empfehlung + +- **Phase 1:** `SpeechRecognizer` + System-TTS. +- **Phase 2:** optional Vosk/ähnlich für vollständige Unabhängigkeit von Google-Services.[^4_7] + + +## iPhone nativ + +Auf iPhone ist native STT ebenfalls möglich, und Apple dokumentiert dafür ausdrücklich `requiresOnDeviceRecognition`. Wenn diese Eigenschaft auf `true` gesetzt wird, verhindert das Senden der Audiodaten übers Netz; Apple weist aber darauf hin, dass On-Device-Erkennung weniger genau sein kann als Servererkennung. Apple empfiehlt außerdem, vorab zu prüfen, ob `supportsOnDeviceRecognition` vorhanden ist, und dann gezielt On-Device zu aktivieren.[^4_8][^4_9][^4_1] + +Damit ist die iPhone-Zielarchitektur sehr klar: **Speech Framework lokal**, **AVSpeechSynthesizer lokal**, **LLM und Memory am Server**. Für dein Senioren-Szenario ist das attraktiv, weil du eine kontrollierte UX bekommst, ohne Safari-Eigenheiten im Browser.[^4_9][^4_1][^4_8] + +### Komponenten + +- iOS-App: + - `SFSpeechRecognizer` + Request mit `requiresOnDeviceRecognition = true`.[^4_1] + - Prüfung auf `supportsOnDeviceRecognition` vor Sessionstart.[^4_8][^4_9] + - `AVSpeechSynthesizer` für lokale Sprachausgabe. + - WebSocket-Client für Texttransport. +- Python-Backend: + - wie bei Android. + + +### Datenfluss + +1. App nimmt Audio auf und transkribiert lokal, wenn unterstützt.[^4_9][^4_1] +2. Nur Text geht an den Server. +3. Server antwortet mit Text. +4. iPhone spricht lokal. + +## Gemeinsame Serverarchitektur + +Dein Ubuntu-24.04-/Python-Backend kann in allen drei Varianten nahezu gleich bleiben. Es sollte nur noch diese Kernrollen übernehmen: + +- Benutzer- und Sitzungsverwaltung. +- Gedächtnis / Langzeitkontext. +- LLM-Orchestrierung. +- WebSocket- oder SSE-Schnittstelle für Text-Events. +- Optionaler Fallback-STT/TTS, wenn ein Client lokales Speech nicht kann.[^4_1][^4_3][^4_2] + +Ein sinnvolles Nachrichtenmodell wäre: + +- Client → Server: + - `session_start` + - `partial_transcript` + - `final_transcript` + - `barge_in` + - `tts_stop` +- Server → Client: + - `assistant_text_partial` + - `assistant_text_final` + - `memory_hint` + - `fallback_required` + +Das passt gut zu langen Smalltalk-Sessions, weil du Unterbrechungen, Zwischenresultate und Streaming-Antworten sauber behandeln kannst. + +## Empfehlung + +Für dein Projekt würde ich die Reihenfolge so setzen: + + +| Stufe | Ziel | Warum | +| :-- | :-- | :-- | +| 1 | TTS lokal auf Handy | Sofort weniger Kosten und weniger Audio-Latenz. [^4_1][^4_3] | +| 2 | Android nativ mit lokalem STT | Technisch pragmatisch, gute Testbasis. [^4_3][^4_6] | +| 3 | iPhone nativ mit `requiresOnDeviceRecognition` | Sehr sauberer Apple-Pfad, gute UX. [^4_1][^4_9] | +| 4 | Browser-STT nur ergänzend | Nützlich als Fallback, aber nicht deine Hauptplattform. [^4_2][^4_5] | + +Wenn du möglichst effizient vorgehen willst, wäre mein Rat: **Android nativ zuerst**, mit lokalem STT/TTS und deinem bestehenden Python-Server dahinter. Danach iPhone nativ mit Apples On-Device-Speech-Framework.[^4_7][^4_3][^4_9][^4_1] + +Soll ich dir im nächsten Schritt eine **konkrete Referenzarchitektur mit Modulen, WebSocket-Events und Zustandsautomat** für dein Python-Backend plus Android-Client aufschreiben? +[^4_10][^4_11][^4_12][^4_13][^4_14][^4_15] + +
+ +[^4_1]: https://developer.apple.com/documentation/speech/sfspeechrecognitionrequest/requiresondevicerecognition + +[^4_2]: https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition/processLocally + +[^4_3]: https://developer.android.com/reference/android/speech/SpeechRecognizer + +[^4_4]: https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition + +[^4_5]: https://developer.mozilla.org/ja/docs/Web/API/SpeechRecognition/available_static + +[^4_6]: https://stackoverflow.com/questions/31562229/offline-speech-recognition-in-android + +[^4_7]: https://github.com/alphacep/vosk-android-demo + +[^4_8]: https://devstreaming-cdn.apple.com/videos/wwdc/2019/256p7m9z4yst71ai/256/256_advances_in_speech_recognition.pdf + +[^4_9]: https://developer.apple.com/videos/play/wwdc2019/256/ + +[^4_10]: https://stackoverflow.com/questions/17003620/can-i-make-android-offline-voice-recognition-api-public + +[^4_11]: https://developer.mozilla.org/ja/docs/Web/API/SpeechRecognition/processLocally + +[^4_12]: https://stackoverflow.com/questions/38729105/how-to-make-ios-speech-to-text-persistent/38729106 + +[^4_13]: https://qiita.com/m-naoki-m/items/38eb7199a07e844d3f49 + +[^4_14]: https://www.geeksforgeeks.org/android/offline-speech-to-text-without-any-popup-dialog-in-android/ + +[^4_15]: https://chromium.googlesource.com/external/github.com/web-platform-tests/wpt/+/refs/tags/merge_pr_53592/speech-api/SpeechRecognition-phrases-manual.https.html + diff --git a/README.md b/README.md index 983cd44..1ea1f3f 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,20 @@ VA_PROFILE=hybrid make run VA_PROFILE=local-dev make run ``` +### Backend wechseln (llama.cpp ↔ Ollama) + +Beide Server können nicht gleichzeitig laufen (geteilter GPU-Speicher). + +```bash +# → zu llama.cpp wechseln (Ollama vorher killen): +sudo systemctl stop ollama && pkill -f "ollama serve" 2>/dev/null || true +make llm-up && make llm-status + +# → zu Ollama wechseln (llama.cpp vorher killen): +make llm-down # oder: docker rm -f va_llm +sudo systemctl start ollama +``` + ### Alle `make`-Targets im Überblick ```bash