ساخت APK رایگان

API پل جاوااسکریپت

تبدیل متن به گفتار

صداهای دستگاه، که از صفحه گفته می‌شوند.

SpeechRecognition استاندارد وب#

webkitSpeechRecognition / SpeechRecognition — speech to text

نمونه

Web Speech API استاندارد برای دیکته: کاربر حرف می‌زند، صفحه متن می‌گیرد. Chrome در اندروید آن را دارد و WebView اندروید ندارد، پس اپلیکیشن آن را روی تشخیص‌دهنده‌ی گفتار خود اندروید فراهم می‌کند. کدی که برای 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() اجرا می‌شود از کاربر می‌پرسد.

<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 می‌رسند. اپلیکیشن‌های ساخته‌شده با هوش مصنوعی از speech.start() از @/lib/appmintNative.

speechSynthesis استاندارد وب#

window.speechSynthesis + SpeechSynthesisUtterance

نمونه

متن را با موتور تبدیل متن به گفتار خود گوشی و با Web Speech API معمولی بلند می‌خواند.

بازگشتی: speechSynthesis.speak(u) چیزی برنمی‌گرداند؛ رویدادهای start / boundary / end / error / pause / resume مربوط به utterance (به‌صورت ویژگی‌های onstart … یا با addEventListener) به شما می‌گویند چه شد. getVoices() بلافاصله آرایه‌ای از { voiceURI, name, lang, localService, default } برمی‌گرداند. نیازمند: هیچ چیز. WebView اندروید API گفتار کارآمدی ندارد؛ اپلیکیشن این را در آغاز سند در هر frame نصب می‌کند.

یک جمله بگویید و بدانید کی تمام شده:

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);
}

یک خواننده‌ی مقاله با یک دکمه‌ی «مکث / ادامه» که بند در حال خواندن را برجسته می‌کند:

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، voice برنده است؛ با هیچ‌کدام، صدای پیش‌فرض موتور صحبت می‌کند.
  • boundary پیش از هر کلمه با charIndex / charLength فعال می‌شود (اندروید ۸ به بالا؛ موتورهایی که موقعیت کلمه گزارش نمی‌کنند هیچ نمی‌فرستند).
  • pause() / resume(): موتور اندروید نمی‌تواند وسط کلمه مکث کند، پس pause() آن را متوقف می‌کند و resume() باقی جمله را از آخرین کلمه‌ای که موتور گزارش کرده ادامه می‌دهد (رویدادهای pause / resume فعال می‌شوند). روی موتوری که موقعیت کلمه گزارش نمی‌کند، resume() آن utterance را از ابتدا دوباره شروع می‌کند. speaking هنگام مکث true می‌ماند؛ pending وقتی utterance‌ها در صف منتظرند true است.
  • cancel() error را با error: 'interrupted' روی utterance در حال گفتن و '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 می‌رسد: {id, type} برای start/audiostart/speechstart/speechend/audioend/end، {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) روی 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 می‌رسد: {id, type} برای start/audiostart/speechstart/speechend/audioend/end، {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) روی 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 می‌رسد: {id, type} برای start/audiostart/speechstart/speechend/audioend/end، {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) روی 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 می‌رسد: {id, type} برای start/audiostart/speechstart/speechend/audioend/end، {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) روی SpeechRecognizer اندروید پیاده‌سازی شده. __srStart برای صفحه‌هایی که به اپلیکیشن تعلق ندارند رد می‌شود.

__ttsSpeak پل#

window.WebToApk.__ttsSpeak(json: String)

speak کامل polyfill مربوط به speechSynthesis: `{text, lang, rate, pitch, volume (0-1), voice (نامی از getVoices()، یا ''), id}`. [ttsSpeak] برای صفحه‌هایی که مستقیم پل را صدا می‌زنند باقی می‌ماند؛ صدا (volume) یا voice ندارد.

نمونه

انتقال داخلی پشت speechSynthesis.speak(utterance): گفتار کامل - متن، زبان، سرعت، زیر و بمی، صدا و صدای انتخاب‌شده - به‌صورت یک رشته‌ی JSON. صفحه‌ها از API استاندارد speechSynthesis استفاده می‌کنند؛ هرگز مستقیم این را صدا نزنید.

بازگشتی: هیچ. پیشرفت به‌صورت رویدادهای appmint:tts می‌رسد که لایه‌ی speechSynthesis آن‌ها را به رویدادهای start / boundary / end / error مربوط به utterance تبدیل می‌کند. نیازمند: هیچ چیز.

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);
}

یک انتخابگر صدا که کاربر یک بار انتخاب می‌کند؛ هر گفتار بعدی همان صدای دقیق را به همراه دارد:

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()

از polyfill مربوط به window.speechSynthesis پشتیبانی می‌کند که در آغاز سند در هر frame نصب می‌شود - صفحه‌ها باید از API استاندارد speechSynthesis استفاده کنند و این‌ها برایشان صدا زده می‌شوند. 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 نمی‌فرستد، پس onend یک utterance بعد از لغو اجرا نمی‌شود. اگر شناسه‌های خام ttsSpeak را خودتان دنبال می‌کنید، هنگام فراخوانی آن‌ها را فراموش کنید ttsCancel().

ttsGetVoices پل#

window.WebToApk.ttsGetVoices(): String

آرایه‌ی JSON از صداهای نصب‌شده: [{name, lang, default}]. تا پایان راه‌اندازی موتور خالی است - صفحه آن موقع 'voiceschanged' می‌گیرد و دوباره پرس‌وجو می‌کند، دقیقاً مثل قرارداد getVoices() ناهمزمان Chrome.

نمونه

صداهای تبدیل متن به گفتار نصب‌شده روی گوشی را فهرست می‌کند. صفحه‌ها معمولاً از 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 یک صدا شناسه‌ی خود موتور است و هنگام صحبت کردن نمی‌توان آن را با نام انتخاب کرد؛ فقط زبانش استفاده می‌شود.

ttsIsSpeaking پل#

window.WebToApk.ttsIsSpeaking(): Boolean

از polyfill مربوط به window.speechSynthesis پشتیبانی می‌کند که در آغاز سند در هر frame نصب می‌شود - صفحه‌ها باید از API استاندارد speechSynthesis استفاده کنند و این‌ها برایشان صدا زده می‌شوند. WebView اندروید speechSynthesis کارآمدی ندارد، به همین دلیل این مسیردهی مجدد وجود دارد.

به‌جای خودش، با گروهش تبدیل متن به گفتار توضیح داده می‌شود.

نمونه

مشخص می‌کند که آیا موتور تبدیل متن به گفتار گوشی در این لحظه در حال صحبت است یا نه. صفحه‌ها معمولاً به‌جایش از speechSynthesis.speaking یا onend مربوط به utterance استفاده می‌کنند.

بازگشتی: 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
});

نکته‌ها: سریع poll نکنید؛ وقتی خودتان گفتار را شروع کرده‌اید یک رویداد (onend، یا appmint:tts با event: 'end') بهتر است.

ttsSpeak پل#

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

از polyfill مربوط به window.speechSynthesis پشتیبانی می‌کند که در آغاز سند در هر frame نصب می‌شود - صفحه‌ها باید از API استاندارد speechSynthesis استفاده کنند و این‌ها برایشان صدا زده می‌شوند. WebView اندروید speechSynthesis کارآمدی ندارد، به همین دلیل این مسیردهی مجدد وجود دارد.

به‌جای خودش، با گروهش تبدیل متن به گفتار توضیح داده می‌شود.

نمونه

گفتن متن را با موتور تبدیل متن به گفتار گوشی شروع می‌کند. صفحه‌ها معمولاً از API speechSynthesis استاندارد استفاده می‌کنند که این را برایتان صدا می‌زند.

بازگشتی: هیچ. پیشرفت بعداً به‌صورت رویداد 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);
}

فراخوانی خام، اگر شناسه‌های خودتان را می‌خواهید. آرگومان‌ها: 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'); });

فهرستی از مراحل را به ترتیب و با شناسه‌های خودتان بخوانید و مرحله‌ی در حال گفتن را برجسته کنید:

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);
  });
});

نکته‌ها: گفتارها پشت سر هم در صف می‌روند. lang می‌تواند '' باشد (صدای پیش‌فرض موتور)؛ rate و pitch به ۰٫۱ تا ۴ محدود می‌شوند. اگر موتور هنوز در حال شروع است، متن منتظر می‌ماند و وقتی آماده شد گفته می‌شود؛ اگر موتور نتواند شروع شود، هر گفتار منتظر 'error' می‌گیرد. از پیشوند شناسه‌ی خودتان استفاده کنید؛ شناسه‌هایی که با wta_u شروع می‌شوند به لایه‌ی speechSynthesis تعلق دارند. در اندروید ۸ به بالا appmint:tts پیش از هر کلمه {id, event: 'boundary', charIndex, charLength} را هم می‌آورد. این فراخوانی خام صدا (volume) یا voice ندارد - speechSynthesis هر دو را دارد.

ttsWarmUp پل#

window.WebToApk.ttsWarmUp()

از polyfill مربوط به window.speechSynthesis پشتیبانی می‌کند که در آغاز سند در هر frame نصب می‌شود - صفحه‌ها باید از API استاندارد speechSynthesis استفاده کنند و این‌ها برایشان صدا زده می‌شوند. 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);
  };
}

فراخوانی خام، سپس منتظر رویداد آماده بودن بمانید:

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
}

وقتی صفحه‌ی «بلند بخوان» باز می‌شود موتور را شروع کنید و دکمه‌اش را وقتی موتور آماده شد فعال کنید:

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() را صدا بزنید.