मुफ़्त APK बनाएँ

JavaScript ब्रिज API

टेक्स्ट टू स्पीच

डिवाइस की आवाज़ें, पेज से बोली जाती हैं।

SpeechRecognition वेब स्टैंडर्ड#

webkitSpeechRecognition / SpeechRecognition — speech to text

उदाहरण

डिक्टेशन के लिए मानक Web Speech API: यूज़र बोलता है, पेज को टेक्स्ट मिलता है। Android पर Chrome में यह है और Android के WebView में नहीं, इसलिए ऐप इसे Android के अपने स्पीच रिकग्नाइज़र पर उपलब्ध कराता है। Chrome के लिए लिखा कोड बिना बदलाव चलता है।

लौटाता है: start() सुनना शुरू करता है; result इवेंट event.results[i][0].transcript ले जाते हैं (और .confidence, .isFinal); error इवेंट event.error ले जाते हैं (not-allowed, no-speech, audio-capture, network, aborted, language-not-supported, service-not-allowed); end हमेशा आखिर में आता है। ज़रूरी: माइक्रोफ़ोन। जब आपका कोड SpeechRecognition का ज़िक्र करता है तो बिल्ड इसे अपने-आप चालू कर देता है, और start() पहली बार चलने पर Android यूज़र से पूछता है।

<button id="mic">Dictate</button>
<textarea id="note"></textarea>
<script>
const Rec = window.SpeechRecognition || window.webkitSpeechRecognition;
const mic = document.getElementById('mic');
if (!Rec) {
  mic.hidden = true;                       // no speech recogniser on this phone
} else {
  mic.addEventListener('click', () => {
    const rec = new Rec();
    rec.lang = 'en-IN';                    // leave empty for the page / phone language
    rec.interimResults = true;             // live text while the user speaks
    rec.onresult = (e) => {
      let text = '';
      for (const r of e.results) text += r[0].transcript;
      document.getElementById('note').value = text;
    };
    rec.onerror = (e) => {
      if (e.error === 'not-allowed') alert('Allow the microphone to dictate.');
    };
    rec.onend = () => { mic.disabled = false; };
    mic.disabled = true;
    rec.start();
  });
}
</script>

लगातार डिक्टेशन जो माँगने पर रुकता है और हर त्रुटि रिपोर्ट करता है:

const Rec = window.SpeechRecognition || window.webkitSpeechRecognition;
let rec = null;
function toggleDictation() {
  if (!Rec) return showMessage('Voice typing is not available on this phone.');
  if (rec) { rec.stop(); return; }                   // stop() delivers what was heard
  rec = new Rec();
  rec.continuous = true;
  rec.onresult = (e) => {
    for (let i = e.resultIndex; i < e.results.length; i++) {
      if (e.results[i].isFinal) appendToNote(e.results[i][0].transcript);
    }
  };
  rec.onerror = (e) => {
    const msg = { 'not-allowed': 'Allow the microphone first.', 'no-speech': 'Nothing was heard.',
                  'audio-capture': 'No microphone found.', 'network': 'Speech service unreachable.' }[e.error];
    if (msg) showMessage(msg);
  };
  rec.onend = () => { rec = null; };
  rec.start();
}

फ़ोन की भाषा में कमांड बोलें और उस पर काम करें:

const Rec = window.SpeechRecognition || window.webkitSpeechRecognition;
function listenForCommand() {
  if (!Rec) return;
  const rec = new Rec();
  rec.lang = navigator.language;
  rec.onresult = (e) => {
    const said = e.results[0][0].transcript.toLowerCase();
    if (said.includes('next')) goNext();
    else if (said.includes('back')) goBack();
    else showMessage('Heard: ' + said);
  };
  rec.onerror = (e) => {
    if (e.error === 'language-not-supported') showMessage('This language is not supported here.');
  };
  rec.start();
}

ध्यान दें: continuous = true वाक्यों के पार तब तक सुनता रहता है जब तक आप stop() कॉल न करें; तीन चुप दौरों के बाद यह no-speech के साथ खत्म हो जाता है, ताकि भूला हुआ रिकग्नाइज़र हमेशा न सुनता रहे। stop() जो सुना वह देता है; abort() उसे छोड़ देता है। ऐप के बैकग्राउंड में जाने पर रिकग्निशन रुक जाती है, जैसे Chrome टैब छिपने पर रुकती है। सिर्फ़ ऐप के अपने पेज (उसकी अपनी फ़ाइलें, या क्रिएटर की वेबसाइट) इस तरह माइक्रोफ़ोन इस्तेमाल कर सकते हैं; कोई दूसरी साइट not-allowed पाती है। फ़ोन में स्पीच रिकग्निशन सर्विस न हो तो API नहीं होता, इसलिए ऊपर की तरह जाँचें। अंदरूनी ट्रांसपोर्ट: __srStart, __srStop, __srAbort, __srAvailable; नतीजे appmint:sr के रूप में आते हैं। AI से बने ऐप speech.start() इस्तेमाल करते हैं, @/lib/appmintNative.

speechSynthesis वेब स्टैंडर्ड#

window.speechSynthesis + SpeechSynthesisUtterance

उदाहरण

सामान्य Web Speech API से फ़ोन के अपने टेक्स्ट-टू-स्पीच इंजन के ज़रिए टेक्स्ट ज़ोर से पढ़ता है।

लौटाता है: speechSynthesis.speak(u) कुछ नहीं लौटाता; utterance के start / boundary / end / error / pause / resume इवेंट (onstart … प्रॉपर्टी या addEventListener से) बताते हैं कि क्या हुआ। getVoices() तुरंत { voiceURI, name, lang, localService, default } का ऐरे लौटाता है। ज़रूरी: कुछ नहीं। Android WebView में अपना कोई चलने वाला स्पीच API नहीं है; ऐप इसे हर फ़्रेम में डॉक्यूमेंट शुरू होते ही इंस्टॉल करता है।

एक वाक्य बोलें और जानें कि वह कब पूरा हुआ:

function say(text) {
  if (!('speechSynthesis' in window)) { alert('Speech is not available here'); return; }
  var u = new SpeechSynthesisUtterance(text);
  u.lang = 'en-US';   // BCP-47 tag: 'ta-IN', 'hi-IN', 'fr-FR' ...
  u.rate = 1.2;       // 0.1 .. 4 (1 = normal)
  u.pitch = 1;        // 0.1 .. 4 (1 = normal)
  u.onstart = function () { document.body.classList.add('speaking'); };
  u.onend = function () { document.body.classList.remove('speaking'); };
  u.onerror = function (e) {
    document.body.classList.remove('speaking');
    console.log('Speech failed:', e.error);   // 'synthesis-failed'
  };
  speechSynthesis.speak(u);   // queues after anything already speaking
}

document.getElementById('stop').onclick = function () {
  if ('speechSynthesis' in window) speechSynthesis.cancel();   // stops now, clears the queue
};

आवाज़ें शुरू होने के थोड़ी देर बाद आती हैं। voiceschanged चलने पर उन्हें फिर से पढ़ें:

var voices = [];
function loadVoices() {
  voices = speechSynthesis.getVoices();   // [] until the engine is ready
  var tamil = voices.filter(function (v) { return v.lang.indexOf('ta') === 0; });
  document.getElementById('tamil-btn').hidden = tamil.length === 0;
}
if ('speechSynthesis' in window) {
  loadVoices();
  speechSynthesis.addEventListener('voiceschanged', loadVoices);
}

function sayWithVoice(text, voice) {
  var u = new SpeechSynthesisUtterance(text);
  u.voice = voice;           // a voice from getVoices(): that exact voice is used
  u.volume = 0.8;            // 0 .. 1
  speechSynthesis.speak(u);
}

एक आर्टिकल रीडर जिसमें एक Pause / Resume बटन है और जो पढ़े जा रहे पैराग्राफ़ को हाइलाइट करता है:

var toggle = document.getElementById('pause-toggle');

toggle.onclick = function () {
  if (!('speechSynthesis' in window) || !speechSynthesis.speaking) return;
  if (speechSynthesis.paused) speechSynthesis.resume();   // continues from the last word
  else speechSynthesis.pause();
};

function readArticle() {
  if (!('speechSynthesis' in window)) return;
  speechSynthesis.cancel();                               // start over
  document.querySelectorAll('article p').forEach(function (p) {
    var u = new SpeechSynthesisUtterance(p.textContent);
    u.onstart = function () { p.classList.add('reading'); };
    u.onend = u.onerror = function () { p.classList.remove('reading'); };
    u.onpause = function () { toggle.textContent = 'Resume'; };
    u.onresume = function () { toggle.textContent = 'Pause'; };
    speechSynthesis.speak(u);                             // paragraphs queue in order
  });
  toggle.textContent = 'Pause';
}

ध्यान दें:

  • volume (0-1), voice (getVoices() की ठीक वही आवाज़), rate, pitch और lang सब फ़ोन के इंजन तक पहुँचते हैं। voice और lang दोनों हों तो आवाज़ को प्राथमिकता मिलती है; दोनों न हों तो इंजन की डिफ़ॉल्ट आवाज़ बोलती है।
  • boundary हर शब्द से पहले charIndex / charLength के साथ चलता है (Android 8+; जो इंजन शब्दों की स्थिति नहीं बताते वे कुछ नहीं भेजते)।
  • pause() / resume(): Android का इंजन शब्द के बीच में नहीं रुक सकता, इसलिए pause() उसे रोक देता है और resume() वाक्य का बाकी हिस्सा उस आखिरी शब्द से बोलता है जो इंजन ने बताया (pause / resume इवेंट चलते हैं)। जो इंजन शब्दों की स्थिति नहीं बताता, वहाँ resume() उस utterance को शुरू से फिर बोलता है। रुके रहने के दौरान speaking true रहता है; कतार वाले utterance इंतज़ार करें तो pending true होता है।
  • cancel() जो utterance बोला जा रहा है उस पर error: 'interrupted' के साथ error और कतार वालों पर 'canceled' चलाता है, जैसा मानक कहता है - इन्हें फ़ेल होना न दिखाएँ।
  • अगर फ़ोन में उस भाषा का वॉइस डेटा नहीं है, तो इंजन फिर भी अपनी डिफ़ॉल्ट भाषा में बोल सकता है। पहले उस भाषा के लिए getVoices() जाँचें।
  • इसके पीछे के कच्चे इवेंट appmint:tts हैं (देखें ttsSpeak)। इस API को इस्तेमाल करने पर आपको उनकी ज़रूरत नहीं।

__srAbort ब्रिज#

window.WebToApk.__srAbort(id: String)

SpeechRecognition.abort(): तुरंत रुकें, छोड़ दें।

उदाहरण

WebToApk.__srStart के साथ दस्तावेज़ित - वहाँ का उदाहरण इसे भी दिखाता है।

webkitSpeechRecognition / SpeechRecognition के पीछे का अंदरूनी ट्रांसपोर्ट (स्टार्ट, स्टॉप, अबॉर्ट, और फ़ोन पर रिकग्नाइज़र है या नहीं)। पेज मानक API इस्तेमाल करते हैं; इन्हें सीधे कभी कॉल न करें, क्योंकि __ मेथड बिना सूचना बदल सकते हैं।

लौटाता है: __srStart(id, options) सुनना शुरू होने पर "" लौटाता है, या Web Speech त्रुटि का नाम (not-allowed, service-not-allowed)। उसके बाद सब कुछ appmint:sr इवेंट के रूप में आता है: start/audiostart/speechstart/speechend/audioend/end के लिए {id, type}, {id, type:'result', final, alternatives:[{transcript, confidence}]}, और {id, type:'error', error}। ज़रूरी: माइक्रोफ़ोन (कॉल के रूप से अपने-आप चालू)।

पब्लिक API इस्तेमाल करें:

const rec = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
rec.onresult = (e) => console.log(e.results[0][0].transcript);
rec.start();

लाइव टेक्स्ट और भाषा के साथ लगातार डिक्टेशन:

const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
if (SR) {
  const rec = new SR();
  rec.lang = 'en-US';
  rec.continuous = true;
  rec.interimResults = true;
  rec.onresult = (e) => {
    const r = e.results[e.results.length - 1];
    note.value = r[0].transcript + (r.isFinal ? '\n' : '');
  };
  micBtn.onclick = () => rec.start();
  stopBtn.onclick = () => rec.stop();
}

माइक्रोफ़ोन मना किए जाने जैसी त्रुटियाँ रिपोर्ट करें:

rec.onerror = (e) => {
  if (e.error === 'not-allowed' || e.error === 'service-not-allowed') showMessage('Allow the microphone to dictate.');
  else showMessage('Speech error: ' + e.error);
};
rec.onend = () => micBtn.classList.remove('live');

ध्यान दें: ऐप शेल (SpeechRecognitionBridge.kt) में Android के SpeechRecognizer पर बना है। जो पेज ऐप के नहीं हैं उनके लिए __srStart मना कर दिया जाता है।

__srAvailable ब्रिज#

window.WebToApk.__srAvailable(): Boolean

स्पीच रिकग्निशन सर्विस इंस्टॉल है या नहीं (webkitSpeechRecognition सिर्फ़ तभी मौजूद होता है)।

उदाहरण

WebToApk.__srStart के साथ दस्तावेज़ित - वहाँ का उदाहरण इसे भी दिखाता है।

webkitSpeechRecognition / SpeechRecognition के पीछे का अंदरूनी ट्रांसपोर्ट (स्टार्ट, स्टॉप, अबॉर्ट, और फ़ोन पर रिकग्नाइज़र है या नहीं)। पेज मानक API इस्तेमाल करते हैं; इन्हें सीधे कभी कॉल न करें, क्योंकि __ मेथड बिना सूचना बदल सकते हैं।

लौटाता है: __srStart(id, options) सुनना शुरू होने पर "" लौटाता है, या Web Speech त्रुटि का नाम (not-allowed, service-not-allowed)। उसके बाद सब कुछ appmint:sr इवेंट के रूप में आता है: start/audiostart/speechstart/speechend/audioend/end के लिए {id, type}, {id, type:'result', final, alternatives:[{transcript, confidence}]}, और {id, type:'error', error}। ज़रूरी: माइक्रोफ़ोन (कॉल के रूप से अपने-आप चालू)।

पब्लिक API इस्तेमाल करें:

const rec = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
rec.onresult = (e) => console.log(e.results[0][0].transcript);
rec.start();

लाइव टेक्स्ट और भाषा के साथ लगातार डिक्टेशन:

const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
if (SR) {
  const rec = new SR();
  rec.lang = 'en-US';
  rec.continuous = true;
  rec.interimResults = true;
  rec.onresult = (e) => {
    const r = e.results[e.results.length - 1];
    note.value = r[0].transcript + (r.isFinal ? '\n' : '');
  };
  micBtn.onclick = () => rec.start();
  stopBtn.onclick = () => rec.stop();
}

माइक्रोफ़ोन मना किए जाने जैसी त्रुटियाँ रिपोर्ट करें:

rec.onerror = (e) => {
  if (e.error === 'not-allowed' || e.error === 'service-not-allowed') showMessage('Allow the microphone to dictate.');
  else showMessage('Speech error: ' + e.error);
};
rec.onend = () => micBtn.classList.remove('live');

ध्यान दें: ऐप शेल (SpeechRecognitionBridge.kt) में Android के SpeechRecognizer पर बना है। जो पेज ऐप के नहीं हैं उनके लिए __srStart मना कर दिया जाता है।

__srStart ब्रिज#

window.WebToApk.__srStart(id: String, optionsJson: String): String

SpeechRecognition.start(): शुरू होने पर "" (इवेंट `appmint:sr` के रूप में आते हैं), वरना Web Speech त्रुटि का नाम। ऑरिजिन-गेटेड: यूज़र जो बोलता है वह यूज़र का डेटा है।

उदाहरण

webkitSpeechRecognition / SpeechRecognition के पीछे का अंदरूनी ट्रांसपोर्ट (स्टार्ट, स्टॉप, अबॉर्ट, और फ़ोन पर रिकग्नाइज़र है या नहीं)। पेज मानक API इस्तेमाल करते हैं; इन्हें सीधे कभी कॉल न करें, क्योंकि __ मेथड बिना सूचना बदल सकते हैं।

लौटाता है: __srStart(id, options) सुनना शुरू होने पर "" लौटाता है, या Web Speech त्रुटि का नाम (not-allowed, service-not-allowed)। उसके बाद सब कुछ appmint:sr इवेंट के रूप में आता है: start/audiostart/speechstart/speechend/audioend/end के लिए {id, type}, {id, type:'result', final, alternatives:[{transcript, confidence}]}, और {id, type:'error', error}। ज़रूरी: माइक्रोफ़ोन (कॉल के रूप से अपने-आप चालू)।

पब्लिक API इस्तेमाल करें:

const rec = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
rec.onresult = (e) => console.log(e.results[0][0].transcript);
rec.start();

लाइव टेक्स्ट और भाषा के साथ लगातार डिक्टेशन:

const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
if (SR) {
  const rec = new SR();
  rec.lang = 'en-US';
  rec.continuous = true;
  rec.interimResults = true;
  rec.onresult = (e) => {
    const r = e.results[e.results.length - 1];
    note.value = r[0].transcript + (r.isFinal ? '\n' : '');
  };
  micBtn.onclick = () => rec.start();
  stopBtn.onclick = () => rec.stop();
}

माइक्रोफ़ोन मना किए जाने जैसी त्रुटियाँ रिपोर्ट करें:

rec.onerror = (e) => {
  if (e.error === 'not-allowed' || e.error === 'service-not-allowed') showMessage('Allow the microphone to dictate.');
  else showMessage('Speech error: ' + e.error);
};
rec.onend = () => micBtn.classList.remove('live');

ध्यान दें: ऐप शेल (SpeechRecognitionBridge.kt) में Android के SpeechRecognizer पर बना है। जो पेज ऐप के नहीं हैं उनके लिए __srStart मना कर दिया जाता है।

__srStop ब्रिज#

window.WebToApk.__srStop(id: String)

SpeechRecognition.stop(): सुनना बंद करें, जो सुना वह दे दें।

उदाहरण

WebToApk.__srStart के साथ दस्तावेज़ित - वहाँ का उदाहरण इसे भी दिखाता है।

webkitSpeechRecognition / SpeechRecognition के पीछे का अंदरूनी ट्रांसपोर्ट (स्टार्ट, स्टॉप, अबॉर्ट, और फ़ोन पर रिकग्नाइज़र है या नहीं)। पेज मानक API इस्तेमाल करते हैं; इन्हें सीधे कभी कॉल न करें, क्योंकि __ मेथड बिना सूचना बदल सकते हैं।

लौटाता है: __srStart(id, options) सुनना शुरू होने पर "" लौटाता है, या Web Speech त्रुटि का नाम (not-allowed, service-not-allowed)। उसके बाद सब कुछ appmint:sr इवेंट के रूप में आता है: start/audiostart/speechstart/speechend/audioend/end के लिए {id, type}, {id, type:'result', final, alternatives:[{transcript, confidence}]}, और {id, type:'error', error}। ज़रूरी: माइक्रोफ़ोन (कॉल के रूप से अपने-आप चालू)।

पब्लिक API इस्तेमाल करें:

const rec = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
rec.onresult = (e) => console.log(e.results[0][0].transcript);
rec.start();

लाइव टेक्स्ट और भाषा के साथ लगातार डिक्टेशन:

const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
if (SR) {
  const rec = new SR();
  rec.lang = 'en-US';
  rec.continuous = true;
  rec.interimResults = true;
  rec.onresult = (e) => {
    const r = e.results[e.results.length - 1];
    note.value = r[0].transcript + (r.isFinal ? '\n' : '');
  };
  micBtn.onclick = () => rec.start();
  stopBtn.onclick = () => rec.stop();
}

माइक्रोफ़ोन मना किए जाने जैसी त्रुटियाँ रिपोर्ट करें:

rec.onerror = (e) => {
  if (e.error === 'not-allowed' || e.error === 'service-not-allowed') showMessage('Allow the microphone to dictate.');
  else showMessage('Speech error: ' + e.error);
};
rec.onend = () => micBtn.classList.remove('live');

ध्यान दें: ऐप शेल (SpeechRecognitionBridge.kt) में Android के SpeechRecognizer पर बना है। जो पेज ऐप के नहीं हैं उनके लिए __srStart मना कर दिया जाता है।

__ttsSpeak ब्रिज#

window.WebToApk.__ttsSpeak(json: String)

speechSynthesis पॉलीफ़िल का पूरा speak: `{text, lang, rate, pitch, volume (0-1), voice (getVoices() का नाम, या ''), id}`। [ttsSpeak] उन पेजों के लिए रहता है जो ब्रिज को सीधे कॉल करते हैं; उसमें volume या voice नहीं है।

उदाहरण

speechSynthesis.speak(utterance) के पीछे का अंदरूनी ट्रांसपोर्ट: पूरा utterance - टेक्स्ट, भाषा, rate, pitch, volume और चुनी हुई आवाज़ - एक JSON स्ट्रिंग के रूप में। पेज मानक speechSynthesis API इस्तेमाल करते हैं; इसे सीधे कभी कॉल न करें।

लौटाता है: कुछ नहीं। प्रगति appmint:tts इवेंट के रूप में आती है, जिन्हें speechSynthesis लेयर utterance के start / boundary / end / error इवेंट में बदल देती है। ज़रूरी: कुछ नहीं।

यह जिस मानक API को ढोता है:

function readAloud(text) {
  if (!('speechSynthesis' in window)) return;
  var voice = speechSynthesis.getVoices().filter(function (v) { return v.lang === 'en-GB'; })[0];
  var u = new SpeechSynthesisUtterance(text);
  if (voice) u.voice = voice;   // that exact voice
  u.volume = 0.6;               // 0 .. 1
  u.addEventListener('boundary', function (e) { highlightWordAt(e.charIndex, e.charLength); });
  u.addEventListener('end', function () { clearHighlight(); });
  speechSynthesis.speak(u);
}

आवाज़ चुनने वाला, जिसे यूज़र एक बार चुनता है; आगे का हर utterance ठीक वही आवाज़ लेकर चलता है:

var picker = document.getElementById('voice-picker');

function listVoices() {
  var saved = localStorage.getItem('voiceName') || '';
  picker.innerHTML = '';
  speechSynthesis.getVoices().forEach(function (v) {
    picker.add(new Option(v.name + ' (' + v.lang + ')', v.name, false, v.name === saved));
  });
}
if ('speechSynthesis' in window) {
  listVoices();                                   // [] until the engine is ready
  speechSynthesis.onvoiceschanged = listVoices;
}
picker.onchange = function () { localStorage.setItem('voiceName', picker.value); };

function speakWithSavedVoice(text) {
  var name = localStorage.getItem('voiceName');
  var voice = speechSynthesis.getVoices().filter(function (v) { return v.name === name; })[0];
  var u = new SpeechSynthesisUtterance(text);
  if (voice) u.voice = voice;                     // its language is used too when u.lang is empty
  speechSynthesis.speak(u);
}

वर्कआउट के संकेत: उलटी गिनती के लिए धीमे और तेज़, बदलाव के लिए पूरी आवाज़ और ऊँचे सुर में:

function cue(text, loud) {
  if (!('speechSynthesis' in window)) return;
  var u = new SpeechSynthesisUtterance(text);
  u.lang = 'en-US';
  u.rate = 1.4;                  // 0.1 .. 4
  u.pitch = loud ? 1.3 : 1;      // 0.1 .. 4
  u.volume = loud ? 1 : 0.4;     // 0 .. 1
  u.onerror = function (e) {
    if (e.error === 'synthesis-failed') console.log('Cue not spoken:', text);
  };
  speechSynthesis.speak(u);      // queues after the previous cue
}

cue('Ten seconds left', false);
cue('Switch sides!', true);

ध्यान दें: JSON है {text, lang, rate, pitch, volume, voice, id} (voice कोई getVoices() नाम या '' है)। पुराना ttsSpeak(text, lang, rate, pitch, id) उन पेजों के लिए रहता है जो ब्रिज को सीधे कॉल करते हैं; उसमें volume या voice नहीं है।

ttsCancel ब्रिज#

window.WebToApk.ttsCancel()

window.speechSynthesis पॉलीफ़िल को सहारा देता है, जो हर फ़्रेम में डॉक्यूमेंट शुरू होते ही इंस्टॉल होता है - पेजों को मानक speechSynthesis API इस्तेमाल करना चाहिए और ये उनके लिए कॉल हो जाएँगे। Android WebView में अपना कोई चलने वाला speechSynthesis नहीं आता, इसीलिए यह रीरूट मौजूद है।

इसका वर्णन अलग से नहीं, बल्कि इसके समूह टेक्स्ट-टू-स्पीच में है।

उदाहरण

बोलना अभी रोक देता है और बोलने के इंतज़ार में बाकी सब कुछ फेंक देता है। पेज आम तौर पर मानक speechSynthesis.cancel() कॉल करते हैं, जो यह आपके लिए कॉल कर देता है।

लौटाता है: कुछ नहीं। ज़रूरत: कुछ नहीं।

सार्वजनिक तरीका (यही इस्तेमाल करें):

document.getElementById('stop-reading').addEventListener('click', function () {
  if ('speechSynthesis' in window) speechSynthesis.cancel();
});

सीधा कॉल:

if (window.WebToApk && typeof window.WebToApk.ttsCancel === 'function') {
  window.WebToApk.ttsCancel();
}

सिर्फ़ सबसे नया स्टेटस बोलें और कतार में लगी पुरानी बातें छोड़ दें (डिलीवरी ट्रैकर, लाइव स्कोर):

function announceLatest(text) {
  if (!('speechSynthesis' in window)) return;
  speechSynthesis.cancel();   // the old line gets error 'interrupted', queued ones 'canceled'
  var u = new SpeechSynthesisUtterance(text);
  u.onerror = function (e) {
    if (e.error === 'interrupted' || e.error === 'canceled') return;   // replaced, not a failure
    showToast('Could not read that aloud');
  };
  speechSynthesis.speak(u);
}

announceLatest('Your driver is 5 minutes away');
announceLatest('Your driver has arrived');   // cuts the first one off

ध्यान दें: बीच में कटी या छोड़ी गई बोली कोई appmint:tts end या error इवेंट नहीं भेजती, इसलिए cancel के बाद उस utterance का onend नहीं चलता। अगर आप कच्चे ttsSpeak id खुद ट्रैक करते हैं, तो कॉल करते समय उन्हें भूल जाएँ ttsCancel().

ttsGetVoices ब्रिज#

window.WebToApk.ttsGetVoices(): String

इंस्टॉल आवाज़ों की JSON ऐरे: [{name, lang, default}]। इंजन का इनिट पूरा होने तक खाली रहती है - तब पेज को 'voiceschanged' मिलता है और वह फिर से क्वेरी करता है, बिल्कुल Chrome के async getVoices() अनुबंध की तरह।

उदाहरण

फ़ोन पर इंस्टॉल टेक्स्ट-टू-स्पीच आवाज़ों की सूची देता है। पेज आम तौर पर मानक speechSynthesis.getVoices() इस्तेमाल करते हैं, जो यह आपके लिए कॉल कर देता है।

लौटाता है: JSON स्ट्रिंग, तुरंत: [{ "name": "en-us-x-sfg-local", "lang": "en-US", "default": false }, ...]। इंजन शुरू होने तक यह "[]" रहती है। ज़रूरी: कुछ नहीं।

सार्वजनिक तरीका (यही इस्तेमाल करें):

function fillLanguages() {
  var langs = {};
  speechSynthesis.getVoices().forEach(function (v) { langs[v.lang] = true; });
  document.getElementById('langs').textContent = Object.keys(langs).join(', ');
}
if ('speechSynthesis' in window) {
  fillLanguages();
  speechSynthesis.onvoiceschanged = fillLanguages;
}

रॉ कॉल (याद रखें JSON.parse):

function nativeVoices() {
  if (!(window.WebToApk && typeof window.WebToApk.ttsGetVoices === 'function')) return [];
  try { return JSON.parse(window.WebToApk.ttsGetVoices()); } catch (e) { return []; }
}

window.addEventListener('appmint:tts', function (e) {
  if (e.detail && e.detail.event === 'voiceschanged') {
    var hindi = nativeVoices().filter(function (v) { return v.lang.indexOf('hi') === 0; });
    document.getElementById('hindi-btn').hidden = hindi.length === 0;
  }
});

फ़ोन की भाषा में बोलें अगर उसकी आवाज़ इंस्टॉल है, वरना इंजन को उसकी डिफ़ॉल्ट आवाज़ इस्तेमाल करने दें:

function bestSpeechLang() {
  if (!(window.WebToApk && typeof window.WebToApk.ttsGetVoices === 'function')) return '';
  var voices;
  try { voices = JSON.parse(window.WebToApk.ttsGetVoices()); } catch (e) { return ''; }
  var want = navigator.language || 'en-US';            // e.g. 'ta-IN'
  var exact = voices.filter(function (v) { return v.lang === want; })[0];
  if (exact) return exact.lang;
  var base = want.split('-')[0];
  var near = voices.filter(function (v) { return v.lang.split('-')[0] === base; })[0];
  return near ? near.lang : '';                        // '' = the engine's default voice
}

if (window.WebToApk && typeof window.WebToApk.ttsSpeak === 'function') {
  window.WebToApk.ttsSpeak(greetingText(), bestSpeechLang(), 1.0, 1.0, 'greeting');
}

ध्यान दें: lang एक BCP-47 टैग है जैसे en-US या ta-IN। आवाज़ का name इंजन की अपनी id है और बोलते समय नाम से नहीं चुनी जा सकती; सिर्फ़ उसकी भाषा इस्तेमाल होती है।

ttsIsSpeaking ब्रिज#

window.WebToApk.ttsIsSpeaking(): Boolean

window.speechSynthesis पॉलीफ़िल को सहारा देता है, जो हर फ़्रेम में डॉक्यूमेंट शुरू होते ही इंस्टॉल होता है - पेजों को मानक speechSynthesis API इस्तेमाल करना चाहिए और ये उनके लिए कॉल हो जाएँगे। Android WebView में अपना कोई चलने वाला speechSynthesis नहीं आता, इसीलिए यह रीरूट मौजूद है।

इसका वर्णन अलग से नहीं, बल्कि इसके समूह टेक्स्ट-टू-स्पीच में है।

उदाहरण

बताता है कि फ़ोन का टेक्स्ट-टू-स्पीच इंजन इस पल बोल रहा है या नहीं। पेज आम तौर पर इसके बजाय speechSynthesis.speaking या utterance का onend इस्तेमाल करते हैं।

लौटाता है: true / false, तुरंत। इंजन शुरू होने से पहले false। ज़रूरी: कुछ नहीं।

सार्वजनिक तरीका (यही इस्तेमाल करें):

if ('speechSynthesis' in window && speechSynthesis.speaking) {
  speechSynthesis.cancel();
}

रॉ कॉल इंजन से ही पूछती है, इसलिए यह तब भी सटीक है जब बोलना रॉ से शुरू किया गया हो ttsSpeak:

function isSpeaking() {
  if (window.WebToApk && typeof window.WebToApk.ttsIsSpeaking === 'function') {
    return window.WebToApk.ttsIsSpeaking() === true;
  }
  return false;
}

var btn = document.getElementById('read-btn');
setInterval(function () {
  btn.textContent = isSpeaking() ? 'Stop' : 'Read aloud';
}, 500);

रिकॉर्डिंग शुरू करने से पहले इंतज़ार करें कि ऐप बोलना बंद कर दे, ताकि माइक अपनी ही आवाज़ न पकड़े:

function whenQuiet(fn) {
  if (!(window.WebToApk && typeof window.WebToApk.ttsIsSpeaking === 'function')) { fn(); return; }
  (function check() {
    if (window.WebToApk.ttsIsSpeaking()) setTimeout(check, 300);
    else fn();
  })();
}

document.getElementById('answer-btn').addEventListener('click', function () {
  whenQuiet(startRecordingAnswer);   // e.g. after the question was read aloud
});

ध्यान दें: तेज़ी से पोल न करें; जब आपने बोलना खुद शुरू किया हो तो इवेंट (onend, या event: 'end' के साथ appmint:tts) बेहतर है।

ttsSpeak ब्रिज#

window.WebToApk.ttsSpeak(text: String, lang: String, rate: Double, pitch: Double, utteranceId: String)

window.speechSynthesis पॉलीफ़िल को सहारा देता है, जो हर फ़्रेम में डॉक्यूमेंट शुरू होते ही इंस्टॉल होता है - पेजों को मानक speechSynthesis API इस्तेमाल करना चाहिए और ये उनके लिए कॉल हो जाएँगे। Android WebView में अपना कोई चलने वाला speechSynthesis नहीं आता, इसीलिए यह रीरूट मौजूद है।

इसका वर्णन अलग से नहीं, बल्कि इसके समूह टेक्स्ट-टू-स्पीच में है।

उदाहरण

फ़ोन के टेक्स्ट-टू-स्पीच इंजन से टेक्स्ट बोलना शुरू करता है। पेज आम तौर पर मानक speechSynthesis API इस्तेमाल करते हैं, जो यह आपके लिए कॉल कर देता है।

लौटाता है: कुछ नहीं। प्रगति बाद में appmint:tts इवेंट (और window.onAppMintTts(detail) हुक) के रूप में detail = { id, event } के साथ आती है, जहाँ event है 'start', 'end' या 'error', और id वह utteranceId है जो आपने दिया। ज़रूरी: कुछ नहीं।

सार्वजनिक तरीका (यही इस्तेमाल करें):

if ('speechSynthesis' in window) {
  var u = new SpeechSynthesisUtterance('Your order is ready');
  u.lang = 'en-GB';
  u.onend = function () { console.log('done'); };
  speechSynthesis.speak(u);
}

रॉ कॉल, अगर आप अपनी id चाहते हैं। आर्गुमेंट: text, lang, rate, pitch, utteranceId:

var ttsWaiting = {};

window.addEventListener('appmint:tts', function (e) {
  var d = e.detail || {};
  if (d.event === 'voiceschanged') return;        // engine ready, id is ''
  var done = ttsWaiting[d.id];
  if (!done || d.event === 'start') return;
  delete ttsWaiting[d.id];
  done(d.event === 'end');                         // 'end' = spoke it, 'error' = failed
});

function speakRaw(text) {
  return new Promise(function (resolve) {
    if (!(window.WebToApk && typeof window.WebToApk.ttsSpeak === 'function')) { resolve(false); return; }
    var id = 'mine_' + Date.now();
    ttsWaiting[id] = resolve;
    window.WebToApk.ttsSpeak(String(text), 'en-US', 1.0, 1.0, id);
  });
}

speakRaw('Hello').then(function (ok) { console.log(ok ? 'spoken' : 'could not speak'); });

अपने id के साथ चरणों की सूची क्रम से पढ़ें, और जो चरण बोला जा रहा है उसे हाइलाइट करें:

var steps = Array.prototype.slice.call(document.querySelectorAll('.recipe-step'));

window.addEventListener('appmint:tts', function (e) {
  var d = e.detail || {};
  var m = /^recipe_(\d+)$/.exec(d.id || '');
  if (!m) return;                                  // not one of ours
  var el = steps[Number(m[1])];
  if (d.event === 'start') el.classList.add('reading');
  if (d.event === 'end' || d.event === 'error') el.classList.remove('reading');
});

document.getElementById('read-recipe').addEventListener('click', function () {
  if (!(window.WebToApk && typeof window.WebToApk.ttsSpeak === 'function')) return;
  steps.forEach(function (el, i) {
    // '' = the engine's default voice; 0.9 = a little slower for cooking
    window.WebToApk.ttsSpeak(el.textContent, '', 0.9, 1.0, 'recipe_' + i);
  });
});

ध्यान दें: utterance एक के बाद एक कतार में लगते हैं। lang '' हो सकता है (इंजन की डिफ़ॉल्ट आवाज़); rate और pitch को 0.1-4 के बीच रखा जाता है। अगर इंजन अभी शुरू हो रहा है, तो टेक्स्ट इंतज़ार करता है और तैयार होने पर बोला जाता है; अगर इंजन शुरू नहीं हो सकता, तो हर इंतज़ार करता utterance 'error' पाता है। अपनी id का प्रीफ़िक्स इस्तेमाल करें; wta_u से शुरू होने वाली id speechSynthesis लेयर की हैं। Android 8+ पर appmint:tts हर शब्द से पहले {id, event: 'boundary', charIndex, charLength} भी ले जाता है। इस रॉ कॉल में volume या voice नहीं है - speechSynthesis में दोनों हैं।

ttsWarmUp ब्रिज#

window.WebToApk.ttsWarmUp()

window.speechSynthesis पॉलीफ़िल को सहारा देता है, जो हर फ़्रेम में डॉक्यूमेंट शुरू होते ही इंस्टॉल होता है - पेजों को मानक speechSynthesis API इस्तेमाल करना चाहिए और ये उनके लिए कॉल हो जाएँगे। Android WebView में अपना कोई चलने वाला speechSynthesis नहीं आता, इसीलिए यह रीरूट मौजूद है।

इसका वर्णन अलग से नहीं, बल्कि इसके समूह टेक्स्ट-टू-स्पीच में है।

उदाहरण

फ़ोन का टेक्स्ट-टू-स्पीच इंजन पहले से शुरू कर देता है, ताकि पहले speak() में देरी न हो और getVoices() भर जाए। ऐप की speechSynthesis लेयर पेज शुरू होते ही इसे कॉल कर देती है, इसलिए पेजों को इसकी लगभग कभी ज़रूरत नहीं पड़ती।

लौटाता है: कुछ नहीं। इंजन तैयार होने पर appmint:tts इवेंट detail = { id: '', event: 'voiceschanged' } के साथ चलता है (और speechSynthesis.onvoiceschanged चलता है)। ज़रूरी: कुछ नहीं।

सार्वजनिक तरीका (यही इस्तेमाल करें): आवाज़ें तैयार होने पर बस उन्हें पढ़ें।

if ('speechSynthesis' in window) {
  speechSynthesis.onvoiceschanged = function () {
    console.log('voices:', speechSynthesis.getVoices().length);
  };
}

रॉ कॉल, फिर ready इवेंट का इंतज़ार करें:

window.addEventListener('appmint:tts', function (e) {
  if (e.detail && e.detail.event === 'voiceschanged') {
    var list = JSON.parse(window.WebToApk.ttsGetVoices());
    console.log('engine ready,', list.length, 'voices');
  }
});

if (window.WebToApk && typeof window.WebToApk.ttsWarmUp === 'function') {
  window.WebToApk.ttsWarmUp();   // safe to call many times
}

“Read aloud” स्क्रीन खुलने पर इंजन शुरू करें और इंजन तैयार होने पर ही उसका बटन चालू करें:

var readBtn = document.getElementById('read-aloud');

function engineReady() {
  try { return JSON.parse(window.WebToApk.ttsGetVoices()).length > 0; } catch (e) { return false; }
}

function openReaderScreen() {
  showReaderScreen();
  if (!(window.WebToApk && typeof window.WebToApk.ttsWarmUp === 'function')) return;
  readBtn.disabled = !engineReady();       // already started earlier? enable right away
  window.WebToApk.ttsWarmUp();             // no-op when the engine is already running
}

window.addEventListener('appmint:tts', function (e) {
  if (e.detail && e.detail.event === 'voiceschanged') readBtn.disabled = false;
});

ध्यान दें: voiceschanged एक ही बार चलता है, जब इंजन शुरू हो जाता है। अगर वह पहले ही शुरू हो चुका है (जैसे speechSynthesis लेयर ने उसे गरम कर दिया), तो यह फिर नहीं मिलेगा; सीधे ttsGetVoices() कॉल करें।

हर डॉक्स बिल्ड पर ऐप रनटाइम और उसकी उदाहरण फ़ाइलों से बनाया जाता है। Markdown में पढ़ें · सभी फ़ैमिली.

2026-10-03 को शिप किए गए ब्रिज से मिलाकर जाँचा गया।