Come implementare comandi vocali in un bot Telegram

In questo articolo vedremo come implementare un semplice sistema per impartire comandi vocali al nostro bot Telegram.

In particolare utilizzeremo un servizio gratuito di Speech-To-Text che analizza la nostra voce e la traduce in testo.

Potremmo quindi fare in modo che il nostro bot acquisisca i nostri vocali, li traduca in comandi e risponda opportunamente.

Come servizio di Speech-To-Text utilizzeremo le api di AssemblyAI (https://www.assemblyai.com/) che offrono un servizio gratuito di trascrizione limitato a 3 ore per mese con un massimo di 5 richieste concorrenti.

Le api di trascrizione di AssemblyAI includono una serie di parametri molto interessante, tra cui un vocabolario personalizzato, la mappatura di parole, la rilevazione automatica della lingua, solo per citarne alcune.

Procediamo con l’implementazione. Utilizzeremo le librerie NodeJS Telegraf per la gestione del ciclo di vita del bot e Axios per gestire le richieste alle api e le relative risposte.

Il servizio di trascrizione che utilizzeremo è asincrono. Peranto dovremmo inviare il nostro vocale, recuperare l’id del processo e poi effettuare un polling sino a che il processo di elaborazione non sia completato, prima di recuperare la trascrizione del nostro comando.

Il codice minimale per implementare quanto detto è il seguente

const { Telegraf } = require('telegraf')
const axios = require('axios')

const bot = new Telegraf(<TOKEN>)
const S2T_API_ENDPOINT = 'https://api.assemblyai.com/v2'
const S2T_API_KEY = <S2T_API_KEY>

bot.command('start', (ctx) => {
    ctx.reply(`Benvenuto nel mio bot!
    Mandami un vocale e risponderò ai tuoi comandi`)
});

bot.on('voice', async (ctx) => {
    const voiceMessage = ctx.message.voice;
    const fileId = voiceMessage.file_id;
    const fileLink = await ctx.telegram.getFileLink(fileId);
    const assembly = axios.create({
        baseURL: S2T_API_ENDPOINT,
        headers: {
            "Authorization": S2T_API_KEY,
            "Content-Type": "application/json"
        },
    });
    try {
        const response = await assembly.post("/transcript", {
            "audio_url": fileLink.href,
            "language_code": "it"
        });
        let transcriptionId = response.data.id;
        let status = "start"
        let completedResponse = null
        let i = 0
        while (i < 10 && status != "completed" && status != "error") {
            i = i + 1
            completedResponse = await assembly.get(`/transcript/${transcriptionId}`)
            status = completedResponse.data.status;
            await sleep(3000)
        }
        let command = completedResponse.data.text;
        if (command == null) {
            const message = "Riprova, comando non riconosciuto"
            ctx.reply(message);
        } else {
            const message = manageCommand(command) //inserisci in questa funzione la logica del comando
            ctx.reply(message)
        }
    } catch (error) {
        console.error(error);
        ctx.reply("errore nella trascrizione");
    }
});

bot.launch();

const sleep = function (millis) {
    return new Promise(resolve => setTimeout(resolve, millis));
}

Il cuore dell’implementazione risiede nell’handler bot.on(‘voice’, async (ctx) => { … })

che richiama il blocco di codice … alla ricezione di un messaggio vocale.

In particolare, quando un utente invia un messaggio vocale, il bot utilizza l’API di Telegram per recuperare il link del file audio fileLink.href e quindi invia questo link all’API di AssemblyAI per la trascrizione, utilizzando axios. Una volta ricevuta la trascrizione, il bot esegue una logica di comando specifica che viene implementata in una funzione denominata manageCommand. Se la trascrizione non riesce a decodificare il vocale, allora il bot restituisce un messaggio.

La funzione sleep viene utilizzata per aggiungere un ritardo durante il polling dello stato di trascrizione dell’audio dal servizio di AssemblyAI. Fintanto che lo stato non è “completed” o “error”, il ciclo while procede sino a raggiungere un numero massimo di 10 tentativi per evitare che la risposta del bot vada in timeout.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *