正如Iftah在这个回答中所说的那样,我可以通过将Intent传递给Uri来获取由Android中的Speech Recoginition录制的音频:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// the recording url is in getData:
Uri audioUri = data.getData();
}
Run Code Online (Sandbox Code Playgroud)
这里Intent data有我想要的没有问题.
这一切都完美无缺,但是这个解决方案为用户提示何时发言,我不想这样解决问题我让我的活动实现了RecognitionListener:
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) …Run Code Online (Sandbox Code Playgroud) 我试图在文件中保存由android的语音识别服务监听的音频数据.
实际上我RecognitionListener按照这里的解释实现:
Android上的语音到文本
将数据保存到缓冲区中,如下所示: 捕获发送到Google语音识别服务器的音频
并将缓冲区写入Wav文件,如此处所示. Android将原始字节记录到HVEp Streaming的WAVE文件中
我的问题是如何获得适当的音频设置以保存在wav文件的标题中.事实上,当我播放wav文件时,只听到奇怪的噪音,这个参数,
short nChannels=2;// audio channels
int sRate=44100; // Sample rate
short bSamples = 16;// byteSample
Run Code Online (Sandbox Code Playgroud)
或者没有这个:
short nChannels=1;// audio channels
int sRate=8000; // Sample rate
short bSamples = 16;// byteSample
Run Code Online (Sandbox Code Playgroud)
令人困惑的是从logcat查看语音识别任务的参数我发现第一个Set PLAYBACK采样率为44100 HZ:
12-20 14:41:34.007: DEBUG/AudioHardwareALSA(2364): Set PLAYBACK PCM format to S16_LE (Signed 16 bit Little Endian)
12-20 14:41:34.007: DEBUG/AudioHardwareALSA(2364): Using 2 channels for PLAYBACK.
12-20 14:41:34.007: DEBUG/AudioHardwareALSA(2364): Set PLAYBACK sample rate to 44100 HZ
12-20 14:41:34.007: DEBUG/AudioHardwareALSA(2364): …Run Code Online (Sandbox Code Playgroud) 我的应用程序使用AsyncTask中的MediaRecorder类记录音频,并使用Google API转换语音到文本 - Recognizer Intent - 使用此问题的代码:如何在没有Android手机烦人的对话框的情况下使用语音识别
我也试过在Thread中录制音频,但这是更糟糕的解决方案.它会导致更多问题.我的问题是我的应用程序在模拟器上正常工作.但是由于缺乏语音识别服务,模拟器不支持语音重新识别.在我的设备上,当我开始录制音频和语音识别时,我的应用程序崩溃了 - "已意外停止".但是当我关闭wifi时,应用程序就像在模拟器上一样正常工作.
在AndroidManifest中录制音频需要:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Run Code Online (Sandbox Code Playgroud)
和语音识别要求:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
Run Code Online (Sandbox Code Playgroud)
我想这是单音频输入的问题?我该如何解决这个问题?Google Speech Recognizer需要在主UI线程中工作,因此我无法在Async Task中执行此操作.所以我在Async Task中录音.我不知道为什么会导致问题.
我已将设备连接到Eclipse,并且我已使用USB调试.这是我在LogCat中的执行:
08-23 14:50:03.528: ERROR/ActivityThread(12403): Activity go.android.Activity has leaked ServiceConnection android.speech.SpeechRecognizer$Connection@48181340 that was originally bound here
08-23 14:50:03.528: ERROR/ActivityThread(12403): android.app.ServiceConnectionLeaked: Activity go.android.Activity has leaked ServiceConnection android.speech.SpeechRecognizer$Connection@48181340 that was originally bound here
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:1121)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:1016)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ContextImpl.bindService(ContextImpl.java:951)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.content.ContextWrapper.bindService(ContextWrapper.java:347)
08-23 14:50:03.528: ERROR/ActivityThread(12403): …Run Code Online (Sandbox Code Playgroud) 我的应用程序使用RecognizerIntent记录用户的语音并进行语音识别.
现在,我想将结果与一些开源语音识别引擎进行比较.他们中的大多数都将音频文件作为输入.我的想法是,从Android的麦克风捕获声音,同时启动RecognizerIntent.但看起来,访问麦克风是独家的.
Android的SpeechRecognizer显然不允许将您正在进行语音识别的输入记录到音频文件中.也就是说,要么使用MediaRecorder(或AudioRecord)录制语音,要么使用SpeechRecognizer进行语音识别,在这种情况下,音频不会记录到文件中(至少不能录制到一个文件); 但你不能同时做到这两件事.
多次询问如何在Android中同时录制音频和进行语音识别的问题,最流行的"解决方案"是录制一个flac文件并使用Google的非官方语音API,允许你发送一个flac通过POST请求提交文件并获取带有转录的json响应. http://mikepultz.com/2011/03/accessing-google-speech-api-chrome-11/(过时的Android版) https://github.com/katchsvartanian/voiceRecognition/tree/master/VoiceRecognition http:// mikepultz.com/2013/07/google-speech-api-full-duplex-php-version/
这非常有效,但有一个巨大的限制,它不能用于超过大约10-15秒的文件(确切的限制不明确,可能取决于文件大小或可能的单词数量).这使它不适合我的需要.
此外,将音频文件切片为较小的文件不是一种可能的解决方案; 甚至忘记了在正确的位置(不是在一个单词的中间)正确分割文件的困难,对上述web服务api的许多连续请求将随机导致空响应(Google表示每次使用限制为50个请求那天,但像往常一样,他们没有透露明确限制请求突发的实际使用限制的细节.
因此,所有这些似乎表明,在将输入录制到Android中的音频文件的同时获取语音转录是不可能的.
但是,谷歌Keep Android应用就是这么做的.它允许你说话,将你所说的内容翻译成文本,并保存文本和录音(很不清楚它存储在哪里,但你可以重放它).它没有长度限制.
所以问题是:是否有人知道Google如何做到这一点?我会查看源代码,但它似乎不可用,是吗?
我在进行语音识别时嗅探了Google Keep发送和接收的数据包,它肯定不会使用上面提到的语音api.所有流量都是TLS,并且(从外部看)它看起来与使用SpeechRecognizer时非常相似.
那么也许存在将麦克风输入流"分割"(即复制或复用)到两个流中的方式,并将其中一个馈送到SpeechRecognizer,另一个馈送到MediaRecorder?
我正在开发一个功能,当按下按钮时,它将启动语音识别,同时记录用户说的内容.代码如下:
button_start.setOnTouchListener( new View.OnTouchListener()
{
@Override
public boolean onTouch(View arg0, MotionEvent event)
{
if (pressed == false)
{
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,"voice.recognition.test");
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "zh-HK");
intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS,1);
sr.startListening(intent);
Log.i("111111","11111111");
pressed = true;
}
recordAudio();
}
if((event.getAction()==MotionEvent.ACTION_UP || event.getAction()==MotionEvent.ACTION_CANCEL))
{
stopRecording();
}
return false;
}
});
}
public void recordAudio()
{
isRecording = true;
try
{
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(audioFilePath);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.prepare();
}
catch (Exception e)
{
e.printStackTrace();
}
mediaRecorder.start();
}
public void stopRecording()
{
if (isRecording) …Run Code Online (Sandbox Code Playgroud) 认识到由谷歌服务器的演讲,我用SpeechRecognizer类与RecognitionListener组合中建议斯蒂芬的回答到这个问题。此外,我尝试使用 RecognitionListener 中的 onBufferReceived() 回调来捕获正在识别的音频信号,例如:
byte[] sig = new byte[500000] ;
int sigPos = 0 ;
...
public void onBufferReceived(byte[] buffer) {
System.arraycopy(buffer, 0, sig, sigPos, buffer.length) ;
sigPos += buffer.length ;
}
...
Run Code Online (Sandbox Code Playgroud)
这似乎工作正常,除非 SpeechRecognizer 无法连接到 Google 服务器、音频块未复制到上述sig数组中,并且会引发 HTTP 连接超时异常。SpeechRecognizer 最终连接到谷歌服务器,识别结果表明收到了完整的音频信号;只有sig数组缺少一些音频块。
有没有人遇到同样的问题?任何解决方案的提示?谢谢!
我正在使用RecognizerIntent.ACTION_RECOGNIZE_SPEECH ,,,我的问题是,我的问题是,我不知道如何创建将捕获用户输入的语音的缓冲区.我在堆栈溢出上读了很多,但我只是不明白我将如何将缓冲区和识别服务回调到我的代码中.以及我将如何回放保存到缓冲区的内容.
这是我的代码:
public class Voice extends Activity implements OnClickListener {
byte[] sig = new byte[500000] ;
int sigPos = 0 ;
ListView lv;
static final int check =0;
protected static final String TAG = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.voice);
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
"com.domain.app");
SpeechRecognizer recognizer = SpeechRecognizer
.createSpeechRecognizer(this.getApplicationContext());
RecognitionListener listener = new RecognitionListener() {
@Override
public void onResults(Bundle results) {
ArrayList<String> voiceResults = results
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); …Run Code Online (Sandbox Code Playgroud)