Я пытаюсь создать приложение, которое может захватывать и транслировать микрофонный ввод речи в текст с исходящего звонка на Android.
У меня уже есть код для захвата аудиопотока в API.Все, что мне сейчас нужно, - это код для захвата звука вызова одновременно с передачей его на интерфейс API.
package com.ibm.watson.developer_cloud.android.myapplication;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import com.ibm.watson.developer_cloud.android.library.audio.MicrophoneHelper;
import com.ibm.watson.developer_cloud.android.library.audio.MicrophoneInputStream;
import com.ibm.watson.developer_cloud.android.library.audio.StreamPlayer;
import com.ibm.watson.developer_cloud.android.library.audio.utils.ContentType;
import com.ibm.watson.developer_cloud.android.library.camera.CameraHelper;
import com.ibm.watson.developer_cloud.android.library.camera.GalleryHelper;
import com.ibm.watson.developer_cloud.language_translator.v3.LanguageTranslator;
import com.ibm.watson.developer_cloud.language_translator.v3.model.TranslateOptions;
import com.ibm.watson.developer_cloud.language_translator.v3.model.TranslationResult;
import com.ibm.watson.developer_cloud.language_translator.v3.util.Language;
import com.ibm.watson.developer_cloud.service.security.IamOptions;
import com.ibm.watson.developer_cloud.speech_to_text.v1.SpeechToText;
import com.ibm.watson.developer_cloud.speech_to_text.v1.model.RecognizeOptions;
import com.ibm.watson.developer_cloud.speech_to_text.v1.model.SpeechRecognitionResults;
import com.ibm.watson.developer_cloud.speech_to_text.v1.websocket.BaseRecognizeCallback;
import com.ibm.watson.developer_cloud.text_to_speech.v1.TextToSpeech;
import com.ibm.watson.developer_cloud.text_to_speech.v1.model.SynthesizeOptions;
import java.io.IOException;
import java.io.InputStream;
/*
* Copyright 2017 IBM Corp. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
public class MainMenu extends AppCompatActivity {
private final String TAG = "MainMenu";
private EditText input;
private ImageButton mic;
private Button translate;
private ImageButton play;
private TextView translatedText;
private ImageView loadedImage;
private SpeechToText speechService;
private TextToSpeech textService;
private LanguageTranslator translationService;
private String selectedTargetLanguage = Language.SPANISH;
private StreamPlayer player = new StreamPlayer();
private CameraHelper cameraHelper;
private GalleryHelper galleryHelper;
private MicrophoneHelper microphoneHelper;
private MicrophoneInputStream capture;
private boolean listening = false;
/**
* On create.
*
* @param savedInstanceState the saved instance state
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu);
BottomNavigationView bottomNav= findViewById(R.id.bottom_navigation);
bottomNav.setOnNavigationItemSelectedListener(navListener);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DialFragment()).commit();
microphoneHelper = new MicrophoneHelper(this);
speechService = initSpeechToTextService();
input = findViewById(R.id.input);
mic = findViewById(R.id.mic);
mic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!listening) {
// Update the icon background
runOnUiThread(new Runnable() {
@Override
public void run() {
mic.setBackgroundColor(Color.GREEN);
}
});
capture = microphoneHelper.getInputStream(true);
new Thread(new Runnable() {
@Override
public void run() {
try {
speechService.recognizeUsingWebSocket(getRecognizeOptions(capture),
new MicrophoneRecognizeDelegate());
} catch (Exception e) {
showError(e);
}
}
}).start();
listening = true;
} else {
// Update the icon background
runOnUiThread(new Runnable() {
@Override
public void run() {
mic.setBackgroundColor(Color.LTGRAY);
}
});
microphoneHelper.closeInputStream();
listening = false;
}
}
});
}
private void showError(final Exception e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainMenu.this, e.getMessage(), Toast.LENGTH_SHORT).show();
e.printStackTrace();
// Update the icon background
mic.setBackgroundColor(Color.LTGRAY);
}
});
}
private void showMicText(final String text) {
runOnUiThread(new Runnable() {
@Override
public void run() {
input.setText(text);
}
});
}
private void enableMicButton() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mic.setEnabled(true);
}
});
}
private SpeechToText initSpeechToTextService() {
IamOptions options = new IamOptions.Builder()
.apiKey(getString(R.string.speech_text_iam_apikey))
.build();
SpeechToText service = new SpeechToText(options);
service.setEndPoint(getString(R.string.speech_text_url));
return service;
}
private RecognizeOptions getRecognizeOptions(InputStream captureStream) {
return new RecognizeOptions.Builder()
.audio(captureStream)
.contentType(ContentType.OPUS.toString())
.model("en-US_BroadbandModel")
.interimResults(true)
.inactivityTimeout(2000)
.build();
}
private abstract class EmptyTextWatcher implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
// assumes text is initially empty
private boolean isEmpty = true;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.length() == 0) {
isEmpty = true;
onEmpty(true);
} else if (isEmpty) {
isEmpty = false;
onEmpty(false);
}
}
@Override
public void afterTextChanged(Editable s) {}
public abstract void onEmpty(boolean empty);
}
private class MicrophoneRecognizeDelegate extends BaseRecognizeCallback {
@Override
public void onTranscription(SpeechRecognitionResults speechResults) {
System.out.println(speechResults);
if (speechResults.getResults() != null && !speechResults.getResults().isEmpty()) {
String text = speechResults.getResults().get(0).getAlternatives().get(0).getTranscript();
showMicText(text);
}
}
@Override
public void onError(Exception e) {
try {
// This is critical to avoid hangs
// (see https://github.com/watson-developer-cloud/android-sdk/issues/59)
capture.close();
} catch (IOException e1) {
e1.printStackTrace();
}
showError(e);
enableMicButton();
}
@Override
public void onDisconnected() {
enableMicButton();
}
}
/**
* On request permissions result.
*
* @param requestCode the request code
* @param permissions the permissions
* @param grantResults the grant results
*/
@Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions,
int[] grantResults) {
switch (requestCode) {
case CameraHelper.REQUEST_PERMISSION: {
// permission granted
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
cameraHelper.dispatchTakePictureIntent();
}
}
case MicrophoneHelper.REQUEST_PERMISSION: {
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission to record audio denied", Toast.LENGTH_SHORT).show();
}
}
}
}
/**
* On activity result.
*
* @param requestCode the request code
* @param resultCode the result code
* @param data the data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CameraHelper.REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
loadedImage.setImageBitmap(cameraHelper.getBitmap(resultCode));
}
if (requestCode == GalleryHelper.PICK_IMAGE_REQUEST && resultCode == RESULT_OK) {
loadedImage.setImageBitmap(galleryHelper.getBitmap(resultCode, data));
}
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Fragment selectedFragment=null;
switch (item.getItemId()){
case R.id.nav_dialer:
selectedFragment=new DialFragment();
break;
case R.id.nav_contacts:
selectedFragment=new ContactsFragment();
break;
case R.id.nav_transcripts:
selectedFragment=new TranscriptsFragment();
break;
case R.id.nav_settings:
selectedFragment=new SettingsFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,selectedFragment).commit();
return true;
}
};
}
Я ожидаю, что смогу одновременно передавать аудио вход с микрофона на IBM Watson SpeechОтправь текст и позвони одновременно.