DEV Community

Cover image for Cómo un desarrollador programó una app de lectura de textos para su abuelo de 80 años
HuaweiDevsLATAM
HuaweiDevsLATAM

Posted on

Cómo un desarrollador programó una app de lectura de textos para su abuelo de 80 años

John, ¿has visto mis lentes?

Nuestro viejo amigo John, programador de Huawei, tiene un abuelo que a pesar de su vejez, es un ávido lector. Se inclinaba hacia atrás, luchando para entender lo que estaba escrito en el periódico a través de sus gafas, pero incapaz de quitar sus ojos del texto - así era como mi abuelo solía leer, explicó John.

Leer de esta manera perjudicó la visión de su abuelo, y se le ocurrió a John que los oídos podían asumir el papel de "lectura" de los ojos. Pronto desarrolló una aplicación de lectura de texto que seguía esta lógica, reconociendo y luego leyendo texto de una imagen. Gracias a esta aplicación, el abuelo de John ahora puede "leer" desde la comodidad de su mecedora, sin tener que tensar sus ojos.

Cómo implementarlo

  1. El usuario toma una foto de un pasaje de texto.La aplicación identifica automáticamente la ubicación del texto dentro de la imagen, y ajusta el ángulo de tiro a un ángulo que está frente directamente al texto.

  2. La aplicación reconoce y extrae el texto de la imagen.

  3. La aplicación convierte el texto reconocido en salida de audio aprovechando la tecnología de texto a voz.
    Estas funciones son fáciles de implementar cuando se basa en tres servicios en el Kit ML de HUAWEI: corrección de desvío de documentos, reconocimiento de texto y texto a voz (TTS).

Preparativos

Configura el repositorio Maven de Huawei

buildscript {
    repositories {
        google()
        jcenter()
        maven {url 'https://developer.huawei.com/repo/'}
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.1"
        classpath 'com.huawei.agconnect:agcp:1.4.2.300'
        // NOTE: Do not place your app dependencies here; they belong
        // in the individual module build.gradle files.
    }
}
allprojects {
    repositories {
        google()
        jcenter()
        maven {url 'https://developer.huawei.com/repo/'}
    }
}

Enter fullscreen mode Exit fullscreen mode

Agrega las dependencias de compilación del SDK de HMS Core

dependencies {

    // Import the base SDK.
    implementation 'com.huawei.hms:ml-computer-voice-tts:2.1.0.300'
    // Import the bee voice package.
    implementation 'com.huawei.hms:ml-computer-voice-tts-model-bee:2.1.0.300'
    // Import the eagle voice package.
    implementation 'com.huawei.hms:ml-computer-voice-tts-model-eagle:2.1.0.300'
    // Import a PDF file analyzer.
    implementation 'com.itextpdf:itextg:5.5.10'
}

Enter fullscreen mode Exit fullscreen mode

Pulsa Anterior o SIguiente para pasar a la página anterior o siguiente. Pulsa hablar para empezar a leer; toca de nuevo para pausar la lectura.

Proceso de desarrollo

1) Crea un motor de TTS utilizando la clase de configuración personalizada MLTtsConfig. Aquí, el TTS en el dispositivo se utiliza como ejemplo.

private void initTts() {
    // Set authentication information for your app to download the model package from the server of Huawei.
    MLApplication.getInstance().setApiKey(AGConnectServicesConfig.
            fromContext(getApplicationContext()).getString("client/api_key"));
    // Create a TTS engine by using MLTtsConfig.
    mlTtsConfigs = new MLTtsConfig()
            // Set the text converted from speech to English.
            .setLanguage(MLTtsConstants.TTS_EN_US)
            // Set the speaker with the English male voice (eagle).
            .setPerson(MLTtsConstants.TTS_SPEAKER_OFFLINE_EN_US_MALE_EAGLE)
            // Set the speech speed whose range is (0, 5.0]. 1.0 indicates a normal speed.
            .setSpeed(.8f)
            // Set the volume whose range is (0, 2). 1.0 indicates a normal volume.
            .setVolume(1.0f)
            // Set the TTS mode to on-device.
            .setSynthesizeMode(MLTtsConstants.TTS_OFFLINE_MODE);
    mlTtsEngine = new MLTtsEngine(mlTtsConfigs);
    // Update the configuration when the engine is running.
    mlTtsEngine.updateConfig(mlTtsConfigs);
    // Pass the TTS callback function to the TTS engine to perform TTS.
    mlTtsEngine.setTtsCallback(callback);
    // Create an on-device TTS model manager.
    manager = MLLocalModelManager.getInstance();
    isPlay = false;
}
Enter fullscreen mode Exit fullscreen mode

2) Crea un TTS Callback para procesar el resultado de TTS.

MLTtsCallback callback = new MLTtsCallback() {
    @Override
    public void onError(String taskId, MLTtsError err) {
        // Processing logic for TTS failure.
    }
    @Override
    public void onWarn(String taskId, MLTtsWarn warn) {
        // Alarm handling without affecting service logic.
    }
    @Override
    // Return the mapping between the currently played segment and text. start: start position of the audio segment in the input text; end (excluded): end position of the audio segment in the input text.
    public void onRangeStart(String taskId, int start, int end) {
        // Process the mapping between the currently played segment and text.
    }
    @Override
    // taskId: ID of a TTS task corresponding to the audio.
    // audioFragment: audio data.
    // offset: offset of the audio segment to be transmitted in the queue. One TTS task corresponds to a TTS queue.
    // range: text area where the audio segment to be transmitted is located; range.first (included): start position; range.second (excluded): end position.
    public void onAudioAvailable(String taskId, MLTtsAudioFragment audioFragment, int offset,
                                 Pair<Integer, Integer> range, Bundle bundle) {
        // Audio stream callback API, which is used to return the synthesized audio data to the app.
    }
    @Override
    public void onEvent(String taskId, int eventId, Bundle bundle) {
        // Callback method of a TTS event. eventId indicates the event name.
        boolean isInterrupted;
        switch (eventId) {
            case MLTtsConstants.EVENT_PLAY_START:
                // Called when playback starts.
                break;
            case MLTtsConstants.EVENT_PLAY_STOP:
                // Called when playback stops.
                isInterrupted = bundle.getBoolean(MLTtsConstants.EVENT_PLAY_STOP_INTERRUPTED);
                break;
            case MLTtsConstants.EVENT_PLAY_RESUME:
                // Called when playback resumes.
                break;
            case MLTtsConstants.EVENT_PLAY_PAUSE:
                // Called when playback pauses.
                break;
            // Pay attention to the following callback events when you focus on only the synthesized audio data but do not use the internal player for playback.
            case MLTtsConstants.EVENT_SYNTHESIS_START:
                // Called when TTS starts.
                break;
            case MLTtsConstants.EVENT_SYNTHESIS_END:
                // Called when TTS ends.
                break;
            case MLTtsConstants.EVENT_SYNTHESIS_COMPLETE:
                // TTS is complete. All synthesized audio streams are passed to the app.
                isInterrupted = bundle.getBoolean(MLTtsConstants.EVENT_SYNTHESIS_INTERRUPTED);
                break;
            default:
                break;
        }
    }
};
Enter fullscreen mode Exit fullscreen mode

3) Extrae el texto de un PDF

private String loadText(String path) {
    String result = "";
    try {
        PdfReader reader = new PdfReader(path);
        result = result.concat(PdfTextExtractor.getTextFromPage(reader,
                mCurrentPage.getIndex() + 1).trim() + System.lineSeparator());
        reader.close();
    } catch (IOException e) {
        showToast(e.getMessage());
    }
    // Obtain the position of the header.
    int header = result.indexOf(System.lineSeparator());
    // Obtain the position of the footer.
    int footer = result.lastIndexOf(System.lineSeparator());
    if (footer != 0){
        // Do not display the text in the header and footer.
        return result.substring(header, footer - 5);
    }else {
        return result;
    }
}

Enter fullscreen mode Exit fullscreen mode

4) Invoca TTS de lado del dispositivo

// Create an MLTtsLocalModel instance to set the speaker so that the language model corresponding to the speaker can be downloaded through the model manager.
MLTtsLocalModel model = new MLTtsLocalModel.Factory(MLTtsConstants.TTS_SPEAKER_OFFLINE_EN_US_MALE_EAGLE).create();
manager.isModelExist(model).addOnSuccessListener(new OnSuccessListener<Boolean>() {
    @Override
    public void onSuccess(Boolean aBoolean) {
        // If the model is not downloaded, call the download API. Otherwise, call the TTS API of the on-device engine.
        if (aBoolean) {
            String source = loadText(mPdfPath);
            // Call the speak API to perform TTS. source indicates the text to be synthesized.
            mlTtsEngine.speak(source, MLTtsEngine.QUEUE_APPEND);
            if (isPlay){
                // Pause playback.
                mlTtsEngine.pause();
                tv_speak.setText("speak");
            }else {
                // Resume playback.
                mlTtsEngine.resume();
                tv_speak.setText("pause");
            }
            isPlay = !isPlay;
        } else {
            // Call the API for downloading the on-device TTS model.
            downloadModel(MLTtsConstants.TTS_SPEAKER_OFFLINE_EN_US_MALE_EAGLE);
            showToast("The offline model has not been downloaded!");
        }
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(Exception e) {
        showToast(e.getMessage());
    }
});
Enter fullscreen mode Exit fullscreen mode

5) Libera los recursos al destruir la interfáz de usuario

@Override
protected void onDestroy() {
    super.onDestroy();
    try {
        if (mParcelFileDescriptor != null) {
            mParcelFileDescriptor.close();
        }
        if (mCurrentPage != null) {
            mCurrentPage.close();
        }
        if (mPdfRenderer != null) {
            mPdfRenderer.close();
        }
        if (mlTtsEngine != null){
            mlTtsEngine.shutdown();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Enter fullscreen mode Exit fullscreen mode

Otros Escenarios de aplicación

TTS puede utilizarse en una amplia gama de escenarios.Por ejemplo, podrías integrarlo en una aplicación de educación para leer cuentos para dormir a los niños, o integrarlo en una aplicación de navegación, que podría leer instrucciones en voz alta.

Top comments (0)