Search code examples
javaibm-watsonspeech-to-textanonymous-class

Accessing variables outside of anonymous class


I am currently working with IBM's Speech to Text services included in the IBM Watson java SDK. I am trying to set the transcript String to be equal to the results' transcript. However, when I run this code the value is not printed. I am unsure why this is happening, or how to resolve the issue. Any help would be appreciated. I have tried using an external setter with a static variable outside the main method, but I was unsuccessful.

final String[] transcript = {""};
    service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
        @Override
        public void onTranscription(SpeechRecognitionResults speechResults) {
            for(int i = 0; i < speechResults.getResults().size(); i++){
                transcript[0] = transcript[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
            }
        }
    });
    System.out.println(transcript[0]);

Solution

  • You could wrap your array transcript in a class that has its own handler or consumer ( a way to deal with async requests).

    Like so:

    import java.util.function.Consumer;
    
    public class ArrayWrapper {
    
        private Consumer consumer;
    
        private Object [] array;
    
        public ArrayWrapper(int size) {
            this.array = new Object [size];
        }
    
        public void addConsumer(Consumer consumer) {
            this.consumer = consumer;
        }
    
        public void add(Object o, int index) {
            array[index] = o;
            consumer.accept(o);
        }
    
        public Object [] get() {
            return array;
        }
    }
    

    Then you can just implement your logic inside Consumer:

    ArrayWrapper transcript = new ArrayWrapper(1);
    transcript.addConsumer(new Consumer() {
        @Override
        public void accept(Object o) {
            // perform your operations 
            System.out.println(o);
        }
    });
    
    service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
        @Override
        public void onTranscription(SpeechRecognitionResults speechResults) {
            for(int i = 0; i < speechResults.getResults().size(); i++){
                String newTranscript = transcript.get()[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
                transcript.add(newTranscript, 0);
            }
        }
    });
    

    This is just an example, but the idea is that you either have to use a function inside callback, some signal to tell you when loop is done inside callback or something similar.

    Edit:

    Or you can do this in a simpler way (without any additional classes):

        final String[] transcript = {""};
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                //your operations
                System.out.println(s);
            }
        };
        service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
            @Override
            public void onTranscription(SpeechRecognitionResults speechResults) {
                for(int i = 0; i < speechResults.getResults().size(); i++){
                    transcript[0] = transcript[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
                    consumer.accept(transcript[0]);
                }
            }
        });
    }