63

As stated in this answer by Iftah I can get the audio recorded by the Speech Recoginition in android by getting the Uri from the Intent passed to:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // the recording url is in getData:
    Uri audioUri = data.getData();
}

Here the Intent data has exactly what I want without problems.

That all works perfectly, however that solution puts up a prompt for the user of when to speak, I did not want that so to get around that I let my activity implement RecognitionListener as so:

public class MainActivity extends AppCompatActivity implements RecognitionListener {

    private SpeechRecognizer speech = null;
    private Intent recognizerIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "sv_SE");
        recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "sv_SE");
        recognizerIntent.putExtra("android.speech.extra.GET_AUDIO_FORMAT", "audio/AMR");
        recognizerIntent.putExtra("android.speech.extra.GET_AUDIO", true);

        speech = SpeechRecognizer.createSpeechRecognizer(this);
        speech.setRecognitionListener(this);
        speech.startListening(recognizerIntent);
    }

    @Override
    public void onReadyForSpeech(Bundle params) {
        Log.d("Debug", "On ready for speech");
    }

    @Override
    public void onBeginningOfSpeech() {
        Log.d("Debug", "On beggining of speech");
    }

    @Override
    public void onRmsChanged(float rmsdB) {
        Log.d("Debug", "Rsm changed");
    }

    @Override
    public void onBufferReceived(byte[] buffer) {
        Log.d("Debug", "Buffer recieved");
    }

    @Override
    public void onEndOfSpeech() {
        Log.d("Debug", "On end of speech");
    }

    @Override
    public void onError(int error) {
        Log.d("Debug", "Error");
    }

    @Override
    public void onPartialResults(Bundle partialResults) {
        Log.d("Debug", "On partial result");
    }

    @Override
    public void onEvent(int eventType, Bundle params) {
        Log.d("Debug", "On event");
    }

    @Override
    public void onResults(Bundle results) {
        Log.d("Debug", "On result");
    }
}

This gets around the prompt hovewer I can not figure out how to get the Uri like in the first example because here:

@Override
    public void onResults(Bundle results) {
        Log.d("Debug", "On result");
        // The results bundle don't contain the URI!
    }

I get a Bundle results which don't contain the Intent or the Uri. I have tried looking at all the keys in the bundle and no URI or Intent exists, I have also tried getIntent() but that don't return anything.

I appreciate any help or push in the right direction.

Attaullah
  • 3,856
  • 3
  • 48
  • 63
Fredrik
  • 1,389
  • 1
  • 14
  • 32
  • 1
    What is your main purpose of getting Uri? – support_ms Feb 17 '16 at 12:36
  • I use it to retrieve the audio from the Speech Recognition, I know it's a hassle but it's the only way as today to actually get the audio. And I can get the URI as in the first example, it's just when I implement the RecognitionListener myself I just can't seem to get ahold of it. – Fredrik Feb 17 '16 at 12:38
  • I looked at documentation and there are some more callbacks which gives voice buffers as onBufferReceived (byte[] buffer) – support_ms Feb 17 '16 at 12:41
  • No it don't, if you read the documentation about onBufferReceived (byte[] buffer) it says that there is no guarante it will be called, which is the case. It is not called. I appreciate the help though. – Fredrik Feb 17 '16 at 12:43
  • Then I suggest to use AudioRecord class – support_ms Feb 17 '16 at 14:21
  • @support_ms You can't use that with the SpeechRecognition. The speech api do not accept a file/byteArray, it ONLY accepts to get it inputs from the mic and you can't record and use the speech at the same time. The method I am using is the only way to get the audio. – Fredrik Feb 17 '16 at 14:29
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/103741/discussion-between-support-ms-and-fredrik-rosenqvist). – support_ms Feb 17 '16 at 14:31
  • Update on these comments, it didn't solve anything, still same problem. Need the URI from the Intent. – Fredrik Feb 19 '16 at 07:40
  • http://stackoverflow.com/questions/19274880/voice-recognition-fails-to-work-when-the-voice-is-under-recording some other options for process reconizer and persist the recording – Robert Rowntree Feb 21 '16 at 18:45
  • The problem here is that we're relying on something that is not available by default on Android. Most of the time the recognizer being used is the `GoogleRecognitionService` but it is not open source. Also, there is no guarantee that it will be available on all devices or that the `Service` your app connects to will provide what you need. If you must get the audio without showing any dialog, maybe you can look into an open source speech recognizer that you can ship with your app such as [this one](http://kaljurand.github.io/K6nele/). – Ricardo Feb 21 '16 at 19:19
  • @Ricardo Lage Thank you for your input. This app is targeted for a specific device where GoogleRecognitionService is being used. So I know that the URI is present and will be present on the device this app is gonna be used on. So my problem still exists where I need that URI(Which I know exists because I can get it when the prompt is up). – Fredrik Feb 22 '16 at 08:03
  • @RobertRowntree Thank you for you input, I have tried that, but as the SpeechRecognition don't accept input in byte array or any other form than getting it directly from the microphone, that solution is not possible aswell. – Fredrik Feb 22 '16 at 08:05
  • @RicardoLage Regarding the open soruce alternative. I need the speech recognition in swedish which is very scarce with open soruce alternatives. – Fredrik Feb 22 '16 at 08:09
  • @FredrikRosenqvist if you have a rooted device, you can use the "prompt" version to find out where in the device the audio is saved. Then check that folder with the listener method to see if it's saved there as well. You can then try to manually access that folder from your app. – Ricardo Feb 22 '16 at 09:24
  • @RicardoLage unfortuanly the device will not be rooted :/ – Fredrik Feb 22 '16 at 09:46
  • @FredrikRosenqvist Did you try to see if the file does get saved with the listener, at least? Maybe it doesn't and then you are out of options anyway. – Ricardo Feb 22 '16 at 09:58
  • Yes I did check, and even if there was a file I would not have permission to read it. – Fredrik Feb 22 '16 at 12:33
  • @FredrikRosenqvist Depends on where the file is stored. If it is in a public folder, you could create an URI for it and access it like you want. But if you checked and there is no file there, then you are out of options anyway. – Ricardo Feb 22 '16 at 16:58
  • Do you have an example of the URL the working version returned? – Nick Cardoso Feb 23 '16 at 15:57
  • as per my understanding the bundle will have the array list of strings which corresponds to your speech data. Also, u need to read CONFIDENCE_SCORES from the bundle and map it with your speech data. Both confidence and speech array size should be same. – siva Feb 25 '16 at 07:38
  • @7383 I have no problem extracting the data from the bundle. It's just that the URI is missing. – Fredrik Feb 25 '16 at 07:48
  • what do you get in `onEndOfSpeech()` or perhaps in all overriding methods? – Kishor Pawar Feb 25 '16 at 13:17
  • @KishorPawar `onEndOfSpeech()`don't have any parameters so I don't get any data. The other overrides don't contain anything of interest. – Fredrik Feb 25 '16 at 13:38
  • why be so tied down to one particular intrface ( the speech recognizer intent & responseObj)? Widen the scope of possible solutions & you can do anything u want.... https://www.google.com/intl/en/chrome/demos/speech.html is built on chromium src and allows your 'extension' to process the 'stream' underlying the microphone , split it, one copy to ANY recognition service api ( IBM, Googl, dragon, .... ) and one copy to an encoder/ filesink of your choice. any codec you want (OPUS , FLAC, AMR). if u have to do it with the recognizer, try reaching out to @kaarel who is great on this – Robert Rowntree Feb 25 '16 at 16:55
  • http://stackoverflow.com/questions/23047433/record-save-audio-from-voice-recognition-intent/ this should be relevant – Robert Rowntree Feb 25 '16 at 17:01
  • @RobertRowntree I would love to use the google api if it was open to use but it's not. If you have any offical documentation on how to use it please give me a link becasue I have not found any. I'm so locked up right now because the speech api has to accept swedish, which this one does. – Fredrik Feb 25 '16 at 17:01
  • 1
    @FredrikRosenqvist I haven't tried and I don't have android set up to try.. But why don't you start intent with thisa`ACTION_VOICE_SEARCH_HANDS_FREE` action? as the api clearly suggests `Starts an activity that will prompt the user for speech without requiring the user's visual attention or touch input.`, source : http://developer.android.com/reference/android/speech/RecognizerIntent.html#ACTION_RECOGNIZE_SPEECH – Pragnani Feb 28 '16 at 18:05
  • @FredrikRosenqvist does my clomment help ? – Pragnani Mar 09 '16 at 19:27
  • Still puts up a prompt so no – Fredrik Mar 09 '16 at 19:36
  • [Here](https://stackoverflow.com/a/24404235/5429330) is a similar post. They are using an `startActivityForResult()` instead `startListening()` to get the data. Also they comment that the audio file has low quality. Hope this help. – Angel Guevara Jul 15 '16 at 17:42
  • @Fredrik were you able to get audio uri, i am also in same probelm nowadays as you were in 5 years before buddy. I tried many ways. nothing works here. – Anshul1507 Nov 11 '21 at 12:58
  • @Anshul1507 no I don't think I ever solved this actually :/ sorry. – Fredrik Nov 11 '21 at 13:04
  • @Fredrik i wanna small discussion with you, Can you please connect with me on twitter https://twitter.com/thenoobydev – Anshul1507 Nov 11 '21 at 13:27
  • @Anshul1507 I don't think I can help you. I haven't touched any android development 2016.. – Fredrik Nov 11 '21 at 14:15

1 Answers1

1

The results should be in the bundle with the key SpeechRecognizer.RESULTS_RECOGNITION.

@Override
public void onResults(Bundle results) {
    if (results != null && results.containsKey(SpeechRecognizer.RESULTS_RECOGNITION)) {
      List<String> resultsList = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
      // most likely result is resultsList.get(0)
    } else {
      // no results
    }

}

See the Android developer documentation for SpeechRecognizer explains it in detail. This method for getting speech recognition results also works for partial results in #onPartialResults

ajankenm
  • 110
  • 6
  • 1
    this should be the accepted anwser, see [online documentation](https://developer.android.com/reference/android/speech/SpeechRecognizer.html#RESULTS_RECOGNITION) – Piotr Z Jan 10 '18 at 00:28
  • 4
    No when I asked this question I was after the actual audio of the speech recognition, that was the problem and I don’t see how this solves that. – Fredrik Jan 10 '18 at 16:30
  • And this was some time ago now, I don’t really have the enviorment or code setup to test this. But if someone can confirm that this actually gets the audio and the result of the speech recognition without an user prompt, then I will mark it as the accepted answer. – Fredrik Jan 10 '18 at 16:37