feat(voice): modalità dialogo — voce continua hands-free (v0.2.0)

- Nuovo VoiceRecorder (QAudioInput, PCM 16 bit mono): analisi del livello
  in tempo reale e stop automatico dopo il silenzio (pausa e soglia
  configurabili dalle impostazioni); produce WAV per /api/transcribe;
  emette failed("no-speech") se non rileva voce (cattura scartata)
- ChatPage: modalità dialogo (menu "Voice mode"): ascolto -> trascrizione
  -> invio -> lettura della risposta -> riascolto in ciclo; tocco sul
  testo di stato per uscire; limite di 3 errori consecutivi poi esce
- Dettatura manuale: invio automatico dopo la trascrizione (opzione,
  default attivo, disattivabile)
- Settings: sezione "Voice dialog" (auto-invio, pausa auto-stop,
  sensibilità microfono)
- Il percorso di dettatura manuale (Recorder OGG) resta invariato
This commit is contained in:
2026-09-12 09:14:25 +02:00
parent 479edb0f99
commit 9deeedf5b3
12 changed files with 620 additions and 18 deletions
+5 -2
View File
@@ -9,6 +9,7 @@
#include "player.h"
#include "recorder.h"
#include "settings.h"
#include "voicerecorder.h"
Q_DECL_EXPORT int main(int argc, char *argv[])
{
@@ -18,15 +19,16 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
// AppConfigLocation = ~/.config/harbour/hermes (zona persistente della sandbox).
app->setOrganizationName(QStringLiteral("harbour"));
app->setApplicationName(QStringLiteral("hermes"));
app->setApplicationVersion(QStringLiteral("0.1.0"));
app->setApplicationVersion(QStringLiteral("0.2.0"));
qDebug() << "harbour-hermes v0.1.0 build" << __DATE__ << __TIME__;
qDebug() << "harbour-hermes v0.2.0 build" << __DATE__ << __TIME__;
Settings settings;
ApiClient api(&settings);
ChatModel chat(&api);
Recorder recorder;
Player player;
VoiceRecorder voiceRec(&settings);
// Flusso voce: registrazione -> trascrizione; TTS pronto -> riproduzione.
QObject::connect(&recorder, &Recorder::finished, &api, &ApiClient::transcribeFile);
@@ -38,6 +40,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
view->rootContext()->setContextProperty(QStringLiteral("chat"), &chat);
view->rootContext()->setContextProperty(QStringLiteral("recorder"), &recorder);
view->rootContext()->setContextProperty(QStringLiteral("player"), &player);
view->rootContext()->setContextProperty(QStringLiteral("voiceRec"), &voiceRec);
view->rootContext()->setContextProperty(QStringLiteral("appVersion"),
QCoreApplication::applicationVersion());