Riconoscimento e sintesi vocale con Python

Riconoscimento e sintesi vocale con Python
Riconoscimento e sintesi vocale con Python

Riconoscimento e sintesi vocale: In questo articolo parlerò di due bellissime funzionalità di Python che non è nemmeno difficile testare: il riconoscimento vocale (speech recognizing) e la sintesi vocale.

Ho preso ispirazione dal sito copyassignment.com e mi sono un attimo studiato le librerie.

Analisi vocale (riconoscimento)

Il primo aspetto comprende i metodi con i quali viene analizzato il segnale audio.

Il parlato è un processo stocastico particolare nell’insieme dei suoni che ci circondano che ha delle caratteristiche peculiari. Vengono individuate all’interno del segnale audio cioè le caratteristiche come la frequenza, la presenza di determinati pattern:

  • segnali periodici, come le vocali o le mute “m”, “n”;
  • segnali aperiodici, come il suono “f” o “s” che assomigliano al rumore bianco
  • segnali “esplosivi” come le lettere “p”, “t” ecc.

e la suddivisione del segnale del parlato in fonemi. In sostanza analisi significa estrarre l’informazione dal parlato (analogico), ovvero riconoscere i fonemi e ricomporli per associarli a parole di una frase per poterla maneggiare come informazione di testo (digitale).

L’analisi vocale è basata sulla libreria Python speech_recognition che mette a disposizione una serie di API per l’analisi.

Sintesi vocale

La sintesi, viceversa, è la costruzione del segnale sonoro (analogico) del parlato a partire da una stringa di testo (digitale). Come assemblare gruppi di consonanti e di vocali per produrre i fonemi che compongono a loro volta le parole. La sintesi vocale è fornita dalla libreria pyttsx3.

pyttsx3 è una libreria di conversione “da testo a parlato” scritta in Python. A differenza di librerie alternative, può funzionare senza essere collegati a Internet ed è compatibile sia con Python 2 che con Python 3.

Prima di avventurarci su riconoscimento e sintesi vocale

Potreste anche direttamente andare nel sito di copyassignment.com se volete, ma qui posso risolvervi un paio di piccoli grattacapi dovuti alla mancanza di configurazione necessaria per eseguire questo programma.

Si tratta di farsi una minima idea del complesso di librerie che ci è nessario per passare al microfono al programma e dal programma agli altoparlanti.

Vi predigerisco già la pappa e vi illustro qual è lo stack su cui si basa il programma che in sostanza ci servirà per spegnere il computer:

sd.py  <----- il nostro programma
---------------------------------
speech_assignment / pyttsx3
---------------------------------
espeak                        (x)
---------------------------------
pyaudio
---------------------------------
PortAudio19                   (x)
---------------------------------
hardware (mike/speakers)
---------------------------------

L’ordine delle operazioni come ve lo presenta CopyAssignment.com è il seguente dove però non capiamo cosa stiamo facendo:

$ pip install pyaudio
$ pip install speechrecognition
$ pip install pyttsx3

Procedendo in quest’ordine però è molto probabile che vi troverete qualche gatta da pelare, come vediamo tra poco. Con (x) nello stack sopra ho contrassegnato le installazioni non citate da CopyAssignment.com

Installazione di pyaudio

marcob@jsbach:~$ pip install pyaudio

Se vi dovesse uscire questo errore

Building wheels for collected packages: pyaudio
   Building wheel for pyaudio (setup.py) 
   ERROR: Command errored out with exit status 1:
    ...

significa che non è installato l’header file portaudio.h, che è contenuto nel package portaudio19-dev. Dobbiamo pertanto installarlo preventivamente.

Installazione di PortAudio19 (x)

marcob@jsbach:~$ sudo apt-get install portaudio19-dev

PortAudio è una libreria per I/O audio portabile progettata per la gestione multipiattaforma dell’audio. Dell’audio in generale, intendiamo. non solo la voce umana.

È la libreria che permette di generare suoni e di leggere dalla periferica del microfono e convertire il segnale analogico in digitale. È la libreria a più basso livello di cui abbiamo bisogno.

Usa un meccanismo di callback per richiedere l’elaborazione audio. L’audio può essere generato in svariati formati, inclusa virgola mobile a 32 bit, e sarà convertito internamente nel formato nativo.

Riprovando a questo punto, a me è terminata con successo l’installazione di pyaudio; posso procedere con il package dell’analisi vocale.

Installazione di speech_recognition

arcob@jsbach:~$ pip install speechrecognition
Collecting speechrecognition
  Downloading SpeechRecognition-3.8.1-py2.py3-none-any.whl (32.8 MB)
     |████████████████████████████████| 32.8 MB 43 kB/s 
Installing collected packages: speechrecognition
Successfully installed speechrecognition-3.8.1

A questo punto si deve installare con pip il package Python che per la produzione del parlato

Installazione di pyttsx3

marcob@jsbach:~$ pip install pyttsx3
Collecting pyttsx3
  Downloading pyttsx3-2.90-py3-none-any.whl (39 kB)
Installing collected packages: pyttsx3
Successfully installed pyttsx3-2.90

Anche questo è andato bene. Questo è il sorgente del programma che potete trovare in CopyAssignment e che ho salvato in un file sd.py, modificando in italiano le stringhe di colloquio con il computer: lo posiamo avviare

# Importing required modules
# importing pyttsx3
import pyttsx3
# importing speech_recognition
import speech_recognition as sr
# importing os module
import os


# creating take_commands() function which
# can take some audio, Recognize and return
# if there are not any errors
def take_commands():
    # initializing speech_recognition
    r = sr.Recognizer()
    # opening physical microphone of computer
    with sr.Microphone() as source:
        print('Ascolto...')
        r.pause_threshold = 0.7
        # storing audio/sound to audio variable
        audio = r.listen(source)
        try:
            print("Riconoscimento")
            # Recognizing audio using google api
            Query = r.recognize_google(audio)
            print("Questo è ciò che ho capito='", Query, "'")
        except Exception as e:
            print(e)
            print("Prova a ripetere")
            # returning none if there are errors
            return "None"
    # returning audio as text
    import time
    time.sleep(2)
    return Query


# creating Speak() function to giving Speaking power
# to our voice assistant
def Speak(audio):
    # initializing pyttsx3 module
    engine = pyttsx3.init()
    voice_id = 'italian'
    engine.setProperty('voice', voice_id)
    # anything we pass inside engine.say(),
    # will be spoken by our voice assistant
    engine.say(audio)
    engine.runAndWait()

Speak("Vuoi spegnere il computer, Marco?")

while True:
    command = take_commands()
    if "no" in command:
        Speak("Ok Marco, lascio acceso")
        break
    if "yes" in command:
        # Shutting down
        Speak("Spengo")
        os.system("shutdown -h now")
        break
    Speak("Puoi ripetere? grazie")

Salvo il tutto in un file sd.py e provo ad eseguirlo

marcob@jsbach:~$ python3 sd.py
 OSError: libespeak.so.1: cannot open shared object file: No such file or directory

Questo è un problema che si situa ad un livello intermedio tra portaudio19 e Python (speech_assignment / pyttsx3): non risulta infatti installata nel sistema la libreria per il riconoscimento e la sintesi vocale che saranno invocate dalle librerie Python: espeak.

Installazione di espeak (x)

eSpeak è un sintetizzatore vocale software open source compatto per inglese e altre lingue, per Linux e Windows.
eSpeak utilizza un metodo di “sintesi formante”. Ossia costruisce i suoni in base ad un modello fisico dell’apparato fonatorio umano e utilizza la sovrapposizione di segnali sinusoidali, ovvero le serie di Fourier, per determinare il contenuto armonico del segnale.

Ciò consente di fornire molte lingue in dimensioni ridotte. Il parlato prodotto è chiaro e può essere utilizzato ad alta velocità, ma non è così naturale o fluido come sintetizzatori più grandi basati su registrazioni vocali umane. Ricorda un po’ i primi vocoder anni ’80. Se riprodotti su un impianto HiFi anche discreto, il suono risulta un po’ meno “cibernetico”.

marcob@jsbach:~$ sudo apt install espeak-ng-espeak
Lettura elenco dei pacchetti... Fatto
...
 Elaborazione dei trigger per doc-base (0.10.9)...
 Elaborazione 1 file doc-base aggiunto...
marcob@jsbach:~$

A questo punto manca solo il componente che collega python a espeak:

marcob@jsbach:~$ sudo apt install python3-espeak

A questo punto possiamo testare il programma.

Proprietà della libreria speech_recognition

Di questa libreria noi utilizzeremo in particolare la libreria Google di riconoscimento dei fonemi, il metodo recognize_google della classe Recognizer del package speech_recognition (sr).

L’unico parametro che viene impostato è

pause_threshold

ossia la soglia di silenzio che permette di separare le parole. Viene impostato a 0.7.

La variabile audio contiene un file mp3 che viene scritto dal metodo listen() della classe sr.Microhpone().

Alla fine il metodo magico che trasforma il suono (audio) ìn stringa (Query) è il seguente

Query = r.recognize_google(audio)

La classe è scritta bene, rende l’idea di cosa il programma stia facendo e con quali periferiche stia interagendo.

Proprietà della libreria pyttsx3

Questa componente trasforma la stringa in parlato ed è utilizzata per l’interfaccia human computer di interrogazione delle direttive dell’operatore. Ho selezionato il parlato in italiano (tra i molti disponibili):

voice_id = 'italian'
engine.setProperty('voice', voice_id)

e finalmente viene invocato il metodo che produce il suono:

engine.say(audio)
engine.runAndWait()

Se vi è piaciuto, mettete un like e/o ricondividetelo nel vostro social network preferito.

4 commenti

Vai al modulo dei commenti

    • Gianluca il 09/03/2021 alle 18:06
    • Rispondi

    Ciao Marco,
    Grazie per il tuo tutorial.. Molto molto interessante, complimenti. Io sono un novizio in Python e mi sto divertendo un po’ con il Raspberry pi4 utilizzando Thonny 3.7. Volevo porti qualche domandina e spero tu possa aiutarmi/chiarirmi le idee.
    Ho notato che :
    -una volta inserito un qualsiasi script di esempio di SpeechRecognition in un ciclo while.. Quest ultimo funziona correttamente per un po’.. Ma poi inizia a diventare molto molto lento.
    – se per qualche minuto nella stanza non vi è alcun suono e poi si prova a parlare.. Lo script sembra bloccato.. E si riprende dopo un bel po’.
    A te capita mai?

    Non capisco se è un problema di installazione con Pip.. O altro..

    Potresti gentilmente dirmi quale versione Python usi.. E quale Pip?
    Sul Raspberry Pi4 ci sono preinstallati Python2.7/3/ 3.7e tutte le volte non so mai quale usare per le mie attività..
    Pip …….2.7
    Pip3…. 3
    Pip3……3.7
    É corretta questa assegnazione?

    Grazie mille per aver dedicato del tempo per questa lettura.

    Buona giornata

    1. Ciao Gianluca!
      Mi fa molto piacere che ti sia piaciuto l’articolo.
      Non riesco a fare molte verifiche in questo preciso istante, ma quello che posso dirti subito è questo:
      marcob@jsbach:~$ pip -V
      pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)
      marcob@jsbach:~$ python3
      Python 3.8.5 (default, Jan 27 2021, 15:41:15)
      [GCC 9.3.0] on linux
      Type "help", "copyright", "credits" or "license" for more information.
      >>>

      Sto lavorando con un Ubuntu 20.04:

      marcob@jsbach:~$ uname -a
      Linux jsbach 5.4.0-66-generic #74-Ubuntu SMP Wed Jan 27 22:54:38 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

      Non ho fatto grosse valutazioni sul consumo di memoria, probabilmente gli script vanno ottimizzati da questo punto di vista.
      In fondo ho fatto questo piccolo esercizio solo per mera curiosità.
      Ma fammi sapere eventuali sviluppi che magari ci do un’occhiata più in profondità.

      Buona giornata!

  1. ciao Marco, sto cercando di studiare il tuo esempio, mi chiedevo, in quanto nuovo di python, e se vollessi passare un file audio allo script, come dovrei modificarlo? Puoi darmi qualche suggerimento? A me interessa la conversione da voce a testo…. Grazie mille!

    1. Salta la parte di riconoscimento dentro la funzione take_commands() e inizializza

      audio = open(‘audio.wav’,’r’)
      query = r.recognize_google(audio)

      ciao!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.