एंड्रॉइड में ऑन-डिवाइस स्पीच रिकग्निशन (गूगल API के बिना)
यह ट्यूटोरियल SpeechRecognizer API का उपयोग करके ऑन-डिवाइस स्पीच रिकग्निशन लागू करने का तरीका दिखाता है, जो इंटरनेट के बिना काम करता है (यदि डिवाइस ऑफलाइन मॉडल सपोर्ट करता है)।
आवश्यक अनुमतियाँ
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- कुछ डिवाइस पर मॉडल डाउनलोड के लिए -->
लेआउट (activity_main.xml)
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp">
<ImageView
android:id="@+id/ivMic"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:src="@drawable/ic_mic"
android:contentDescription="माइक्रोफोन" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ivMic"
android:layout_marginTop="24dp"
android:paddingHorizontal="24dp"
android:max="10"
android:visibility="gone" />
<TextView
android:id="@+id/tvResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/progressBar"
android:layout_centerHorizontal="true"
android:layout_marginTop="24dp"
android:textSize="18sp"
android:gravity="center" />
<ToggleButton
android:id="@+id/toggleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="50dp"
android:textOn="सुनना बंद करें"
android:textOff="सुनना शुरू करें" />
</RelativeLayout>
MainActivity.java
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.util.Log;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import java.util.ArrayList;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements RecognitionListener {
private static final String TAG = "SpeechRecognition";
private static final int REQUEST_RECORD_PERMISSION = 100;
private TextView tvResult;
private ToggleButton toggleButton;
private ProgressBar progressBar;
private SpeechRecognizer speechRecognizer;
private Intent recognizerIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResult = findViewById(R.id.tvResult);
progressBar = findViewById(R.id.progressBar);
toggleButton = findViewById(R.id.toggleButton);
// SpeechRecognizer इंस्टेंस बनाएं
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
speechRecognizer.setRecognitionListener(this);
// रिकग्निशन इंटेंट कॉन्फिगर करें
recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
recognizerIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 3);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true);
// ऑफलाइन मोड प्राथमिकता (यदि उपलब्ध हो)
recognizerIntent.putExtra(RecognizerIntent.EXTRA_PREFER_OFFLINE, true);
Log.d(TAG, "रिकग्निशन उपलब्ध: " + SpeechRecognizer.isRecognitionAvailable(this));
toggleButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
startListening();
} else {
stopListening();
}
});
}
private void startListening() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECORD_AUDIO},
REQUEST_RECORD_PERMISSION);
toggleButton.setChecked(false);
return;
}
progressBar.setVisibility(View.VISIBLE);
progressBar.setIndeterminate(true);
tvResult.setText("सुन रहा हूं...");
speechRecognizer.startListening(recognizerIntent);
}
private void stopListening() {
progressBar.setIndeterminate(false);
progressBar.setVisibility(View.GONE);
speechRecognizer.stopListening();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_RECORD_PERMISSION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startListening();
} else {
Toast.makeText(this, "माइक्रोफोन अनुमति आवश्यक है", Toast.LENGTH_SHORT).show();
toggleButton.setChecked(false);
}
}
}
// RecognitionListener कॉलबैक्स
@Override
public void onReadyForSpeech(Bundle params) {
Log.d(TAG, "onReadyForSpeech");
progressBar.setIndeterminate(false);
progressBar.setMax(10);
}
@Override
public void onBeginningOfSpeech() {
Log.d(TAG, "onBeginningOfSpeech");
}
@Override
public void onRmsChanged(float rmsdB) {
// साउंड लेवल के आधार पर प्रोग्रेस बार अपडेट
progressBar.setProgress(Math.min(10, (int) (rmsdB + 5)));
}
@Override
public void onBufferReceived(byte[] buffer) {
Log.d(TAG, "onBufferReceived");
}
@Override
public void onEndOfSpeech() {
Log.d(TAG, "onEndOfSpeech");
progressBar.setIndeterminate(true);
toggleButton.setChecked(false);
}
@Override
public void onError(int errorCode) {
String errorMessage = getErrorText(errorCode);
Log.e(TAG, "त्रुटि: " + errorMessage);
tvResult.setText("त्रुटि: " + errorMessage);
toggleButton.setChecked(false);
progressBar.setVisibility(View.GONE);
}
@Override
public void onResults(Bundle results) {
Log.d(TAG, "onResults");
ArrayList matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
if (matches != null && !matches.isEmpty()) {
StringBuilder text = new StringBuilder();
for (String result : matches) {
text.append(result).append("\n");
}
tvResult.setText(text.toString().trim());
}
progressBar.setVisibility(View.GONE);
}
@Override
public void onPartialResults(Bundle partialResults) {
ArrayList matches = partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
if (matches != null && !matches.isEmpty()) {
tvResult.setText("आंशिक: " + matches.get(0));
}
}
@Override
public void onEvent(int eventType, Bundle params) {
Log.d(TAG, "onEvent: " + eventType);
}
private String getErrorText(int errorCode) {
switch (errorCode) {
case SpeechRecognizer.ERROR_AUDIO: return "ऑडियो रिकॉर्डिंग त्रुटि";
case SpeechRecognizer.ERROR_CLIENT: return "क्लाइंट साइड त्रुटि";
case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS: return "अपर्याप्त अनुमतियाँ";
case SpeechRecognizer.ERROR_NETWORK: return "नेटवर्क त्रुटि";
case SpeechRecognizer.ERROR_NETWORK_TIMEOUT: return "नेटवर्क टाइमआउट";
case SpeechRecognizer.ERROR_NO_MATCH: return "कोई मिलान नहीं";
case SpeechRecognizer.ERROR_RECOGNIZER_BUSY: return "रिकग्निशन सेवा व्यस्त";
case SpeechRecognizer.ERROR_SERVER: return "सर्वर त्रुटि";
case SpeechRecognizer.ERROR_SPEECH_TIMEOUT: return "कोई स्पीच इनपुट नहीं";
default: return "समझ नहीं आया, कृपया पुनः प्रयास करें";
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (speechRecognizer != null) {
speechRecognizer.destroy();
Log.d(TAG, "SpeechRecognizer नष्ट किया गया");
}
}
}
महत्वपूर्ण बिंदु
- ऑफलाइन सपोर्ट: सभी डिवाइस ऑफलाइन रिकग्निशन सपोर्ट नहीं करते।
EXTRA_PREFER_OFFLINEकेवल एक संकेत है। - लाइफसाइकिल: हमेशा
onDestroy()मेंdestroy()कॉल करें ताकि मेमोरी लीक न हो। - भाषा:
EXTRA_LANGUAGEके साथ भाषा सेट करें (उदाहरण: "hi-IN" हिंदी के लिए)। - निरंतर सुनना: लंबे सत्रों के लिए,
onEndOfSpeechमें पुनःstartListening()कॉल करें।
वैकल्पिक: Vosk (पूरी तरह से ऑफलाइन, ओपन सोर्स)
पूर्ण ऑफलाइन नियंत्रण के लिए, Vosk लाइब्रेरी का उपयोग करें:
// build.gradle
implementation "org.vosk:vosk-android:0.3.45"
// उपयोग
Model model = new Model("model_path");
SpeechRecognizer recognizer = new SpeechRecognizer(model, 16000.0f);