Android XR

Gemini Nano 4 की मदद से, स्मार्ट चश्मे के लिए ऑडियो-फ़र्स्ट अनुभव तैयार करना

स्पीकर

इसके बारे में

बातचीत के बारे में जानकारी

डिवाइस में मौजूद एआई की मदद से, हैंड्स-फ़्री ऑडियो के बेहतरीन अनुभव देने वाले ऐप्लिकेशन बनाने का तरीका जानें. हम आपको हर ज़रूरी जानकारी देंगे: स्मार्ट ग्लास की गतिविधि सेट अप करना, माइक और कैमरा फ़ीड कैप्चर करना, और आवाज़ के साथ-साथ अन्य ऑडियो क्यू को अपने मुख्य यूज़र इंटरफ़ेस (यूआई) के तौर पर इस्तेमाल करना. Google AI Edge Gallery ऐप्लिकेशन में बनाए गए ओपन-सोर्स XR Language Teacher के रीयल-वर्ल्ड शोकेस के ज़रिए, Gemini Nano 4 (Gemma 4 पर बनाया गया और Android डिवाइसों के लिए ऑप्टिमाइज़ किया गया) और ML Kit को इस्तेमाल करने का तरीका जानें. साथ ही, LiteRT रनटाइम का इस्तेमाल करके, तेज़ी से काम करने वाले ऐसे XR अनुभव बनाएं जो नैचुरल तरीके से सुन, देख, और बोल सकें.

खास जानकारी

  • Jetpack Projected लाइब्रेरी (ऐल्फ़ा), Android फ़ोन को इंटेलिजेंट आईवियर से जोड़ती है. अपने मौजूदा ऐप्लिकेशन में प्रोजेक्ट की गई गतिविधि जोड़ने से, कॉन्टेंट को डिसप्ले या सिर्फ़ ऑडियो वाले स्मार्ट ग्लास पर प्रोजेक्ट किया जा सकता है.
  • ML Kit, चुनिंदा डिवाइसों पर ऑडियो-फ़र्स्ट इंटरैक्शन के लिए, डिवाइस पर मौजूद स्पीच लाइब्रेरी का ऐल्फ़ा वर्शन उपलब्ध कराता है. यह 21 स्थान-भाषाओं में, आठ आवाज़ों में लिखे गए शब्दों को सुनने की सुविधा देता है. साथ ही, Pixel 10 पर Gemini Nano के ऐडवांस मोड के साथ, बोली की पहचान की सुविधा देता है.
  • Gemini Nano 4, कैमरे के फ़्रेम और ट्रांसक्राइब किए गए सवालों को एक साथ प्रोसेस करता है. यह सुविधा, उपयोगकर्ता के डिवाइस पर मौजूद स्पीच मॉडल को स्थानीय तौर पर चेन करके, ऑफ़लाइन मोड में काम करती है. यह सुविधा, चुनिंदा फ़्लैगशिप फ़ोन पर उपलब्ध है.
  • टू-पास डिज़ाइन, स्मार्ट ग्लास पर रीयल-टाइम ऑडियो के इंतज़ार के समय को प्राथमिकता देता है. Pass 1, बोले गए टेक्स्ट को स्ट्रीम करता है. इसके लिए, वह इनलाइन एक्सएमएल टैग का इस्तेमाल करता है, ताकि वाक्य के बीच में भाषा बदली जा सके. वहीं, Pass 2 बैकग्राउंड में स्ट्रक्चर्ड डेटा को एक्सट्रैक्ट करता है.
  • ओपन-सोर्स XR Language Teacher को Google AI Edge Gallery ऐप्लिकेशन में उपलब्ध कराया गया है. डेवलपर इसके कोड को मल्टीमोडल असिस्टेंट के अन्य इस्तेमाल के उदाहरणों के लिए अडैप्ट कर सकते हैं.

संसाधन

Gemini Notebook

विषय

  • स्मार्ट-आईवियर
  • android-xr
  • gemini-nano
  • on-device-ai
  • ml-kit
  • बोली पहचानने की सुविधा
  • लिखे गए शब्दों को सुनने की सुविधा के साथ-साथ

ट्रांसक्रिप्ट

ट्रांसक्रिप्ट डाउनलोड करें

परिचय

  • नमस्ते, सभी का स्वागत है.

  • आज आप सभी से मिलकर बहुत खुशी हुई.

  • आने के लिए धन्यवाद.

  • मैं एमी हूं.

  • आज मेरे साथ मेरी कलीग एलिस भी हैं. हम इस बारे में बात करेंगे कि Gemini Nano 4 का इस्तेमाल करके, स्मार्ट आईवियर के लिए ऑडियो-फ़र्स्ट अनुभव कैसे तैयार किया जा सकता है.

  • चलिए, शुरू करते हैं.

  • जब हम इंटेलिजेंट आईवियर की बात करते हैं, तो हमारा मतलब पोर्टेबल और हल्के चश्मों से होता है. इन्हें पूरे दिन पहना जा सकता है.

  • इस कैटगरी में, डिसप्ले और सिर्फ़ ऑडियो वाले स्मार्ट ग्लास शामिल होंगे. इन डिवाइसों में, आपको अलग-अलग तरह के हार्डवेयर देखने को मिलेंगे.

  • सबसे पहले आपको यह दिखेगा कि इनमें एक टच पैड है. इसका इस्तेमाल, उपयोगकर्ता के इनपुट के लिए किया जा सकता है. जैसे, टैप और स्वाइप करना.

  • इनमें स्पीकर, कैमरा, और माइक्रोफ़ोन भी होगा.

  • साथ ही, इनमें डिसप्ले हो भी सकता है और नहीं भी. इसके अलावा, इनमें दोनों का कॉम्बिनेशन भी हो सकता है.

  • आज हम ऑडियो-फ़र्स्ट के बारे में बात करेंगे. साथ ही, यह भी जानेंगे कि कभी भी, कहीं भी, दिलचस्प और शानदार अनुभव कैसे दिया जा सकता है.

  • सिर्फ़ ऑडियो वाले कॉन्टेंट की एक दिलचस्प बात यह है कि इसमें आवाज़ ही आपका यूज़र इंटरफ़ेस (यूआई) बन जाती है.

  • साथ ही, उपयोगकर्ता के डिवाइस पर मौजूद एआई उन डेवलपर के लिए बेहतरीन है जो ऑफ़लाइन और कहीं भी इस्तेमाल किए जा सकने वाले अनुभव चाहते हैं.

Android XR के लिए ऐप्लिकेशन बनाना

  • एक और अच्छी खबर है.

  • इसलिए, अगर पहले से ही Android के लिए ऐप्लिकेशन बनाए जा रहे हैं, तो इसका मतलब है कि Android XR के लिए भी ऐप्लिकेशन बनाए जा रहे हैं.

  • मौजूदा Android ऐप्लिकेशन, ऑडियो ग्लास के साथ बेहतर तरीके से काम करते हैं. ये ब्लूटूथ के ज़रिए, बोलकर दी जाने वाली सूचनाएं और अन्य ऑडियो उपलब्ध कराते हैं.

  • अगर आपको अपने ऐप्लिकेशन को एक्सआर के लिए और बेहतर बनाना है, तो इसके कई तरीके हैं.

  • इसलिए, इस बातचीत में हम उपयोगकर्ता के डिवाइस पर मॉडल के बारे में बात कर रहे हैं. हालांकि, यह पूरी सूची नहीं है.

  • हमारे पास क्लाउड मॉडल भी हैं.

  • जैसे, Gemini Live API.

  • Gemini जैसे सिस्टम एजेंट को इंटिग्रेट किया जा सकता है. ये सभी एजेंट, आपको बेहतर अनुभव देने में मदद कर सकते हैं.

  • तो फिर ऐसा अनुभव कैसे तैयार किया जाए जो नैचुरल तरीके से सुनता, देखता, और बोलता हो?

  • आज हम आपको डिवाइस पर मौजूद एआई की मदद से, बोलकर इस्तेमाल की जा सकने वाली बेहतरीन सुविधाएं बनाने का तरीका बताएंगे.

  • मैं आपको बुनियादी बातें बताऊंगी: स्मार्ट ग्लास के लिए ऐप्लिकेशन कैसे बनाएं, अपनी गतिविधि कैसे सेट अप करें, ज़रूरी अनुमतियां कैसे पाएं, और बातचीत वाले यूज़र इंटरफ़ेस (यूआई) के लिए ML Kit का इस्तेमाल कैसे करें.

  • इसके बाद, मैं ऐलिस को माइक सौंपूंगा. वे आपको Gemini Nano 4 का इस्तेमाल करने के कुछ असल उदाहरणों के बारे में बताएंगी.

  • चलिए, अब कोड के बारे में जानते हैं.

  • इसलिए, चश्मे के साथ फ़ोन ही ज़्यादा काम करता है. साथ ही, चश्मे का कॉन्टेंट, फ़ोन से चश्मे पर प्रोजेक्ट किया जाएगा.

  • इसलिए, पहली बार सेट अप करते समय इन डिवाइसों को जोड़ने के लिए, आपको दो चीज़ों की ज़रूरत होगी.

  • सबसे पहले, आपको Jetpack Projected लाइब्रेरी की ज़रूरत होगी.

  • आपको यह डिपेंडेंसी जोड़नी होगी. इसमें वे एपीआई शामिल होंगे जो प्रोजेक्ट किए गए अनुभव को बेहतर बनाएंगे.

    dependencies {
       implementation("androidx.xr.projected:projected:1.0.0-alpha13")
    }
  • इसके बाद, आपको खास तौर पर स्मार्ट ग्लास के लिए एक नई गतिविधि भी बनानी होगी.

    class ProjectedMainActivity : ComponentActivity() {
       override fun onCreate(savedInstanceState: Bundle?) {
           super.onCreate(savedInstanceState)
           setContent {
               // Glasses content
           }
       }
    }
  • इसके बाद, आपको Jetpack Projected लाइब्रेरी का इस्तेमाल, अपने मौजूदा ऐप्लिकेशन और इस नई गतिविधि, दोनों में करना होगा. इससे, ज़रूरत पड़ने पर दोनों डिवाइस आसानी से कम्यूनिकेट कर पाएंगे.

  • इसलिए, आपने जो भी सामान्य गतिविधि देखी है उसकी तरह ही, आपको इसे अपने मेनिफ़ेस्ट में एलान करना होगा.

    <activity
       android:name=".ProjectedMainActivity"
       android:exported="false"
       android:requiredDisplayCategory="android.hardware.display.category.XR_PROJECTED"
       android:label="Example activity for audio glasses">
       <intent-filter>
           <action android:name="android.intent.action.MAIN" />
           <category android:name="android.intent.category.XR_PROJECTED_LAUNCHER"/>
       </intent-filter>
    </activity>
  • इनमें सबसे बड़ा अंतर यह है कि आपको XR_PROJECTED को requiredDisplayCategory के तौर पर इस्तेमाल करना होगा.

  • इससे सिस्टम को पता चलता है कि यह गतिविधि, चश्मे के लिए है.

  • इसके बाद, आपको यहां इंटेंट कैटगरी, XR_PROJECTED_LAUNCHER का भी इस्तेमाल करना होगा.

  • इससे Gemini आपके ऐप्लिकेशन को खोज पाता है, ताकि उपयोगकर्ता उसे बोलकर कभी भी, कहीं भी लॉन्च कर सकें.

  • ठीक है।

  • इसलिए, जैसा कि मैंने बताया, ऐक्टिविटी सेट अप करने के बाद, ऐप्लिकेशन इस्तेमाल करने के अनुभव को बेहतर बनाने के लिए, Projected लाइब्रेरी का इस्तेमाल किया जाएगा.

  • इस लाइब्रेरी में वे सभी टूल मौजूद हैं जिनकी मदद से, स्मार्ट ग्लास का बेहतरीन अनुभव पाया जा सकता है.

  • चलिए, कुछ मुख्य एपीआई के बारे में जानते हैं जिनका इस्तेमाल यहां किया जाएगा.

  • सबसे पहले, isProjectedDeviceConnected के बारे में बात करते हैं.

    // Continuously monitor whether the glasses are connected
    val isGlassesConnected by ProjectedContext.isProjectedDeviceConnected(
       context,
       scope.coroutineContext
    ).collectAsStateWithLifecycle(initialValue = false)
    
    // Launch the activity
    val options = ProjectedContext.createProjectedActivityOptions(context)
    val intent = Intent(context, ProjectedMainActivity::class.java)
    context.startActivity(intent, options.toBundle())
    
    // Check if the device is audio only or has a display
    val projectedDeviceController = ProjectedDeviceController.create(this@ProjectedMainActivity)
    isVisualUiSupported = projectedDeviceController.capabilities.contains(CAPABILITY_VISUAL_UI)
  • इस तरह, स्मार्ट ग्लास के कनेक्शन को लगातार मॉनिटर किया जा सकता है.

  • इसका इस्तेमाल, डिवाइस की लाइफ़ साइकल के साथ किया जाता है. इससे यह पता चलता है कि स्मार्ट ग्लास असल में कब उपलब्ध हैं. इससे न सिर्फ़ यह पता चलता है कि उन्हें कब जोड़ा गया या चालू किया गया, बल्कि यह भी पता चलता है कि उन्हें कब पहना गया और वे इस्तेमाल के लिए कब तैयार हैं.

  • तो, हां, यही है.

  • इससे आपको ठीक-ठीक पता चल जाएगा कि आपको वह गतिविधि कब लॉन्च करनी है.

  • इसके लिए, जब आप गतिविधि लॉन्च करने के लिए तैयार हों, तो गतिविधि शुरू करते समय आपको कुछ खास विकल्प सेट करने होंगे.

  • इनके लिए, आपको ProjectedContext पर createProjectedActivityOptions का इस्तेमाल करना होगा.

  • इसके बाद, उस कॉन्टेक्स्ट का इस्तेमाल करके, इंटेंट के बारे में जानकारी दी जा सकती है.

  • इसके बाद, एक और टूल है जिसका इस्तेमाल आपको करना चाहिए. वह है ProjectedDeviceController.

  • इससे आपको पता चलेगा कि उपयोगकर्ता किस तरह के स्मार्ट ग्लास का इस्तेमाल कर रहा है.

  • जैसा कि मैंने पहले बताया था कि इंटेलिजेंट आईवियर में सिर्फ़ डिसप्ले और ऑडियो वाले चश्मे शामिल होते हैं. आपको यह देखना होगा कि क्या इसमें CAPABILITY_VISUAL_UI की सुविधाएं शामिल हैं. इससे आपको अपने ऐप्लिकेशन को अलग-अलग डिवाइसों के हिसाब से अडजस्ट करने और उस डिवाइस के लिए ऑप्टिमाइज़ किया गया अनुभव देने में मदद मिलेगी.

  • इसलिए, इस अलग अनुभव को तैयार करते समय, आपको डिवाइस के हार्डवेयर को ऐक्सेस करना पड़ सकता है. उदाहरण के लिए, स्मार्ट ग्लास के कैमरे का इस्तेमाल करना.

  • इसलिए, किसी प्रोजेक्ट की गई गतिविधि से ऐसा करने के लिए, आपको ProjectedActivityCompat का इस्तेमाल करके ज़रूरी अनुमतियों का अनुरोध करना होगा.

    // In a projected activity
    private fun requestProjectedPermissions() {
       lifecycleScope.launch {
           try {
               ProjectedActivityCompat.requestPermissions(
                   this@PermissionsFromProjectedActivity,
                   arrayOf(Manifest.permission.CAMERA),
                   // CAMERA_PERMISSION_REQUEST_CODE is a developer defined constant
                   requestCode = CAMERA_PERMISSION_REQUEST_CODE,
               )
           } catch (e: IllegalStateException) {
               // Thrown when the projected system service can't be bound.
               Log.e(TAG, "Request failed: projected service unavailable.", e)
           }
       }
    }
  • अगर आपके ऐप्लिकेशन के पास पहले से ही फ़ोन के लिए ज़रूरी अनुमतियां हैं, तो भी आपको स्मार्ट ग्लास के हार्डवेयर के लिए खास अनुमतियों का अनुरोध करना होगा.

  • अनुमतियों के साथ काम करते समय, Android के लिए सबसे सही तरीकों का पालन करना न भूलें.

  • मेनिफ़ेस्ट में ज़रूरी अनुमतियों का एलान करें. साथ ही, उन अनुमतियों का अनुरोध करें जिनकी ज़रूरत आपके ऐप्लिकेशन को काम करने के लिए है.

  • इसलिए, हमने developer.android.com पर अपनी साइट पर इस बारे में जानकारी दी है.

  • हालांकि, हमारे पास एक नई स्किल भी है, जिसे प्रोजेक्टेड हार्डवेयर स्किल कहा जाता है.

  • Android Studio में Android के सीएलआई के साथ इसका इस्तेमाल करके, अनुमतियों का वर्कफ़्लो सेट अप किया जा सकता है. साथ ही, इस स्किल और Android की अन्य सभी स्किल का ऐक्सेस पाया जा सकता है.

    android skills add projected-hardware
    android skills add --all

ऑडियो-फ़र्स्ट अनुभव डिज़ाइन करना

  • ठीक है, अब जब हम कनेक्ट हो गए हैं, हमें अपने हार्डवेयर की क्षमताओं के बारे में पता है, और हमारे पास सही अनुमतियां हैं, तो आइए उन टूल के बारे में बात करते हैं जिनका इस्तेमाल करके आपको ऑडियो अनुभव को बेहतर बनाना है.

  • इसलिए, ऑडियो-फ़र्स्ट अनुभव को डिज़ाइन करते समय, हम यह पक्का करना चाहते हैं कि हम उपयोगकर्ताओं को अच्छी क्वालिटी का अनुभव दे रहे हों.

  • इसमें कुछ मुख्य इंटरैक्शन शामिल हो सकते हैं.

  • पहला तरीका है, आउटपुट के तौर पर आवाज़ का इस्तेमाल करना. इससे उपयोगकर्ता को आपकी आवाज़ नैचुरल तरीके से सुनाई देती है.

  • इसके बाद, उपयोगकर्ता को खास ऑडियो सिग्नल भेजने के लिए, ईयरकॉन का इस्तेमाल किया जाएगा.

  • इसके अलावा, उपयोगकर्ता के इनपुट को भी मैनेज किया जा सकता है. जैसे, टचपैड पर टैप और स्वाइप करके या उपयोगकर्ता को आपके ऐप्लिकेशन से बात करने की अनुमति देकर.

  • इसलिए, सबसे पहले हम आउटपुट के तौर पर आवाज़ का इस्तेमाल करने के बारे में बात करेंगे.

  • इसलिए, मैं आपको ML Kit की नई जेन एआई टेक्स्ट-टू-स्पीच लाइब्रेरी के बारे में बताना चाहता हूं.

  • फ़िलहाल, यह सुविधा ऐल्फ़ा वर्शन में उपलब्ध है. साथ ही, यह चुनिंदा Pixel और Samsung डिवाइसों पर ही काम करती है.

  • हम इस सुविधा को लेकर काफ़ी उत्साहित हैं. खास तौर पर, ऑडियो-फ़र्स्ट पॉडकास्ट के लिए.

  • अगर आपने पहले लिखे गए शब्दों को सुनने की सुविधा का इस्तेमाल किया है, तो आपको पता होगा कि सिस्टम की आवाज़ हमेशा उतनी नैचुरल नहीं होती जितनी आपको पसंद है.

  • अन्य आवाज़ों के लिए क्लाउड मॉडल से कनेक्ट करने पर, आपको इंतज़ार करना पड़ सकता है या अतिरिक्त शुल्क देना पड़ सकता है.

  • इसलिए, ML Kit आपको सिस्टम टीटीएस की तुलना में ज़्यादा नैचुरल आवाज़ देता है.

  • ML Kit में आठ अलग-अलग आवाज़ें उपलब्ध हैं. इनमें से, अपने ऐप्लिकेशन के हिसाब से कोई भी आवाज़ चुनी जा सकती है.

  • इसके अलावा, ML Kit में 21 अलग-अलग भाषाओं के लिए बेहतरीन सहायता उपलब्ध है. इनमें से अपनी पसंद की भाषा चुनी जा सकती है.

  • इसके अलावा, इसका एक और बड़ा फ़ायदा यह है कि डाउनलोड करने के बाद, यह पूरी तरह से डिवाइस पर काम करेगा.

  • इसलिए, यह मॉडल सिस्टम में डाउनलोड किया जाएगा और इसे सभी ऐप्लिकेशन के साथ शेयर किया जाएगा. इससे आपके APK का साइज़ नहीं बढ़ेगा.

  • यह ऑफ़लाइन भी उपलब्ध है. यह उन लोगों के लिए काफ़ी अहम है जो स्मार्ट ग्लास का इस्तेमाल करते हैं और कभी भी, कहीं भी सफ़र कर रहे हैं. ऐसा हो सकता है कि उनके पास वाई-फ़ाई न हो या वे खराब कवरेज वाले इलाकों में हों. हालांकि, आपको बेहतर परफ़ॉर्मेंस भी देखने को मिल सकती है, क्योंकि आपको सर्वर को दोतरफ़ा यात्रा करने की ज़रूरत नहीं पड़ती.

  • ठीक है।

  • चलिए, इस लाइब्रेरी के बारे में ज़्यादा जानकारी देखते हैं. साथ ही, यह भी जानते हैं कि इसका इस्तेमाल करके, हम किस तरह से ऐप्लिकेशन बना सकते हैं.

  • इसलिए, सबसे पहले आपको डिपेंडेंसी जोड़नी होगी.

    dependencies {
       // ML Kit GenAI TTS SDK
       implementation("com.google.mlkit:genai-text-to-speech:1.0.0-alpha1")
    }
  • इसलिए, आपको सिर्फ़ ML Kit के टेक्स्ट-टू-स्पीच एसडीके की ज़रूरत है.

  • इसके बाद, कोड लिखना शुरू किया जा सकता है.

  • इसलिए, GenAI ML Kit लाइब्रेरी में, स्पीच सिंथेसाइज़र एपीआई शामिल हैं.

    // 1. Initializing the SpeechSynthesizer client.
    val options = SpeechSynthesizerOptions.Builder(Locale.US).build()
    val client = SpeechSynthesis.getClient(options)
    
    // 2. Check and download the voice model.
    val voiceInfo = client.getSupportedVoices().firstOrNull()
    
    if (voiceInfo != null && client.checkStatus(voiceInfo) == FeatureStatus.DOWNLOADABLE) {
       client.download(voiceInfo).collect { status -> println("Download status: $status") }
    } else if (voiceInfo == null) {
       // Tip: Fallback to system TTS if ML Kit voice is unavailable
    }
  • इससे आपको अपनी पसंद की आवाज़ें लागू करने का आसान तरीका मिलता है.

  • यहां आपको सबसे पहले, स्पीच सिंथेसाइज़र का इस्तेमाल करके अपने क्लाइंट को फिर से शुरू करना होगा. साथ ही, अपनी चुनी हुई भाषा सेट करनी होगी.

  • इसके बाद, डाउनलोड की स्थिति देखें और आवाज़ चुनें.

  • इस उदाहरण में, हम पहली आवाज़ चुन रहे हैं. हालांकि, हम यहां यह भी बताना चाहते हैं कि हम firstOrNull का इस्तेमाल कर रहे हैं.

  • जैसा कि मैंने बताया, ML Kit के लिए ज़रूरी है कि आपके पास Samsung या Pixel डिवाइस हो.

  • इसलिए, अगर आपको शून्य वैल्यू मिलती है, तो इसका मतलब यह हो सकता है कि उपयोगकर्ता, इस सुविधा के साथ काम करने वाले फ़ोन का इस्तेमाल नहीं कर रहा है.

  • इसके बाद, आपको यह पक्का करना होगा कि आपके पास फ़ॉलबैक मौजूद हो. भले ही, वह सिस्टम की लिखे गए शब्दों को सुनने की सुविधा पर वापस जाना हो या रिकॉर्ड किया गया कोई मैसेज चलाना हो या ऐसा ही कुछ और.

  • ठीक है. इसके बाद, अनुरोध करने के लिए, स्पीच सिंथे- SpeechSynthesizerRequest का इस्तेमाल किया जाएगा. इसमें इनपुट टेक्स्ट दिया जाएगा. इसके बाद, इस्तेमाल और कॉन्टेंट टाइप को सेट किया जाएगा.

    // 3. Construct the SpeechSynthesizerRequest
    val request = SpeechSynthesizerRequest(
       input = SpeechSynthesizerRequest.Input.Text("Hello world", voiceInfo),
       audioAttributes = AudioAttributes.Builder()
           .setUsage(AudioAttributes.USAGE_MEDIA)
           .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
           .build()
    )
    
    // 4. Speak and collect status
    client.synthesize(request).collect { response ->
       when (response) {
           is SpeechSynthesizerResponse.StatusUpdate -> println("Playback status: ${response.status}")
       }
    }
  • स्पीच चलाएं, स्टेटस पर नज़र रखें, और- ताकि आपको पता चल सके कि स्पीच कब पूरी हुई. इसके बाद, होने वाली किसी भी गड़बड़ी को ठीक करें.

  • इसके बाद, ज़रूरत पड़ने पर किसी भी संसाधन को बंद करें.

    // 4. Speak and collect status
    client.synthesize(request).collect { response ->
       when (response) {
           is SpeechSynthesizerResponse.StatusUpdate -> println("Playback status: ${response.status}")
       }
    }
    
    // 5. Release resources when finished (e.g., on Activity destroy)
    override fun onDestroy() {
       super.onDestroy()
       client.close()
    }
  • यह काफ़ी आसान है, है न?

  • इन चरणों को अपनाकर, अपने ऐप्लिकेशन की आवाज़ को पूरी तरह से बदला जा सकता है. जैसे, इस तरह की आवाज़ से…

  • नमस्ते, Android डेवलपर.

  • आज आप सभी से मिलकर बहुत खुशी हुई.

  • हमें उम्मीद है कि आपको ऑडियो-फ़र्स्ट अनुभवों पर हमारी प्रज़ेंटेशन पसंद आ रही होगी.

  • इस तरह की आवाज़ में बदल दिया.

  • नमस्ते Android डेवलपर.

  • आज आप सभी से मिलकर बहुत खुशी हुई.

  • हमें उम्मीद है कि आपको ऑडियो-फ़र्स्ट अनुभवों पर हमारी प्रज़ेंटेशन पसंद आ रही होगी.

  • यह पहले से बेहतर है, है न?

  • ठीक है।

  • ML Kit की लिखे गए शब्दों को सुनने की सुविधा लाइब्रेरी एक बेहतरीन टूल है. हालांकि, इसमें सिर्फ़ इन आवाज़ों का इस्तेमाल नहीं किया जा सकता, बल्कि इस लाइब्रेरी की मदद से ईयरकॉन भी चलाए जा सकते हैं.

    // 1. Register Earcon resource with Builder
    SpeechSynthesizerOptions.Builder(Locale.US)
       .addEarcon(
           name = "shutter_sound",
           Uri = "path/to/earcon.file".toUri()
       )
       .build()
    
    // 2. Request Earcon playback
    val request = SpeechSynthesizerRequest(
       input = SpeechSynthesizerRequest.Input.Earcon(
           name = "shutter_sound"
       ),
       audioAttributes = AudioAttributes.Builder()
           .setUsage(AudioAttributes
               .USAGE_ASSISTANCE_SONIFICATION)
           .setContentType(AudioAttributes
               .CONTENT_TYPE_SONIFICATION)
           .build()
    )
  • जैसा कि नाम से पता चलता है, ईयरकॉन आइकॉन के ऑडियो वर्शन होते हैं.

  • इससे आपको अपने उपयोगकर्ता से बातचीत करने के लिए, छोटी-छोटी आवाज़ें चलाने की सुविधा मिलेगी.

  • ईयरकॉन वाले विज़ुअल आइकॉन की तरह ही, उपयोगकर्ता को यह जानना होगा कि ये क्या हैं और इनका क्या मतलब है.

  • इसलिए, शुरुआत में आपको उन्हें बोलकर दी जाने वाली सूचनाओं के साथ जोड़ना चाहिए, ताकि यह साफ़ हो सके.

  • हमने पहले से ही कुछ स्टैंडर्ड साउंड बनाए हैं, जो Android Design Hub पर उपलब्ध हैं. इनका इस्तेमाल किया जा सकता है. इन्हें सीधे वहां से डाउनलोड किया जा सकता है. साथ ही, इनका इस्तेमाल ऐप्लिकेशन खोलने, ऐप्लिकेशन बंद करने, गड़बड़ी की सूचनाएं देने, और म्यूट या अनम्यूट करने जैसी चीज़ों के लिए किया जा सकता है.

  • इसके अलावा, आपके पास अपनी पसंद के मुताबिक ईयरकॉन बनाने का विकल्प भी है.

  • ईयरकॉन के लिए, हमारा सुझाव है कि आप कुछ सबसे सही तरीके अपनाएं. भले ही, आपने डिज़ाइन हब से डाउनलोड किए गए ईयरकॉन इस्तेमाल किए हों या खुद के ईयरकॉन बनाए हों.

  • इसलिए, आपको ईयरकॉन का इस्तेमाल सोच-समझकर करना चाहिए.

  • इसलिए, कुछ बातों का ध्यान रखना ज़रूरी है. जैसे, शुरुआत में ईयरकॉन का ज़्यादा इस्तेमाल न करें.

  • एक ही साउंड को बार-बार न चलाएं. इससे कानों में थकान महसूस हो सकती है.

  • यह भी ध्यान रखें कि आपके ईयरकॉन शानदार और आसान होने चाहिए. साथ ही, उन्हें लागू करते समय जानी-पहचानी पिच और रिदम का इस्तेमाल करें.

  • इसके बाद, ऐसे ईयरकॉन इस्तेमाल करने से बचें जो बहुत जटिल हों और जिन्हें समझाने की ज़रूरत पड़े. ऐसे ईयरकॉन, आवाज़ वाली सूचना के तौर पर बेहतर हो सकते हैं.

  • यह भी ध्यान रखें कि जो आवाज़ स्टूडियो, सिस्टम या कंप्यूटर के स्पीकर पर अच्छी लगती है वह बार-बार सुनने पर दर्शकों को परेशान कर सकती है.

  • इसलिए, उपयोगकर्ताओं को ऐसी आवाज़ें न सुनाएं जिनसे वे भ्रमित हो जाएं या ज़रूरी सूचनाओं को अनदेखा कर दें.

  • ठीक है।

  • इसलिए, अब हम ऑडियो क्यू और सुझाव, राय या शिकायत देने की सुविधा दे सकते हैं. इसके लिए, नैचुरल स्पीच या ईयरकॉन का इस्तेमाल किया जा सकता है.

  • लेकिन इनपुट का क्या?

  • इसलिए, डिवाइस पर एक टचपैड या खास बटन भी होता है. इसका इस्तेमाल करके, टैप और स्वाइप वाले इंटरैक्शन बनाए जा सकते हैं.

  • हालांकि, हो सकता है कि आपको बातचीत वाले इस यूज़र इंटरफ़ेस (यूआई) की अनुमति देनी हो. इसके लिए, ML Kit के GenAI Speech Recognition API का इस्तेमाल किया जा सकता है.

  • फ़िलहाल, यह ऐल्फ़ा वर्शन में है और चुनिंदा डिवाइसों पर उपलब्ध है. हालांकि, यह दो अलग-अलग मोड में काम करता है.

  • इसलिए, इसमें बेसिक मोड उपलब्ध है. यह उपयोगकर्ता के डिवाइस पर बोली पहचानने की सुविधा का इस्तेमाल करता है. यह सुविधा, एपीआई लेवल 31 और इसके बाद के वर्शन वाले Android डिवाइसों पर उपलब्ध है.

  • इसके बाद, ऐडवांस मोड भी है. यह Gemini Nano का इस्तेमाल करता है. यह Pixel 10 और इसके बाद के वर्शन वाले डिवाइसों पर उपलब्ध है. इसमें आपको बेहतर क्वालिटी और ज़्यादा भाषाओं में अनुवाद की सुविधा मिलेगी.

  • इसलिए, SpeechRecognizer का कोड पैटर्न, SpeechSynthesizer से काफ़ी मिलता-जुलता है.

  • अपना क्लाइंट बनाएं, देखें कि मॉडल उपलब्ध है या नहीं, ज़रूरत पड़ने पर डाउनलोड करें, अनुरोध बनाएं, और अपने संसाधन रिलीज़ करें.

  • इसलिए, आइए हम यहां मुख्य अंतरों पर फ़ोकस करें. जैसे, अनुरोध बनाना, माइक से ऑडियो कैप्चर करना, और फिर नतीजे को प्रोसेस करना.

  • इसके बाद, आपको ज़रूरी डिपेंडेंसी जोड़नी होंगी.

    dependencies {
       // ML Kit Speech Recognition
       implementation("com.google.mlkit:genai-speech-recognition:1.0.0-alpha1")
    }
  • इसके लिए, आपको सिर्फ़ बोली पहचानने वाले एपीआई की ज़रूरत होगी.

  • इसके बाद, अनुरोध बनाने की प्रोसेस शुरू की जा सकती है.

  • इसलिए, पहचान करने के लॉजिक को तय करते समय, आपको suspend फ़ंक्शन का इस्तेमाल करना होगा.

    suspend fun startMyRecognition() {
       // choose locale and mode
       val options: SpeechRecognizerOptions =
           speechRecognizerOptions {
               locale = Locale.US
               preferredMode = SpeechRecognizerOptions.Mode.MODE_ADVANCED
           }
    
       val speechRecognizer: SpeechRecognizer = SpeechRecognition.getClient(options)
    
       val request: SpeechRecognizerRequest =
           speechRecognizerRequest { audioSource = AudioSource.fromMic() }
    ...
  • इसके बाद, बोली पहचानने के विकल्प तय करें. इसके लिए, स्थान-भाषा और preferredMode सेट करें.

  • इसके बाद, यहां से audioSource को चुना जा सकता है और अनुरोध को तय किया जा सकता है.

  • इसके बाद, आपको पहचान की प्रक्रिया शुरू करनी होगी और जवाब इकट्ठा करना होगा.

    speechRecognizer.startRecognition(request).collect { response ->
       when (response) {
           is SpeechRecognizerResponse.PartialTextResponse -> {
               // Real-time: Act immediately if trigger phrase is heard
               handleResponse(response.text, speechRecognizer)
           }
           is SpeechRecognizerResponse.FinalTextResponse -> {
               // Final result and recognition
               handleResponse(response.text, speechRecognizer)
           }
           is SpeechRecognizerResponse.CompletedResponse -> {
               resetListeningUi()
           }
           is SpeechRecognizerResponse.ErrorResponse -> {
               Log.e("SpeechRec", "Error: ${response.e.errorCode}", response.e)
               resetListeningUi()
           }
    ...
  • इसलिए, SpeechRecognizer के साथ आपको चार संभावित जवाब मिल सकते हैं: अधूरा, फ़ाइनल, गड़बड़ी, और पूरा.

  • पार्शियल, रीयल-टाइम स्ट्रीम को देखेगा. इसलिए, इसका इस्तेमाल हॉटवर्ड या कीवर्ड जैसी चीज़ों के लिए किया जाता है.

  • 'फ़ाइनल' का मतलब है कि ऑडियो स्ट्रीम का पूरी तरह से विश्लेषण करने और उसे अपडेट करने के बाद, फ़ाइनल ऑडियो स्ट्रीम ली जा रही है. 'पूरा हुआ' का मतलब है कि स्पीच पूरी हो गई है. इसके बाद, 'गड़बड़ी' का मतलब है कि होने वाली किसी भी गड़बड़ी को इकट्ठा किया जा रहा है.

  • यहां बताया गया है कि हम इन सभी को एक साथ कैसे इस्तेमाल करते हैं.

    // Helper function to check for multiple phrases and trigger the right action
    private suspend fun handleResponse(text: String, recognizer: SpeechRecognizer) {
       val savePhrases = listOf("save", "bookmark", "remember")
       if (savePhrases.any { text.contains(it) }) {
    
           // 1. Update app state immediately
           saveItemForLater()
    
           // 2. Stop the recognizer to enforce the action and prevent TTS echo
           recognizer.stopRecognition()
    
           // 3. Play the mute earcon for immediate, non-verbal confirmation
           playEarcon()
    
           // 4. Provide voice feedback
           playAudioFeedback("Saved")
       }
    }
  • मान लें कि हमें उपयोगकर्ता को यह सुविधा देनी है कि वह बोलकर दिए जाने वाले निर्देश का इस्तेमाल करके, ऐप्लिकेशन को किसी कॉन्टेंट को बाद में देखने के लिए सेव करने के लिए कह सके.

  • हम बोलकर दिए जाने वाले किसी एक निर्देश का इस्तेमाल कर सकते हैं, जिसके बारे में हमने उन्हें बताया है. इसके अलावा, उन्हें कई कीवर्ड और वाक्यांशों का इस्तेमाल करने की अनुमति दी जा सकती है.

  • इसलिए, हमने यहां ये विकल्प सेट किए हैं- हम उन्हें 'सेव करें', 'बुकमार्क करें' या 'याद रखें' का इस्तेमाल करने की अनुमति दे रहे हैं.

  • जैसे ही SpeechRecognizer को पता चलता है कि उपयोगकर्ता ने इनमें से किसी एक वाक्यांश का इस्तेमाल किया है, वह कॉन्टेंट को सेव कर लेगा. इसके बाद, वह बोली की पहचान करने की सुविधा को बंद कर देगा, पसंद के मुताबिक ईयरकॉन चलाएगा, और ML Kit के जेन एआई की मदद से, लिखे गए शब्दों को सुनने की सुविधा का इस्तेमाल करके उपयोगकर्ता को बताएगा कि कॉन्टेंट सेव हो गया है.

एक्सआर लैंग्वेज टीचर की केस स्टडी

  • ठीक है।

  • इसलिए, हमें काफ़ी मुश्किलों का सामना करना पड़ा.

  • यह थोड़ा मुश्किल लग सकता है.

  • अगर आप मेरी तरह हैं, तो आपको असल ज़िंदगी के कुछ उदाहरण देखने होंगे.

  • मैं और ऐलिस आपको इसी बारे में बताना चाहते हैं.

  • वह आपको Google AI Edge Gallery ऐप्लिकेशन में, XR Language Teacher के बारे में बताएंगी.

  • एलिस की टीम ने इसे बनाया है. वे आपको बताएंगी कि यह कैसे काम करता है.

  • अब आपकी बारी.

  • धन्यवाद, ऐमी.

  • हाँ।

  • इसलिए, मैं एक ऐसी चीज़ से शुरुआत करना चाहता हूं जिसे आप में से कई लोग पहचानते होंगे.

  • मैं जैपनीज़ सीख रही हूँ. मैंने भाषा सीखने वाले ऐप्लिकेशन, फ़्लैशकार्ड, स्ट्रीक वगैरह पर घंटों बिताए हैं.

  • इसके बाद, जब मैं टोक्यो पहुंची और एक मार्केट हॉल में गई, तो मुझे एहसास हुआ कि मेरे सामने मौजूद ज़्यादातर शब्द, उन शब्दों से बिलकुल अलग थे जो मैंने सीखे थे.

  • बाज़ार के एक स्टॉल पर लकड़ी का कप-ऐंड-बॉल खिलौना है, जिसे मैं देखकर पहचानता हूं. हालांकि, मुझे नहीं पता कि इसे जैपनीज़ में क्या कहते हैं.

  • मुझे दुकान की खिड़की में रखा एक गहना खरीदना है, लेकिन मुझे उसका नाम नहीं पता.

  • यही वह समय होता है, जब मुझे किसी शब्द को सीखने की सबसे ज़्यादा प्रेरणा मिलती है.

  • मैं सोफ़े पर बैठकर, भाषा सीखने वाले ऐप्लिकेशन का इस्तेमाल नहीं कर रहा था.

  • उस समय, मैं उस चीज़ को देख रहा होता हूं जिसे मुझे सीखना है.

  • इसलिए, मुझे यह चाहिए.

  • मुझे पूरे दिन स्मार्ट ग्लास पहनकर घूमना पसंद है.

  • जब भी मुझे कोई चीज़ पसंद आती है, तो मैं उसके बारे में ज़ोर से पूछती हूँ.

  • इसके बाद, रात में जब मैं अपने होटल वापस जाता, तो मैंने जो भी पूछा होता वह सब मेरे फ़ोन पर वोकैबलरी कार्ड की तरह मेरा इंतज़ार कर रहा होता.

  • हमने यह बनाया है.

  • चलिए, एक छोटी क्लिप देखते हैं.

  • इसलिए, हम इसे एक्सआर लैंग्वेज टीचर कहते हैं.

  • नमस्ते.

  • आज आपको किस बारे में जानकारी चाहिए?

  • साथ ही, शिक्षक की सेटिंग में जाकर, सीखने के अनुभव को अपनी पसंद के मुताबिक बनाया जा सकता है.

  • उदाहरण के लिए, वह भाषा चुनें जो आपको सीखनी है. साथ ही, अपनी पसंद के हिसाब से शिक्षक का अवतार चुनें.

  • सचमुच।

  • साथ ही, स्मार्ट ग्लास और फ़ोन मोड के बीच स्विच किया जा सकता है.

  • मैं स्पैनिश में 'ये अंगूर' कैसे कहूं?

  • इसे देखकर, उन स्वादिष्ट अंगूरों को उवास कहा जाता है.

  • स्पैनिश में, इनके बारे में बताने के लिए, "Estas uvas son deliciosas" कहा जा सकता है.

  • मुझे हरे अंगूर पसंद हैं.

  • हमें इसकी समीक्षा करने दें.

  • हरे अंगूरों के बारे में बताने के लिए, "Uvas verdes" कहा जा सकता है.

  • Me gustan las uvas verdes," is a great way to tell someone you like them.

  • इसे फ़्रेंच में कैसे कहते हैं और मैं तीन के लिए कैसे पूछूं?

  • आइए, इस बारे में जानते हैं.

  • स्वादिष्ट दिखने वाली इन पेस्ट्री को डे मैडलीन कहा जाता है.

  • फ़्रेंच में तीन मैडलीन मांगने के लिए, "Je voudrais trois madeleines, s'il vous plaît" कहें.

  • इससे खुले पैसे कैसे मांगूं?

  • चलिए, देखते हैं कि हमारे पास क्या है.

  • बचे हुए पैसे मांगने के लिए, "ओत्सुरी वा अरिमासु का?" कहें

  • इसका मतलब है, "क्या आपके पास खुले पैसे हैं?"

  • "ओत्सुरी ओ ओनेगाइशिमासु" कहकर भी, विनम्रता से बचे हुए पैसे मांगे जा सकते हैं.

  • इसके बाद, आपने जो भी सीखा है वह आपके लिए शब्दावली कार्ड के तौर पर अपने-आप सेव हो जाता है.

  • La botella de agua.

  • Esta es una botella de agua.

  • हां, और स्टडी टैब में जाकर, अपनी याददाश्त की जांच की जा सकती है और प्रैक्टिस की जा सकती है.

  • ठीक है।

  • हाँ।

  • आपने अभी जो कुछ भी देखा वह डिवाइस पर ही चला. इसके लिए, किसी नेटवर्क की ज़रूरत नहीं पड़ी.

  • मैं अंतरराष्ट्रीय डेटा प्लान के साथ यात्रा करती हूं. यह प्लान आम तौर पर तब तक ठीक काम करता है, जब तक मैं किसी मार्केट हॉल में, अंडरग्राउंड या कंक्रीट की मोटी दीवारों के पीछे न जाऊं.

  • अक्सर ऐसा होता है कि जब आपको इंटरनेट की सबसे ज़्यादा ज़रूरत होती है, तब सिग्नल सबसे खराब होता है.

  • मैं यह कहना चाहूंगा कि इंटरनेट कनेक्शन न होने पर काम न करने वाला ऐप्लिकेशन, यात्रा के दौरान काम का नहीं होता. इसलिए, हमने XR Language Teacher को पूरी तरह से ऑफ़लाइन और डिवाइस पर काम करने लायक बनाया है.

डिवाइस पर मौजूद मॉडल को चेन करना

  • तो इसे कैसे बनाया गया?

  • आर्किटेक्चर के हिसाब से, एमी ने आपको पहले ही बता दिया है कि स्मार्ट ग्लास से फ़ोन में प्रोजेक्ट किए गए कैमरा फ़्रेम का इस्तेमाल कैसे किया जाता है.

  • उन्होंने आपको ML Kit का इस्तेमाल करके, बोली को पहचानने और टेक्स्ट को बोली में बदलने का तरीका बताया. साथ ही, ML Kit की मदद से, टेक्स्ट को बोली में बदलने का तरीका भी बताया.

  • हमें अब भी एक ऐसे सिस्टम की ज़रूरत थी जो कैमरे के फ़्रेम और सवाल को एक साथ देख सके. साथ ही, यह समझ सके कि उपयोगकर्ता असल में क्या पूछ रहा है.

  • यह Gemini Nano 4 है, जिसे Gemma 4 के आधार पर बनाया गया है. यह Google का ओपन-सोर्स मॉडल है, जो फ़ोन पर ही काम करता है.

  • इसलिए, इस सुविधा के साथ काम करने वाले Android डिवाइसों पर, सीधे तौर पर ML Kit एपीआई का इस्तेमाल करके, बेहतर परफ़ॉर्मेंस पाई जा सकती है.

  • Android सिस्टम, आपके लिए मॉडल की डिलीवरी का ध्यान रखेगा. इसलिए, आपको अपने ऐप्लिकेशन में कुछ भी बंडल करने की ज़रूरत नहीं है.

  • इन सभी को एक साथ इस्तेमाल करने के लिए, माइक्रोफ़ोन से बोली की पहचान करने वाली सुविधा को डेटा मिलता है. इसके बाद, कैमरे का फ़्रेम और ट्रांसक्रिप्ट, Gemini Nano 4 में जाती है. Gemini Nano 4, टेक्स्ट को बोली में बदलने वाली सुविधा को डेटा भेजता है. इसके बाद, स्पीकर से आवाज़ सुनाई देती है.

  • ये तीनों मॉडल, एक-दूसरे से जुड़े हुए हैं और आपके फ़ोन पर ही काम करते हैं.

  • Gemini Nano 4 इस समस्या को हल करने के लिए सबसे सही क्यों है, इसकी कुछ वजहें यहां दी गई हैं.

  • पहला, यह एक ही बार में टेक्स्ट को देखता और पढ़ता है.

  • ML Kit की मदद से, Gemini Nano 4 टेक्स्ट और इमेज को नेटिव तौर पर हैंडल करता है. इसलिए, आपको डिटेक्टर, क्लासिफ़ायर, और ट्रांसलेटर का इस्तेमाल करने की ज़रूरत नहीं पड़ती.

  • यह एक ऐसा मॉडल है जो कैमरे के फ़्रेम और सवाल को एक साथ देखता है.

  • दूसरा, यह कई भाषाओं में उपलब्ध है.

  • Gemini Nano 4 को 140 से ज़्यादा भाषाओं में ट्रेनिंग दी गई है.

  • साथ ही, भाषा सिखाने वाले ट्यूटर के लिए, सिर्फ़ अनुवाद करना काफ़ी नहीं है.

  • आपको मुहावरे, फ़ॉर्मल और कैज़़ुअल रजिस्टर, और ऐसे उदाहरण वाले वाक्य चाहिए जो कोई असल व्यक्ति बोलता है.

  • आखिर में, इसे इस तरह से कंट्रोल किया जा सकता है कि यह एक अलग पहचान बना सके.

  • तेज़ आवाज़ में उच्चारण की प्रैक्टिस करना मुश्किल हो सकता है.

  • यह मॉडल, सिस्टम प्रॉम्प्ट को अच्छी तरह से फ़ॉलो करता है. इसलिए, उपयोगकर्ता अपनी पसंद के हिसाब से शिक्षक का पर्सोना चुन सकता है.

  • अगर कोई व्यक्ति धैर्य रखने वाला और हौसला बढ़ाने वाला हो, तो लोग ज़्यादा कोशिश कर सकते हैं.

  • डिज़ाइन के बारे में एक और बात है जो मुझे पसंद है.

  • जब ग्लासेस मोड में बातचीत हो रही होती है, तब ऐप्लिकेशन बैकग्राउंड में शब्दावली कार्ड बनाता है.

  • वह शब्द, उसका अनुवाद, उदाहरण के तौर पर दिया गया वाक्य, और सवाल पूछते समय ली गई फ़ोटो.

  • उपयोगकर्ता को मैन्युअल तरीके से कुछ भी टैप करने की ज़रूरत नहीं है.

  • वे बस चल रहे हैं और बात कर रहे हैं.

  • इसके बाद, दिन के आखिर में उन्हें अपने फ़ोन पर सारी जानकारी मिल जाती है. टोक्यो में रहने के दौरान, मुझे भी यही चाहिए था.

  • इसलिए, ऑडियो फ़र्स्ट का मतलब सिर्फ़ ऑडियो नहीं है.

  • स्मार्ट ग्लास, किसी चीज़ के बारे में जानने के लिए सही डिवाइस है. वहीं, फ़ोन उस चीज़ के बारे में ज़्यादा जानकारी पाने के लिए सही डिवाइस है.

  • बोलकर डिवाइस का इस्तेमाल करने की सुविधा से, कुछ खास पलों को यादगार बनाएं.

  • अब हम आपको Gemini Nano 4 और ML Kit की मदद से, रीयल-टाइम में काम करने वाले ऐप्लिकेशन बनाने के कुछ प्रैक्टिकल टिप्स देंगे. ये टिप्स, हमें इस डेमो को बनाने के दौरान मिले हैं.

टू-पास डिज़ाइन की मदद से, रीयल-टाइम लेटेंसी को प्राथमिकता देना

  • पहली सलाह, रीयल-टाइम लेटेंसी को प्राथमिकता देने के लिए, टू-पास डिज़ाइन का इस्तेमाल करें.

  • ऑडियो ग्लास पर, "यह क्या है?" पूछने पर

  • ऑडियो में मौजूद हर पॉज़ पर ध्यान दिया जाता है.

  • एक्सआर लैंग्वेज टीचर के उदाहरण में, हमें उपयोगकर्ता के इंटरैक्शन के हर टर्न के लिए, मॉडल से दो चीज़ों की ज़रूरत होती है: तुरंत दिया गया जवाब और ऐप्लिकेशन में सेव करने के लिए, स्ट्रक्चर्ड वोकैबलरी कार्ड.

  • अगर हम मॉडल से एक ही बार में दो चीज़ें करने के लिए कहते हैं, तो बैकग्राउंड में डेटा जनरेट करने में खर्च होने वाले हर टोकन की वजह से, पहले बोले गए वाक्य में देरी होगी.

  • इसलिए, हम उपयोगकर्ता की मौजूदा ज़रूरत को ऐप्लिकेशन की कुछ सेकंड बाद की ज़रूरत से अलग करते हैं.

  • इसलिए, हमने हर टर्न को दो पास में बांट दिया.

  • पहले पास में, हम कैमरे के फ़्रेम और सवाल को सिर्फ़ बोलकर जवाब देने के लिए स्ट्रीम करते हैं. इससे पहला वाक्य पूरा होते ही, लिखे गए शब्दों को सुनने की सुविधा चालू हो जाती है.

  • टीपीयू या एनपीयू, लिखे गए शब्दों को सुनने की सुविधा के पूरा होने से काफ़ी पहले ही छोटा जवाब जनरेट कर देता है. इस वजह से, हमें कुछ सेकंड की विंडो मिलती है. इसमें उपयोगकर्ता अब भी सुन रहा होता है और चिप पहले से ही कुछ नहीं कर रही होती है.

  • पहले पास ने टेक्स्ट के ज़रिए दिए गए जवाब में ऑब्जेक्ट की पहचान कर ली है. इसलिए, दूसरे पास को इमेज इनपुट की ज़रूरत नहीं है.

  • हम Pass 1 के जवाब को उस खाली चिप में वापस भेज देते हैं, ताकि शिक्षक के बोलने से पहले ही, स्ट्रक्चर्ड कार्ड को निकाला और सेव किया जा सके.

  • अब, चलिए Pass 1 पर ज़ूम इन करते हैं. इससे मुझे दूसरी सलाह देने में मदद मिलेगी.

  • स्ट्रीमिंग के दौरान, कम साइज़ वाले एक्सएमएल टैग इस्तेमाल करें.

  • पहले पास में, टेक्स्ट को सीधे बोली में बदलने की सुविधा का इस्तेमाल किया जाता है. इसलिए, आपको पहले बोले गए शब्द को होल्ड करने के लिए, भारी JSON ऑब्जेक्ट की ज़रूरत नहीं होती.

  • इसके बजाय, आपको ऐसा सादा टेक्स्ट चाहिए जो तुरंत बोला जा सके. इसके लिए, हल्के-फुल्के इनलाइन टैग का इस्तेमाल किया जा सकता है. ऐसा तब किया जाता है, जब ऐप्लिकेशन को स्ट्रीम के बीच में कोई कार्रवाई करनी हो.

  • चलिए, आपको उस समस्या के बारे में बताते हैं जिसकी वजह से हमें यह बदलाव करना पड़ा.

  • क्या आपको लकड़ी से बना कप-ऐंड-बॉल वाला वह खिलौना याद है जिसके बारे में मैंने बताया था?

  • जैपनीज़ में इसे "केंडामा" कहा जाता है.

  • शुरुआत में, मॉडल ने कैमरे के फ़्रेम से इसे पहचाना और सही जवाब दिया, "यह केंडामा है, जो लकड़ी का एक खिलौना है."

  • इसलिए, हमने उस पूरे वाक्य को अंग्रेज़ी में लिखे गए शब्दों को सुनने की सुविधा वाले सेशन में डाला. इसके बाद, हमें यह मिला.

  • यह केन-मी है, जो लकड़ी का एक खिलौना है.

  • यह सही नहीं लग रहा.

  • इसके बजाय, उस वाक्य को इस तरह से बोला जाना चाहिए…

  • यह केंदामा है, जो लकड़ी का एक खिलौना है.

  • तो ऐसा क्यों हुआ?

  • केंडामा को हिरागाना, "केन", और कांजी वर्ण, "डामा" के साथ लिखा जाता है.

  • अंग्रेज़ी में लिखे गए शब्दों को सुनने की सुविधा, "केन" जैसे फ़ोनेटिक हिरागाना को ठीक से हैंडल करती है. हालांकि, कांजी वाले हिस्से पर आते ही यह पूरी तरह से गड़बड़ा जाती है और दामा को कुछ ऐसा बना देती है जो मेरे जैसा लगता है.

  • अगर आपने लोकेल को स्विच नहीं किया, तो अलग-अलग भाषाओं में ऐसा अलग-अलग तरीकों से होता है.

  • उदाहरण के लिए, स्पैनिश में आपको यह सुनाई दे सकता है…

  • स-बो-ल…

  • जब आपको असल में उम्मीद हो…

  • Cebolla.

  • इसी तरह, फ़्रेंच में आपको यह सुनाई दे सकता है…

  • PAIN oh chock-uh-lat…

  • जब आपको असल में उम्मीद हो…

  • पेन ओ शोकोला.

  • हां, टीटीएस सेशन को आम तौर पर एक समय में एक ही भाषा के लिए डिज़ाइन किया जाता है. हालांकि, भाषा सिखाने वाले शिक्षक को हर वाक्य में कोड-स्विच करना पड़ता है.

  • इसलिए, पहले पास में हम मॉडल से कहते हैं कि वह टारगेट वाली भाषा के हर शब्द या वाक्यांश को टारगेट एक्सएमएल टैग के अंदर रैप करे.

  • जैसे ही चंक आते हैं, हमारा क्लाइंट उन्हें टारगेट के हिसाब से बांट देता है. साथ ही, हर स्पैन को लिखे गए शब्दों को सुनने की सुविधा के मैच होने वाले स्थान-भाषा के हिसाब से रूट करता है. यह स्थान-भाषा जैपनीज़, स्पैनिश, फ़्रेंच या आपकी सीखी जा रही कोई भी भाषा हो सकती है. इसके बाद, उन्हें बिना किसी रुकावट के चलाता है. साथ ही, वाक्य के बीच में लहजे को बदलता है, ताकि केंडामा जैसे शब्द सही तरीके से सुनाई दें.

  • इसलिए, यहां ध्यान देने वाली बात यह है कि मॉडल को पहले से ही पता होता है कि कौनसी शब्दावली किस भाषा की है, कौनसे शब्द किस भाषा के हैं, और स्ट्रीमिंग के दौरान टारगेट स्पैन को इनलाइन टैग करना, इस पूरी चीज़ को बाद में खुद प्रोसेस करने से कहीं ज़्यादा आसान है.

  • यहां कोड में पास 1 दिया गया है.

    // 1. Pass 1 System + Turn Prompt (XrLanguageTeacherPersona.kt)
    // System: "Always start immediately with <reply>...</reply> (strictly 1 to 3 sentences total).
    //   Inside <reply>, wrap every Japanese word AND every complete Japanese example sentence
    //   inside <target>...</target> tags (never output <card>)."
    val pass1TurnPrompt = """
      The student is looking at the camera view and asked: "$question". Answer in English
      teaching Japanese inside <reply>...</reply>: if they refer to 'this'/'that' or point to
      an object, ground it to the focal item in the camera frame; if they ask for a phrase or
      greeting, teach that phrase.
    """.trimIndent()
    
    // 2. Stream multimodal dialogue (ImagePart + TextPart) and split <target> tags to TTS
    val generativeModel = Generation.getClient()
    val pass1Request = generateContentRequest(ImagePart(frame), TextPart(pass1TurnPrompt)) {
      temperature = 1.0f; topK = 1; maxOutputTokens = 1024
    }
    generativeModel.generateContentStream(pass1Request).collect { chunk ->
      val delta = chunk.candidates.firstOrNull()?.text.orEmpty()
      streamReplyAndSplitTargetTagsToTts(delta) // Speaks 1st complete sentence immediately
    }
    // Streams: "<reply>That's <target>けん玉</target> — a wooden toy. <target>けん玉をください。</target></reply>"
  • सबसे ऊपर, हम प्रॉम्प्ट का इस्तेमाल करके मॉडल को निर्देश देते हैं कि वह जवाब वाले टैग के अंदर एक से तीन वाक्यों में जवाब दे. इसके बाद, हर जैपनीज़ शब्द या उदाहरण वाले वाक्य को टारगेट टैग के अंदर रैप करे.

  • इसके बाद, हम कैमरे ImagePart और प्रॉम्प्ट TextPart को ML Kit के generateContentStream में पास करते हैं. इससे, हर वाक्य के आने पर, टारगेट स्पैन को टेक्स्ट-टू-स्पीच में बांट दिया जाता है.

  • अब बात करते हैं दूसरे पास और हमारी तीसरी सलाह की.

  • लाइव ऑडियो स्ट्रीम के लिए, लाइटवेट एक्सएमएल टैग का इस्तेमाल करना बेहतर होता है. हालांकि, स्ट्रक्चर्ड आउटपुट का इस्तेमाल करें. इन्हें आपके ऐप्लिकेशन में डेटा सेव करते समय, साफ़ और टाइप किया गया ऑब्जेक्ट दिखाने के लिए बनाया गया है.

  • एक्सआर लैंग्वेज टीचर, बातचीत के ज़रिए सिखाता है. इसलिए, उपयोगकर्ता इससे फ़ॉलो-अप सवाल भी पूछ सकते हैं. हालांकि, इन सवालों के जवाब में कोई नया शब्द नहीं सिखाया जाता.

  • जब कोई शब्द सिखाया जाता है, तो डेटाबेस को शब्दावली कार्ड बनाने के लिए, डिक्शनरी के फ़ील्ड को साफ़ करना पड़ता है.

  • इसलिए, पहले पास की ट्रांसक्रिप्ट को पार्स करने के लिए, मुश्किल रेगुलर एक्सप्रेशन लिखने के बजाय, हम दूसरे पास को बैकग्राउंड में टाइप-सेफ़ ऑब्जेक्ट निकालने की अनुमति देते हैं.

  • दूसरे चरण में स्कीमा को लागू करने के लिए, हम ML Kit के स्ट्रक्चर्ड आउटपुट एपीआई का इस्तेमाल करते हैं. यह एपीआई, बैकग्राउंड में कंस्ट्रेंड डिकोडिंग का इस्तेमाल करता है.

    import com.google.mlkit.genai.prompt.Generation
    import com.google.mlkit.genai.prompt.generateTypedContentRequest
    import com.google.mlkit.genai.schema.annotations.Generable
    import com.google.mlkit.genai.schema.annotations.Guide
    
    // Pass 2 schema (XrLanguageTeacherGenerableSchemas.kt):
    @Generable(description = "Vocabulary flashcard for the taught word or short phrase")
    data class GenerableVocabCard(
      @Guide(description = TeacherResponseSchema.WORD_FIELD_DESCRIPTION) val word: String,
      @Guide(description = "Native-language meaning or translation") val meaning: String,
      @Guide(description = "Target-language example sentence") val example: String,
      @Guide(description = "Native-language translation of the example sentence") val example_translation: String,
    )
    
    @Generable(description = "Optional vocabulary card extracted from a teacher reply")
    data class GenerableOptionalVocabCardWrapper(
      @Guide(description = "Vocabulary flashcard if a vocabulary term was taught, or null otherwise")
      val card: GenerableVocabCard?
    )
  • आपको बस डेटा क्लास को @Generable और हर फ़ील्ड को @Guide से एनोटेट करना होगा. ठीक वैसे ही जैसे यहां दिए गए वोकैबलरी कार्ड क्लास के उदाहरण में किया गया है.

  • साथ ही, नलेबल कार्ड फ़ील्ड को रैप करके, पास 2 नया शब्द सिखाए जाने पर भरा हुआ कार्ड दिखाता है. इसके अलावा, सिर्फ़ बातचीत वाले टर्न पर शून्य दिखाता है.

  • यहां कोड में पास 2 दिया गया है.

    // 1. Pass 1 Streamed Output -> Pass 2 Extraction Prompt (no image needed!)
    val replyWithTargetTags =
      "<reply>That's <target>けん玉</target> — a wooden toy. <target>けん玉をください。</target></reply>"
    
    val pass2Prompt = """
      If the teacher reply below teaches or introduces a specific Japanese vocabulary item, extract
      only its core focal dictionary term into "card" with keys "word", "meaning", "example", and
      "example_translation". If purely conversational with no focal term taught, set "card" to null:
      $replyWithTargetTags
    """.trimIndent()
    
    // 2. Extract @Generable card on idle NPU while TTS audio plays
    val pass2Request = generateContentRequest(TextPart(pass2Prompt)) {
      temperature = 1.0f; topK = 1; maxOutputTokens = 256
    }
    val typedRequest =
      generateTypedContentRequest(pass2Request, GenerableOptionalVocabCardWrapper::class)
    val card: GenerableVocabCard? =
      generativeModel.generateContent(typedRequest).candidates.firstOrNull()?.response?.card
    // Extracts: {"word": "けん玉", "meaning": "a wooden toy", "example": "けん玉をください。", ...}
  • सबसे ऊपर, हम पहले पास के स्ट्रीम किए गए जवाब का टेक्स्ट लेते हैं. इसके लिए, किसी इमेज की ज़रूरत नहीं होती. इसके बाद, हम जानकारी निकालने के लिए प्रॉम्प्ट बनाते हैं.

  • इसके बाद, जब उपयोगकर्ता लिखे गए शब्दों को सुनने की सुविधा का इस्तेमाल कर रहा होता है, तब हम प्रॉम्प्ट और अपनी रैपर क्लास को generateTypedContentRequest में पास करते हैं. साथ ही, टैग-फ़्री वोकैबलरी कार्ड निकालते हैं. अगर कोई शब्द नहीं सिखाया गया है, तो हम null वैल्यू निकालते हैं.

  • ठीक है।

  • हमने कई चीज़ों के बारे में बात की.

  • इस समय यह सोचना सही है कि "बहुत बढ़िया, स्टेज पर एक और ऐसी चीज़ दिख रही है जो बहुत अच्छी है, लेकिन मैं इसे कभी इस्तेमाल नहीं कर पाऊंगा."

  • यह नहीं!

  • XR Language Teacher, Google AI Edge Gallery ऐप्लिकेशन में उपलब्ध है. इसमें डिवाइस पर मौजूद एआई की अन्य सुविधाएं भी शामिल हैं.

  • इसे आज ही डाउनलोड करें और अपने फ़ोन पर इंस्टॉल करें. इसके बाद, किसी भी चीज़ पर कैमरा फ़ोकस करके, यह जानें कि उसे किसी दूसरी भाषा में क्या कहते हैं.

  • अगर आपको यह जानना है कि इसे कैसे बनाया गया है, तो GitHub पर जाएं. वहां इस पूरे सिस्टम को ओपन सोर्स के तौर पर उपलब्ध कराया गया है.

  • अगर आपके सभी उपयोगकर्ताओं के पास ऑडियो या डिसप्ले ग्लास या इस सुविधा के साथ काम करने वाले फ़्लैगशिप Android डिवाइस नहीं हैं, तो चिंता न करें.

  • हमारे कोड बेस में, इस बात के उदाहरण भी दिए गए हैं कि इस अनुभव को सिर्फ़ मोबाइल के लिए कैसे अपनाया जा सकता है.

  • अगर आपको अन्य प्लैटफ़ॉर्म पर भी पहुंचना है, तो Google AI Edge Gallery ऐप्लिकेशन के कोड से आपको यह भी पता चलता है कि Google LiteRT रनटाइम और MediaPipe Tasks API का इस्तेमाल करके, इस सुविधा को कैसे बनाया जाए.

  • इसके अलावा, अगर आपको उपयोगकर्ता के डिवाइस पर मौजूद अन्य ओपन सोर्स ऑडियो या लैंग्वेज मॉडल इस्तेमाल करने हैं, तो कोड की मदद से ऐसा करने का तरीका भी देखा जा सकता है.

एआई एजेंट की मदद से, अन्य कामों को पूरा करना

  • इसलिए, हमने XR Language Teacher को ओपन सोर्स बनाया है, ताकि आपके लिए प्रोटोटाइप बनाना आसान हो सके.

  • अपने पसंदीदा एजेंट को हमारी GitHub रिपॉज़िटरी पर ले जाएं, ताकि डिवाइस पर मौजूद एआई की मदद से काम करने वाले इस लाइव अनुभव को किसी और चीज़ में बदला जा सके.

  • यह म्यूज़ियम गाइड, कुकिंग असिस्टेंट, रिपेयर वॉकथ्रू, सुलभता नरेटर, फ़ील्ड इंस्पेक्शन टूल वगैरह हो सकता है.

  • मॉडल, रनटाइम, ओपन-सोर्स इंप्लिमेंटेशन, और टूल अब उपलब्ध हैं, ताकि आप इस साल के अंत में लॉन्च होने वाले इंटेलिजेंट आईवियर के लिए तैयार हो जाएं.

  • हमें यह देखने में खुशी होगी कि आपने इस सुविधा का इस्तेमाल करके क्या बनाया है.

  • आखिर में, आज हमने आपको कुछ बेहतरीन उदाहरण दिखाए कि उपयोगकर्ता के डिवाइस पर आसानी से काम करने वाले एआई मॉडल से क्या-क्या किया जा सकता है.

  • यहां कुछ तरीके दिए गए हैं, जिनसे शुरुआत की जा सकती है.

  • सबसे पहले, स्क्रीन पर मौजूद संसाधन इकट्ठा करें.

  • डेमो आज़माने के लिए, AI Edge Gallery ऐप्लिकेशन डाउनलोड करें. साथ ही, GitHub पर रेफ़रंस कोड देखें.

  • Android XR SDK, ML Kit API, और Google AI Edge के ऑफ़र ऐक्सेस करने के लिए, क्यूआर कोड स्कैन करें.

  • दूसरा, आज ही अपने फ़ोन पर एक्सपेरिमेंट करना शुरू करें.

  • हमने ऐसी कई चीज़ों के बारे में बताया है जिन्हें मोबाइल-फ़र्स्ट अनुभव के साथ पहले से ही बनाया जा सकता है.

  • तीसरा, अपने मौजूदा मोबाइल ऐप्लिकेशन को देखें और खुद से पूछें कि इसकी कौनसी मुख्य सुविधाएं, बोलकर इस्तेमाल करने पर बेहतर अनुभव देंगी?

  • अपने मौजूदा APK में Projected Activity जोड़कर, स्मार्ट ग्लास पर भी यह अनुभव पाया जा सकता है.

  • आज के सेशन में शामिल होने के लिए, आप सभी का बहुत-बहुत शुक्रिया.

  • हम यह देखने के लिए बेताब हैं कि Android और इंटेलिजेंट आईवियर के लिए, ऑडियो-फ़र्स्ट अनुभव देने वाले कौनसे बेहतरीन ऐप्लिकेशन बनाए जाएंगे.

  • धन्यवाद.

कोड

कोड स्निपेट

"Android XR के लिए ऐप्लिकेशन बनाना" वीडियो में 02:39 पर Kotlin स्निपेट
dependencies {
   implementation("androidx.xr.projected:projected:1.0.0-alpha13")
}
"Android XR के लिए ऐप्लिकेशन बनाना" वीडियो में 02:45 पर Kotlin स्निपेट
class ProjectedMainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContent {
           // Glasses content
       }
   }
}
"Building for Android XR" में 03:02 पर एक्सएमएल स्निपेट
<activity
   android:name=".ProjectedMainActivity"
   android:exported="false"
   android:requiredDisplayCategory="android.hardware.display.category.XR_PROJECTED"
   android:label="Example activity for audio glasses">
   <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.XR_PROJECTED_LAUNCHER"/>
   </intent-filter>
</activity>
"Android XR के लिए ऐप्लिकेशन बनाना" में 03:44 पर Kotlin स्निपेट
// Continuously monitor whether the glasses are connected
val isGlassesConnected by ProjectedContext.isProjectedDeviceConnected(
   context,
   scope.coroutineContext
).collectAsStateWithLifecycle(initialValue = false)

// Launch the activity
val options = ProjectedContext.createProjectedActivityOptions(context)
val intent = Intent(context, ProjectedMainActivity::class.java)
context.startActivity(intent, options.toBundle())

// Check if the device is audio only or has a display
val projectedDeviceController = ProjectedDeviceController.create(this@ProjectedMainActivity)
isVisualUiSupported = projectedDeviceController.capabilities.contains(CAPABILITY_VISUAL_UI)
"Android XR के लिए ऐप्लिकेशन बनाना" में 05:05 पर Kotlin स्निपेट
// In a projected activity
private fun requestProjectedPermissions() {
   lifecycleScope.launch {
       try {
           ProjectedActivityCompat.requestPermissions(
               this@PermissionsFromProjectedActivity,
               arrayOf(Manifest.permission.CAMERA),
               // CAMERA_PERMISSION_REQUEST_CODE is a developer defined constant
               requestCode = CAMERA_PERMISSION_REQUEST_CODE,
           )
       } catch (e: IllegalStateException) {
           // Thrown when the projected system service can't be bound.
           Log.e(TAG, "Request failed: projected service unavailable.", e)
       }
   }
}
"Android XR के लिए ऐप्लिकेशन बनाना" वीडियो में 05:46 पर शेल स्निपेट
android skills add projected-hardware
android skills add --all
"Designing audio-first experiences" में 08:14 पर Kotlin स्निपेट
dependencies {
   // ML Kit GenAI TTS SDK
   implementation("com.google.mlkit:genai-text-to-speech:1.0.0-alpha1")
}
"Designing audio-first experiences" में 08:26 पर Kotlin स्निपेट
// 1. Initializing the SpeechSynthesizer client.
val options = SpeechSynthesizerOptions.Builder(Locale.US).build()
val client = SpeechSynthesis.getClient(options)

// 2. Check and download the voice model.
val voiceInfo = client.getSupportedVoices().firstOrNull()

if (voiceInfo != null && client.checkStatus(voiceInfo) == FeatureStatus.DOWNLOADABLE) {
   client.download(voiceInfo).collect { status -> println("Download status: $status") }
} else if (voiceInfo == null) {
   // Tip: Fallback to system TTS if ML Kit voice is unavailable
}
"Designing audio-first experiences" में 09:26 पर Kotlin स्निपेट
// 3. Construct the SpeechSynthesizerRequest
val request = SpeechSynthesizerRequest(
   input = SpeechSynthesizerRequest.Input.Text("Hello world", voiceInfo),
   audioAttributes = AudioAttributes.Builder()
       .setUsage(AudioAttributes.USAGE_MEDIA)
       .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
       .build()
)

// 4. Speak and collect status
client.synthesize(request).collect { response ->
   when (response) {
       is SpeechSynthesizerResponse.StatusUpdate -> println("Playback status: ${response.status}")
   }
}
"ऑडियो-फ़र्स्ट अनुभव डिज़ाइन करना" में 09:47 पर Kotlin स्निपेट
// 4. Speak and collect status
client.synthesize(request).collect { response ->
   when (response) {
       is SpeechSynthesizerResponse.StatusUpdate -> println("Playback status: ${response.status}")
   }
}

// 5. Release resources when finished (e.g., on Activity destroy)
override fun onDestroy() {
   super.onDestroy()
   client.close()
}
"Designing audio-first experiences" में 10:29 पर Kotlin स्निपेट
// 1. Register Earcon resource with Builder
SpeechSynthesizerOptions.Builder(Locale.US)
   .addEarcon(
       name = "shutter_sound",
       Uri = "path/to/earcon.file".toUri()
   )
   .build()

// 2. Request Earcon playback
val request = SpeechSynthesizerRequest(
   input = SpeechSynthesizerRequest.Input.Earcon(
       name = "shutter_sound"
   ),
   audioAttributes = AudioAttributes.Builder()
       .setUsage(AudioAttributes
           .USAGE_ASSISTANCE_SONIFICATION)
       .setContentType(AudioAttributes
           .CONTENT_TYPE_SONIFICATION)
       .build()
)
"Designing audio-first experiences" में 13:42 पर Kotlin स्निपेट
dependencies {
   // ML Kit Speech Recognition
   implementation("com.google.mlkit:genai-speech-recognition:1.0.0-alpha1")
}
"Designing audio-first experiences" में 13:52 पर Kotlin स्निपेट
suspend fun startMyRecognition() {
   // choose locale and mode
   val options: SpeechRecognizerOptions =
       speechRecognizerOptions {
           locale = Locale.US
           preferredMode = SpeechRecognizerOptions.Mode.MODE_ADVANCED
       }

   val speechRecognizer: SpeechRecognizer = SpeechRecognition.getClient(options)

   val request: SpeechRecognizerRequest =
       speechRecognizerRequest { audioSource = AudioSource.fromMic() }
...
"Designing audio-first experiences" में 14:12 पर Kotlin स्निपेट
speechRecognizer.startRecognition(request).collect { response ->
   when (response) {
       is SpeechRecognizerResponse.PartialTextResponse -> {
           // Real-time: Act immediately if trigger phrase is heard
           handleResponse(response.text, speechRecognizer)
       }
       is SpeechRecognizerResponse.FinalTextResponse -> {
           // Final result and recognition
           handleResponse(response.text, speechRecognizer)
       }
       is SpeechRecognizerResponse.CompletedResponse -> {
           resetListeningUi()
       }
       is SpeechRecognizerResponse.ErrorResponse -> {
           Log.e("SpeechRec", "Error: ${response.e.errorCode}", response.e)
           resetListeningUi()
       }
...
"Designing audio-first experiences" में 14:41 पर Kotlin स्निपेट
// Helper function to check for multiple phrases and trigger the right action
private suspend fun handleResponse(text: String, recognizer: SpeechRecognizer) {
   val savePhrases = listOf("save", "bookmark", "remember")
   if (savePhrases.any { text.contains(it) }) {

       // 1. Update app state immediately
       saveItemForLater()

       // 2. Stop the recognizer to enforce the action and prevent TTS echo
       recognizer.stopRecognition()

       // 3. Play the mute earcon for immediate, non-verbal confirmation
       playEarcon()

       // 4. Provide voice feedback
       playAudioFeedback("Saved")
   }
}
"दो-पास डिज़ाइन की मदद से रीयल-टाइम लेटेंसी को प्राथमिकता देना" में 26:27 पर Kotlin स्निपेट
// 1. Pass 1 System + Turn Prompt (XrLanguageTeacherPersona.kt)
// System: "Always start immediately with <reply>...</reply> (strictly 1 to 3 sentences total).
//   Inside <reply>, wrap every Japanese word AND every complete Japanese example sentence
//   inside <target>...</target> tags (never output <card>)."
val pass1TurnPrompt = """
  The student is looking at the camera view and asked: "$question". Answer in English
  teaching Japanese inside <reply>...</reply>: if they refer to 'this'/'that' or point to
  an object, ground it to the focal item in the camera frame; if they ask for a phrase or
  greeting, teach that phrase.
""".trimIndent()

// 2. Stream multimodal dialogue (ImagePart + TextPart) and split <target> tags to TTS
val generativeModel = Generation.getClient()
val pass1Request = generateContentRequest(ImagePart(frame), TextPart(pass1TurnPrompt)) {
  temperature = 1.0f; topK = 1; maxOutputTokens = 1024
}
generativeModel.generateContentStream(pass1Request).collect { chunk ->
  val delta = chunk.candidates.firstOrNull()?.text.orEmpty()
  streamReplyAndSplitTargetTagsToTts(delta) // Speaks 1st complete sentence immediately
}
// Streams: "<reply>That's <target>けん玉</target> — a wooden toy. <target>けん玉をください。</target></reply>"
"दो-पास डिज़ाइन की मदद से रीयल-टाइम लेटेंसी को प्राथमिकता देना" में 27:33 पर Kotlin स्निपेट
import com.google.mlkit.genai.prompt.Generation
import com.google.mlkit.genai.prompt.generateTypedContentRequest
import com.google.mlkit.genai.schema.annotations.Generable
import com.google.mlkit.genai.schema.annotations.Guide

// Pass 2 schema (XrLanguageTeacherGenerableSchemas.kt):
@Generable(description = "Vocabulary flashcard for the taught word or short phrase")
data class GenerableVocabCard(
  @Guide(description = TeacherResponseSchema.WORD_FIELD_DESCRIPTION) val word: String,
  @Guide(description = "Native-language meaning or translation") val meaning: String,
  @Guide(description = "Target-language example sentence") val example: String,
  @Guide(description = "Native-language translation of the example sentence") val example_translation: String,
)

@Generable(description = "Optional vocabulary card extracted from a teacher reply")
data class GenerableOptionalVocabCardWrapper(
  @Guide(description = "Vocabulary flashcard if a vocabulary term was taught, or null otherwise")
  val card: GenerableVocabCard?
)
"टू-पास डिज़ाइन की मदद से रीयल-टाइम लेटेंसी को प्राथमिकता देना" में 28:00 पर Kotlin स्निपेट
// 1. Pass 1 Streamed Output -> Pass 2 Extraction Prompt (no image needed!)
val replyWithTargetTags =
  "<reply>That's <target>けん玉</target> — a wooden toy. <target>けん玉をください。</target></reply>"

val pass2Prompt = """
  If the teacher reply below teaches or introduces a specific Japanese vocabulary item, extract
  only its core focal dictionary term into "card" with keys "word", "meaning", "example", and
  "example_translation". If purely conversational with no focal term taught, set "card" to null:
  $replyWithTargetTags
""".trimIndent()

// 2. Extract @Generable card on idle NPU while TTS audio plays
val pass2Request = generateContentRequest(TextPart(pass2Prompt)) {
  temperature = 1.0f; topK = 1; maxOutputTokens = 256
}
val typedRequest =
  generateTypedContentRequest(pass2Request, GenerableOptionalVocabCardWrapper::class)
val card: GenerableVocabCard? =
  generativeModel.generateContent(typedRequest).candidates.firstOrNull()?.response?.card
// Extracts: {"word": "けん玉", "meaning": "a wooden toy", "example": "けん玉をください。", ...}