Aggiunta della traduzione del parlato alla tua app per Android

Questo tutorial mostra come fornire una funzionalità di traduzione vocale per la tua app Android. L'esempio in questo tutorial utilizza un microservizio che riceve un messaggio audio, traduce il messaggio in una serie di lingue predefinite e memorizza i messaggi tradotti in file audio. L'app client Android scarica e riproduce i file audio tradotti su richiesta dell'utente.

Panoramica delle soluzioni

La soluzione include i seguenti componenti:

Microservizio

Il microservizio è implementato in Cloud Functions for Firebase e utilizza i seguenti prodotti di AI Cloud per tradurre i messaggi:

Il microservizio archivia i messaggi audio tradotti in un bucket in Cloud Storage for Firebase.

App client

Il componente client è un'app Android che registra i messaggi audio e scarica i messaggi tradotti dal bucket Cloud Storage. L'esempio è un'app di chat utilizzata nel tutorial Creazione di un'app Android tramite Firebase e Ambiente flessibile di App Engine. Questo tutorial spiega come estendere l'app di esempio per implementare la funzionalità di traduzione vocale.

Il seguente diagramma mostra l'interazione tra il microservizio e l'applicazione client:

Architettura di alto livello della soluzione

Il microservizio esegue le seguenti attività:

  1. Riceve il messaggio audio nel formato con codifica Base64.
  2. Trascrive il messaggio audio utilizzando l'API Speech-to-Text.
  3. Traduce il messaggio trascritto utilizzando l'API Translation.
  4. Sintetizza il messaggio tradotto utilizzando l'API Text-to-Speech.
  5. Archivia il messaggio audio tradotto in un bucket Cloud Storage.
  6. Invia la risposta al client. La risposta include le impostazioni internazionali del messaggio audio tradotto.

Architettura di microservizi

L'app client esegue le seguenti attività:

  1. Registra il messaggio audio utilizzando le best practice dell'API Speech-to-Text per una maggiore precisione. L'app utilizza il microfono del dispositivo per intercettare l'audio.
  2. Codifica il messaggio audio in formato Base64.
  3. Invia una richiesta HTTP al microservizio che include il messaggio audio codificato.
  4. Riceve la risposta HTTP dal microservizio, che include le impostazioni internazionali del messaggio audio tradotto.
  5. Invia una richiesta al bucket Cloud Storage per recuperare il file che include il messaggio audio tradotto.
  6. Riproduce il messaggio audio tradotto.

Obiettivi

Questo tutorial illustra come:

  • Utilizza Cloud Functions for Firebase per creare un microservizio che incapsula la logica necessaria per tradurre i messaggi audio utilizzando i seguenti prodotti di AI Cloud:
    • API Speech-to-Text
    • API Translation
    • API Text-to-Speech
  • Utilizza le API Android Framework per registrare l'audio seguendo i consigli su come fornire dati audio all'API Speech-to-Text.
  • Usa la libreria di Cronet per caricare i dati vocali dall'app client al microservizio e scaricare i messaggi tradotti da Cloud Storage. Per ulteriori informazioni sulla libreria di Cronet, consulta la sezione Eseguire operazioni di rete con Cronet nella documentazione per gli sviluppatori Android.

Costi

Questo tutorial estende l'app di esempio implementata in Creare un'app Android utilizzando Firebase e l'ambiente flessibile di App Engine. Rivedi la sezione Costi nel tutorial menzionato e considera i seguenti costi aggiuntivi:

  • Firebase definisce le quote per l'utilizzo di Cloud Functions che specificano limiti relativi a risorse, tempi e frequenza. Per ulteriori informazioni, consulta Quote e limiti nella documentazione di Firebase.
  • I prezzi per l'utilizzo dell'API Speech-to-Text vengono calcolati mensilmente in base alla durata dell'audio elaborato correttamente. È previsto un tempo di elaborazione prestabilito che puoi utilizzare gratuitamente ogni mese. Per ulteriori informazioni, consulta la pagina Prezzi dell'API Speech-to-Text.
  • I prezzi per l'utilizzo dell'API Translation vengono calcolati mensilmente in base alla quantità di caratteri inviati all'API per l'elaborazione. Per ulteriori informazioni, consulta la pagina relativa ai prezzi dell'API Translation.
  • I prezzi per l'utilizzo dell'API Text-to-Speech vengono calcolati mensilmente in base alla quantità di caratteri da sintetizzare in audio. Esistono diversi caratteri che puoi utilizzare gratuitamente ogni mese. Per ulteriori informazioni, consulta la pagina Prezzi dell'API Text-to-Speech.
  • Le tariffe di utilizzo di Firebase Storage vengono elaborate come tariffe di Google Cloud Storage. Per ulteriori informazioni, consulta la pagina Prezzi di Cloud Storage.

Prima di iniziare

Completa il tutorial Creazione di un'app Android utilizzando Firebase e l'ambiente flessibile di App Engine e installa il seguente software:

Ottieni un dispositivo hardware con Android 7.0 (livello API 24) o versioni successive per testare la funzionalità di traduzione vocale.

Clonazione del codice campione

Utilizza il comando seguente per clonare il repository nodejs-docs-samples, che include il codice del microservizio:

git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

Abilitazione di fatturazione e API per il progetto Google Cloud

Questo tutorial utilizza il progetto Playchat creato in Crea un'app per Android utilizzando Firebase e l'ambiente flessibile di App Engine, che richiede le API Amministratore di App Engine e API Compute Engine.

Il microservizio richiede le seguenti API per elaborare le richieste di traduzione vocale:

  • API Text-to-Speech
  • API Cloud Translation
  • API Speech-to-Text

Per abilitare le API richieste:

  1. In Google Cloud Console, seleziona il progetto Playchat.

    Vai alla pagina Progetti

  2. Assicurati che la fatturazione sia attivata per il tuo progetto Cloud. Scopri come verificare se la fatturazione è abilitata su un progetto.

  3. Abilita le API App Engine, Speech-to-Text, Translation, and Text-to-Speech.

    Abilita le API

Configurazione del bucket predefinito su Cloud Storage for Firebase

Il microservizio utilizza il bucket Cloud Storage predefinito nel progetto Firebase per archiviare i file audio tradotti. Devi abilitare l'accesso in lettura agli account utente che vogliono recuperare i file audio.

Per abilitare l'accesso in lettura, è necessario l'UID utente Firebase dell'account. Per recuperare l'UID utente:

  1. Nel menu a sinistra della Console Firebase, seleziona Autenticazione nel gruppo Sviluppo.
  2. Prendi nota del valore UID utente dell'account utente che vuoi utilizzare per testare l'app. L'UID utente è una stringa di 28 caratteri.

Per abilitare l'accesso in lettura all'account utente, devi creare una regola di sicurezza dello spazio di archiviazione. Per creare una regola di sicurezza:

  1. Nel menu a sinistra della console di Firebase, seleziona Spazio di archiviazione nel gruppo Sviluppo.
  2. Prendi nota dell'URL predefinito del bucket, nel formato gs://[FIREBASE_PROJECT_ID].appspot.com e visualizzato accanto a un'icona link. Questo valore è necessario per eseguire il deployment del microservizio.
  3. Nella pagina Archiviazione, vai alla sezione Regole e aggiungi la seguente regola nella sezione service firebase.storage:

     match /b/{bucket}/o {
       match /{allPaths=**} {
         allow read: if request.auth.uid == "[ACCOUNT_USER_UID]";
       }
     }
    

    Sostituisci ACCOUNT_USER_UID con il valore UID utente ottenuto nei passaggi precedenti.

Per ulteriori informazioni, consulta la guida introduttiva alle regole di sicurezza dello spazio di archiviazione nella documentazione di Firebase.

Creazione e deployment del microservizio

Per creare il microservizio, apri una finestra terminale, quindi vai alla cartella functions/speech-to-speech/functions nel repository nodejs-docs-samples che hai clonato nella sezione precedente.

Il codice del microservizio include un file .nvmrc che dichiara la versione di Node.js che devi utilizzare per eseguire l'app. Esegui il comando seguente per configurare NVM e installare le dipendenze del microservizio:

nvm install && nvm use && npm install

Accedi a Firebase utilizzando l'interfaccia a riga di comando eseguendo questo comando:

firebase login

Il microservizio richiede le seguenti variabili di ambiente:

  • OUTPUT_BUCKET: il bucket Cloud Storage predefinito nel progetto Firebase.
  • SUPPORTED_LANGUAGE_CODES: un elenco separato da virgole di codici lingua supportati dal microservizio.

Utilizza i seguenti comandi per dichiarare i dati di ambiente richiesti nell'interfaccia a riga di comando. Sostituisci il segnaposto FIREBASE_PROJECT_ID con il valore indicato nella sezione precedente.

firebase functions:config:set playchat.output_bucket="gs://[FIREBASE_PROJECT_ID].appspot.com"
firebase functions:config:set playchat.supported_language_codes="en,es,fr"

Configurazione dell'app Android

L'app di esempio di Playchat richiede l'URL del microservizio per abilitare le funzionalità di traduzione vocale. Per recuperare l'URL del microservizio:

  1. Nel menu a sinistra della Console Firebase, seleziona Funzioni nel gruppo Sviluppo.
  2. L'URL del microservizio viene visualizzato nella colonna Trigger, che è nel formato https://[REGION_ID]-[FIREBASE_PROJECT_ID].cloudfunctions.net/[FUNCTION_NAME].

Per configurare l'applicazione in modo che funzioni con il microservizio, apri il file app/src/main/res/values/speech_translation.xml nel repository firebase-android-client e aggiorna il campo speechToSpeechEndpoint con l'URL del microservizio.

Con l'app Android

Per utilizzare la funzionalità di traduzione vocale nell'app, devi usare un dispositivo che supporti la registrazione audio utilizzando il microfono integrato, ad esempio un dispositivo hardware.

Per utilizzare la funzionalità di traduzione vocale nell'app:

  1. Assicurati che il dispositivo hardware utilizzi una delle lingue configurate nella sezione Creazione e deployment del microservizio. Per cambiare la lingua, apri l'app Impostazioni sul dispositivo e vai a Sistema > Lingue &input > Lingue.
  2. Apri il progetto Playchat in Android Studio e collega il dispositivo hardware al computer tramite un cavo USB. Per ulteriori informazioni, consulta la pagina Configurare un dispositivo per lo sviluppo.
  3. Fai clic su Esegui in Android Studio per creare ed eseguire l'app sul dispositivo.
  4. Tocca l'icona del microfono nell'app Playchat per iniziare a registrare, registrare un breve messaggio e toccare di nuovo l'icona del microfono per interrompere la registrazione.
  5. Dopo alcuni secondi, l'app Playchat visualizza sullo schermo il testo del messaggio registrato. Tocca il messaggio per riprodurre la versione audio.
  6. Configura il dispositivo in modo da utilizzare una lingua supportata diversa.
  7. L'app Playchat visualizza il messaggio registrato in precedenza nella nuova lingua supportata. Tocca il messaggio per riprodurre la versione audio nella nuova lingua.

Lo screenshot seguente mostra l'app Playchat che mostra un messaggio tradotto in francese:

Funzionalità di traduzione vocale in Android

Esplorazione del codice

L'app client esegue le attività seguenti per supportare la funzionalità di traduzione vocale:

  1. Registra l'audio utilizzando i parametri consigliati descritti nelle best practice dell'API Speech-to-Text.
  2. Codifica l'audio utilizzando lo schema Base64 per rappresentare l'audio in un formato stringa che può essere incorporato in una richiesta HTTP.
  3. Invia una richiesta HTTP al microservizio. La richiesta include il messaggio audio codificato insieme a metadati che forniscono informazioni aggiuntive sul payload. L'app utilizza la raccolta di contenuti per gestire le richieste di rete.
  4. Quando l'utente vuole ascoltare il messaggio tradotto, l'app scarica il file audio corrispondente inviando una richiesta HTTP autenticata al bucket Cloud Storage in cui sono archiviati i messaggi tradotti.

L'esempio di codice riportato di seguito mostra le costanti utilizzate dall'esempio per specificare i parametri di configurazione della registrazione:

private static final int AUDIO_SOURCE = MediaRecorder.AudioSource.UNPROCESSED;
private static final int SAMPLE_RATE_IN_HZ = 16000;
private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;
private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
  • AUDIO_SOURCE: MediaRecorder.AudioSource.UNPROCESSED indica una sorgente audio non elaborata, perché l'applicazione di algoritmi di elaborazione dei segnali come la riduzione del rumore o il controllo del guadagno riduce la precisione del riconoscimento.
  • SAMPLE_RATE_IN_HZ: il campione utilizza un valore 16,000 per la frequenza di campionamento nativa della sorgente audio.
  • CHANNEL_CONFIG: AudioFormat.CHANNEL_IN_MONO indica un solo canale audio nella registrazione. L'esempio presuppone che nella registrazione sia registrata una sola voce di persona.
  • AUDIO_FORMAT: AudioFormat.ENCODING_PCM_16BIT indica il formato dei dati audio PCM lineare utilizzando 16 bit per campione. Il formato lineare PCM è senza perdita, preferibilmente per il riconoscimento vocale.

L'app client utilizza l'API AudioRecord per registrare l'audio dal microfono integrato, archiviando un file .WAV sul dispositivo. Per maggiori informazioni, consulta la classe RecordingHelper dell'esempio di Playchat.

Per codificare l'audio utilizzando lo schema Base64, l'esempio utilizza la classe Base64 di Android Framework. L'audio codificato non deve includere terminali di linea, che vengono omessi utilizzando il flag NO_WRAP. L'esempio seguente mostra come codificare l'audio utilizzando la classe Base64:

public static String encode(File inputFile) throws IOException {
    byte[] data = new byte[(int) inputFile.length()];
    DataInputStream input = new DataInputStream(new FileInputStream(inputFile));
    int readBytes = input.read(data);
    Log.i(TAG, readBytes + " read from input file.");
    input.close();
    return Base64.encodeToString(data, Base64.NO_WRAP);
}

Per inviare l'audio codificato al microservizio, l'app client invia una richiesta HTTP con i seguenti parametri:

  • Metodo: POST
  • Tipo di contenuti: application/json
  • Corpo: oggetto JSON con i seguenti attributi:
    • encoding: la stringa LINEAR16
    • sampleRateHertz: la frequenza di campionamento dell'audio registrato. Ad esempio, 16000.
    • languageCode: il codice lingua del messaggio registrato. L'app client presuppone che il messaggio sia registrato nella lingua configurata nelle impostazioni del dispositivo. Ad esempio, en-US.
    • audioContent: il messaggio audio codificato nello schema Base64.

L'esempio seguente mostra come creare un oggetto JSON che includa gli attributi obbligatori nel corpo della richiesta:

JSONObject requestBody = new JSONObject();
try {
    requestBody.put("encoding", SPEECH_TRANSLATE_ENCODING);
    requestBody.put("sampleRateHertz", sampleRateInHertz);
    requestBody.put("languageCode", context.getResources().getConfiguration().getLocales().get(0));
    requestBody.put("audioContent", base64EncodedAudioMessage);
} catch(JSONException e) {
    Log.e(TAG, e.getLocalizedMessage());
    translationListener.onTranslationFailed(e);
}

Per maggiori dettagli su come creare la richiesta HTTP, consulta la classe SpeechTranslationHelper dell'app Playchat di esempio.

Per recuperare i file audio dal bucket Cloud Storage, l'app utilizza un URL di download che include un token che può essere revocato dalla Console Firebase, se necessario. Puoi recuperare l'URL di download chiamando il metodo getDownloadUrl(), come mostrato nell'esempio seguente:

FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference gsReference = storage.getReferenceFromUrl(gcsUrl);
gsReference.getDownloadUrl().addOnCompleteListener(getDownloadUriListener);

Il microservizio esegue la seguente attività per supportare la funzionalità di traduzione vocale:

  1. Riceve richieste di traduzione vocale che includono l'audio codificato in Base64.
  2. Invia l'audio codificato all'API Speech-to-Text e riceve una trascrizione nella lingua di origine.
  3. Per ogni lingua supportata, invia la trascrizione all'API Translation e riceve il testo tradotto.
  4. Per ogni lingua supportata, invia il testo tradotto all'API Text-to-Speech e riceve l'audio tradotto.
  5. Carica i file audio tradotti nel bucket Cloud Storage.

Il microservizio utilizza l'output di una chiamata a un'API Cloud come input della chiamata all'API successiva, come mostrato nell'esempio di codice seguente:

const [sttResponse] = await callSpeechToText(
  inputAudioContent,
  inputEncoding,
  inputSampleRateHertz,
  inputLanguageCode
);

// The data object contains one or more recognition
// alternatives ordered by accuracy.
const transcription = sttResponse.results
  .map(result => result.alternatives[0].transcript)
  .join('\n');
responseBody.transcription = transcription;
responseBody.gcsBucket = outputBucket;

const translations = [];
supportedLanguageCodes.forEach(async languageCode => {
  const translation = {languageCode: languageCode};
  const outputFilename =
    request.body.outputFilename ||
    `${uuid.v4()}.${outputAudioEncoding.toLowerCase()}`;

  try {
    const [textTranslation] = await callTextTranslation(
      languageCode,
      transcription
    );
    translation.text = textTranslation;

    const [{audioContent}] = await callTextToSpeech(
      languageCode,
      textTranslation
    );
    const path = `${languageCode}/${outputFilename}`;

    console.log('zzx', audioContent);

    await uploadToCloudStorage(path, audioContent);

    console.log(`Successfully translated input to ${languageCode}.`);
    translation.gcsPath = path;
    translations.push(translation);
    if (translations.length === supportedLanguageCodes.length) {
      responseBody.translations = translations;
      console.log(`Response: ${JSON.stringify(responseBody)}`);
      response.status(200).send(responseBody);
    }
  } catch (error) {
    console.error(
      `Partial error in translation to ${languageCode}: ${error}`
    );
    translation.error = error.message;
    translations.push(translation);
    if (translations.length === supportedLanguageCodes.length) {
      responseBody.translations = translations;
      console.log(`Response: ${JSON.stringify(responseBody)}`);
      response.status(200).send(responseBody);
    }
  }
});

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial:

Elimina il progetto Google Cloud e Firebase

Il modo più semplice per interrompere gli addebiti è eliminare il progetto che hai creato per questo tutorial. Anche se hai creato il progetto nella Console Firebase, puoi eliminarlo anche in Google Cloud Console, poiché i progetti Firebase e Google Cloud sono gli stessi.

  1. In Cloud Console, vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona il progetto da eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.

Elimina le versioni non predefinite della tua app App Engine

Se non vuoi eliminare il progetto Google Cloud e Firebase, puoi ridurre i costi eliminando le versioni non predefinite della tua app per l'ambiente flessibile App Engine.

  1. In Cloud Console, vai alla pagina Versioni di App Engine.

    Vai a Versioni

  2. Seleziona la casella di controllo relativa alla versione predefinita dell'app da eliminare.
  3. Per eliminare la versione dell'app, fai clic su Elimina.