Ücretsiz APK oluştur

JavaScript köprü API'si

Metinden konuşmaya

Cihaz sesleri, sayfadan konuşturulur.

SpeechRecognition web standardı#

webkitSpeechRecognition / SpeechRecognition — speech to text

Örnek

Dikte için standart Web Speech API: kullanıcı konuşur, sayfa metin alır. Android'deki Chrome'da vardır, Android'in WebView'inde yoktur; bu yüzden uygulama bunu Android'in kendi konuşma tanıyıcısı üzerinden sağlar. Chrome için yazılmış kod değişmeden çalışır.

Döndürür: start() dinlemeye başlar; result olayları event.results[i][0].transcript (ve .confidence, .isFinal) taşır; error olayları event.error taşır (not-allowed, no-speech, audio-capture, network, aborted, language-not-supported, service-not-allowed); end her zaman en sonda gelir. Gerekir: mikrofon. Kodunuz SpeechRecognition ifadesini andığında derleme bunu kendiliğinden açar ve start() çalıştığında Android kullanıcıya ilk seferde sorar.

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

İstek üzerine duran ve her hatayı bildiren sürekli dikte:

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

Bir komut söyleyin ve telefonun dilinde işleme alın:

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

Notlar: continuous = true, siz stop() çağırana kadar cümleler boyunca dinlemeye devam eder; üç sessiz turdan sonra no-speech ile biter, böylece unutulan bir tanıyıcı sonsuza dek dinlemez. stop() duyulanı iletir; abort() atar. Uygulama arka plana gittiğinde, Chrome sekmesi gizlendiğinde olduğu gibi tanıma durur. Mikrofonu bu şekilde yalnızca uygulamaya ait sayfalar (kendi dosyaları veya oluşturucunun web sitesi) kullanabilir; başka her site not-allowed alır. Telefonda konuşma tanıma hizmeti yoksa API bulunmaz, bu yüzden yukarıdaki gibi kontrol edin. İç aktarımlar: __srStart, __srStop, __srAbort, __srAvailable; sonuçlar appmint:sr olarak gelir. Yapay zekayla oluşturulan uygulamalar şuradan speech.start() kullanır: @/lib/appmintNative.

speechSynthesis web standardı#

window.speechSynthesis + SpeechSynthesisUtterance

Örnek

Normal Web Speech API'sini kullanarak, telefonun kendi metinden konuşmaya motoruyla metni yüksek sesle okur.

Döndürür: speechSynthesis.speak(u) hiçbir şey döndürmez; söylemin start / boundary / end / error / pause / resume olayları (onstart … özellikleri olarak veya addEventListener ile) ne olduğunu söyler. getVoices() eşzamanlı olarak bir { voiceURI, name, lang, localService, default } dizisi döndürür. Gerekir: hiçbir şey. Android WebView'in kendi çalışan bir konuşma API'si yoktur; uygulama bunu her çerçevede belge başlangıcında kurar.

Bir cümle söyleyin ve ne zaman bittiğini bilin:

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

Sesler başlangıçtan kısa süre sonra gelir. voiceschanged tetiklendiğinde yeniden okuyun:

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

Okunan paragrafı vurgulayan tek bir Duraklat / Sürdür düğmesiyle makale okuyucu:

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

Notlar:

  • volume (0-1), voice (getVoices() içinden tam ses), rate, pitch ve lang hepsi telefonun motoruna ulaşır. Bir voice ve bir lang ile ses kazanır; ikisi de yoksa motorun varsayılan sesi konuşur.
  • boundary her sözcükten önce charIndex / charLength ile tetiklenir (Android 8+; sözcük konumu bildirmeyen motorlar göndermez).
  • pause() / resume(): Android'in motoru sözcüğün ortasında duraklayamaz, bu yüzden pause() onu durdurur ve resume() cümlenin kalanını motorun bildirdiği son sözcükten itibaren okur (pause / resume olayları tetiklenir). Sözcük konumu bildirmeyen bir motorda resume() o söylemi baştan yeniden başlatır. Duraklatılmışken speaking değeri true kalır; sıradaki söylemler beklerken pending değeri true olur.
  • cancel() standardın dediği gibi, konuşulan söylemde error ile error: 'interrupted', sıradakilerde 'canceled' tetikler - bunları başarısızlık olarak göstermeyin.
  • Telefonda dil için ses verisi yoksa motor yine de varsayılan dilinde konuşabilir. Önce dil için getVoices() kontrol edin.
  • Bunun arkasındaki ham olaylar appmint:tts (bkz. ttsSpeak). Bu API'yi kullandığınızda onlara ihtiyacınız yoktur.

__srAbort köprü#

window.WebToApk.__srAbort(id: String)

SpeechRecognition.abort(): hemen durdur, at.

Örnek

WebToApk.__srStart ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.

webkitSpeechRecognition / SpeechRecognition arkasındaki iç aktarım (başlat, durdur, iptal et ve telefonda bir tanıyıcı olup olmadığı). Sayfalar standart API'yi kullanır; bunları asla doğrudan çağırmayın, çünkü __ yöntemleri haber verilmeden değişebilir.

Döndürür: __srStart(id, options) dinleme başladığında "", ya da bir Web Speech hata adı (not-allowed, service-not-allowed) döndürür. Sonrasında her şey appmint:sr olayları olarak gelir: başlat/audiostart/speechstart/speechend/audioend/end için {id, type}, {id, type:'result', final, alternatives:[{transcript, confidence}]} ve {id, type:'error', error}. Gerekir: mikrofon (çağrı biçiminden hazırlanır).

Genel API'yi kullanın:

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

Canlı metin ve bir dille sürekli dikte:

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

Reddedilen bir mikrofon gibi hataları bildirin:

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

Notlar: Uygulama kabuğunda (SpeechRecognitionBridge.kt) Android'in SpeechRecognizer'ı üzerinden uygulanmıştır. __srStart, uygulamaya ait olmayan sayfalar için reddedilir.

__srAvailable köprü#

window.WebToApk.__srAvailable(): Boolean

Bir konuşma tanıma hizmetinin kurulu olup olmadığı (webkitSpeechRecognition yalnızca o zaman vardır).

Örnek

WebToApk.__srStart ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.

webkitSpeechRecognition / SpeechRecognition arkasındaki iç aktarım (başlat, durdur, iptal et ve telefonda bir tanıyıcı olup olmadığı). Sayfalar standart API'yi kullanır; bunları asla doğrudan çağırmayın, çünkü __ yöntemleri haber verilmeden değişebilir.

Döndürür: __srStart(id, options) dinleme başladığında "", ya da bir Web Speech hata adı (not-allowed, service-not-allowed) döndürür. Sonrasında her şey appmint:sr olayları olarak gelir: başlat/audiostart/speechstart/speechend/audioend/end için {id, type}, {id, type:'result', final, alternatives:[{transcript, confidence}]} ve {id, type:'error', error}. Gerekir: mikrofon (çağrı biçiminden hazırlanır).

Genel API'yi kullanın:

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

Canlı metin ve bir dille sürekli dikte:

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

Reddedilen bir mikrofon gibi hataları bildirin:

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

Notlar: Uygulama kabuğunda (SpeechRecognitionBridge.kt) Android'in SpeechRecognizer'ı üzerinden uygulanmıştır. __srStart, uygulamaya ait olmayan sayfalar için reddedilir.

__srStart köprü#

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

SpeechRecognition.start(): başlarken "" (olaylar `appmint:sr` olarak gelir), aksi halde Web Speech hata adı. Kaynak denetimlidir: kullanıcının söyledikleri kullanıcı verisidir.

Örnek

webkitSpeechRecognition / SpeechRecognition arkasındaki iç aktarım (başlat, durdur, iptal et ve telefonda bir tanıyıcı olup olmadığı). Sayfalar standart API'yi kullanır; bunları asla doğrudan çağırmayın, çünkü __ yöntemleri haber verilmeden değişebilir.

Döndürür: __srStart(id, options) dinleme başladığında "", ya da bir Web Speech hata adı (not-allowed, service-not-allowed) döndürür. Sonrasında her şey appmint:sr olayları olarak gelir: başlat/audiostart/speechstart/speechend/audioend/end için {id, type}, {id, type:'result', final, alternatives:[{transcript, confidence}]} ve {id, type:'error', error}. Gerekir: mikrofon (çağrı biçiminden hazırlanır).

Genel API'yi kullanın:

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

Canlı metin ve bir dille sürekli dikte:

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

Reddedilen bir mikrofon gibi hataları bildirin:

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

Notlar: Uygulama kabuğunda (SpeechRecognitionBridge.kt) Android'in SpeechRecognizer'ı üzerinden uygulanmıştır. __srStart, uygulamaya ait olmayan sayfalar için reddedilir.

__srStop köprü#

window.WebToApk.__srStop(id: String)

SpeechRecognition.stop(): dinlemeyi durdur, duyulanı ilet.

Örnek

WebToApk.__srStart ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.

webkitSpeechRecognition / SpeechRecognition arkasındaki iç aktarım (başlat, durdur, iptal et ve telefonda bir tanıyıcı olup olmadığı). Sayfalar standart API'yi kullanır; bunları asla doğrudan çağırmayın, çünkü __ yöntemleri haber verilmeden değişebilir.

Döndürür: __srStart(id, options) dinleme başladığında "", ya da bir Web Speech hata adı (not-allowed, service-not-allowed) döndürür. Sonrasında her şey appmint:sr olayları olarak gelir: başlat/audiostart/speechstart/speechend/audioend/end için {id, type}, {id, type:'result', final, alternatives:[{transcript, confidence}]} ve {id, type:'error', error}. Gerekir: mikrofon (çağrı biçiminden hazırlanır).

Genel API'yi kullanın:

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

Canlı metin ve bir dille sürekli dikte:

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

Reddedilen bir mikrofon gibi hataları bildirin:

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

Notlar: Uygulama kabuğunda (SpeechRecognitionBridge.kt) Android'in SpeechRecognizer'ı üzerinden uygulanmıştır. __srStart, uygulamaya ait olmayan sayfalar için reddedilir.

__ttsSpeak köprü#

window.WebToApk.__ttsSpeak(json: String)

speechSynthesis polyfill'inin tam konuşma çağrısı: `{text, lang, rate, pitch, volume (0-1), voice (bir getVoices() adı veya ''), id}`. [ttsSpeak], köprüyü doğrudan çağıran sayfalar için kalır; ses düzeyi veya ses seçimi yoktur.

Örnek

speechSynthesis.speak(utterance) arkasındaki iç aktarım: tam söylem - metin, dil, hız, perde, ses düzeyi ve seçilen ses - tek bir JSON dizesi olarak. Sayfalar standart speechSynthesis API'sini kullanır; bunu asla doğrudan çağırmayın.

Döndürür: hiçbir şey. İlerleme appmint:tts olayları olarak gelir ve speechSynthesis katmanı bunları söylemin start / boundary / end / error olaylarına çevirir. Gerekir: hiçbir şey.

Bunun taşıdığı standart 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);
}

Kullanıcının bir kez seçtiği bir ses seçici; sonraki her söylem tam olarak bu sesi taşır:

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

Antrenman uyarıları: geri sayımlar için sessiz ve hızlı, geçiş için tam ses düzeyi ve daha yüksek perde:

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

Notlar: JSON {text, lang, rate, pitch, volume, voice, id} biçimindedir (voice bir getVoices() adı veya ''). Eski ttsSpeak(text, lang, rate, pitch, id), köprüyü doğrudan çağıran sayfalar için kalır; ses düzeyi veya ses seçimi yoktur.

ttsCancel köprü#

window.WebToApk.ttsCancel()

window.speechSynthesis polyfill'ini destekler; bu, her çerçevede belge başlangıcında kurulur - sayfalar STANDART speechSynthesis API'sini kullanmalıdır ve bunlar onlar için çağrılır. Android WebView'in kendi çalışan bir speechSynthesis'i yoktur, yeniden yönlendirmenin var olmasının nedeni budur.

Kendi başına değil, grubu Metinden konuşmaya tarafından açıklanır.

Örnek

Konuşmayı hemen durdurur ve konuşulmayı bekleyen her şeyi atar. Sayfalar normalde bunu sizin için çağıran standart speechSynthesis.cancel() işlevini çağırır.

Döndürür: hiçbir şey. Gerekenler: hiçbir şey.

Herkese açık yol (bunu kullanın):

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

Ham çağrı:

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

Yalnızca en yeni durumu söyleyin ve sırada bekleyen eski her şeyi bırakın (bir teslimat takipçisi, canlı skor):

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

Notlar: Kesilen veya bırakılan konuşma hiçbir appmint:tts end veya error olayı göndermez; bu yüzden bir iptalden sonra söylemin onend işlevi çalışmaz. Ham ttsSpeak kimliklerini kendiniz izliyorsanız, şunu çağırdığınızda unutun: ttsCancel().

ttsGetVoices köprü#

window.WebToApk.ttsGetVoices(): String

Kurulu seslerin JSON dizisi: [{name, lang, default}]. Motor başlatmayı bitirene kadar boştur - sayfa o zaman 'voiceschanged' alır ve Chrome'un eşzamansız getVoices() sözleşmesindeki gibi yeniden sorgular.

Örnek

Telefonda kurulu metinden konuşmaya seslerini listeler. Sayfalar normalde bunu sizin için çağıran standart speechSynthesis.getVoices() işlevini kullanır.

Döndürür: eşzamanlı olarak bir JSON dizesi: [{ "name": "en-us-x-sfg-local", "lang": "en-US", "default": false }, ...]. Motor başlayana kadar "[]" olur. Gerekir: hiçbir şey.

Herkese açık yol (bunu kullanın):

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

Ham çağrı (unutmayın: 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;
  }
});

Telefonun dilinde bir ses kuruluysa o dilde, değilse motorun varsayılan sesiyle konuşun:

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

Notlar: lang, en-US veya ta-IN gibi bir BCP-47 etiketidir. Bir sesin name değeri motorun kendi kimliğidir ve konuşurken ada göre seçilemez; yalnızca dili kullanılır.

ttsIsSpeaking köprü#

window.WebToApk.ttsIsSpeaking(): Boolean

window.speechSynthesis polyfill'ini destekler; bu, her çerçevede belge başlangıcında kurulur - sayfalar STANDART speechSynthesis API'sini kullanmalıdır ve bunlar onlar için çağrılır. Android WebView'in kendi çalışan bir speechSynthesis'i yoktur, yeniden yönlendirmenin var olmasının nedeni budur.

Kendi başına değil, grubu Metinden konuşmaya tarafından açıklanır.

Örnek

Telefonun metinden konuşmaya motorunun şu anda konuşup konuşmadığını söyler. Sayfalar normalde bunun yerine speechSynthesis.speaking veya söylemin onend işlevini kullanır.

Döndürür: true / false, eşzamanlı. Motor başlamadan önce false. Gerekir: hiçbir şey.

Herkese açık yol (bunu kullanın):

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

Ham çağrı motora doğrudan sorar, bu yüzden konuşma ham çağrıyla başlatılmış olsa bile kesindir 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);

Mikrofon kendi sesini yakalamasın diye, kayda başlamadan önce uygulamanın konuşmayı bırakmasını bekleyin:

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

Notlar: Hızlı yoklama yapmayın; konuşmayı kendiniz başlattıysanız bir olay (onend veya event: 'end' ile appmint:tts) daha iyidir.

ttsSpeak köprü#

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

window.speechSynthesis polyfill'ini destekler; bu, her çerçevede belge başlangıcında kurulur - sayfalar STANDART speechSynthesis API'sini kullanmalıdır ve bunlar onlar için çağrılır. Android WebView'in kendi çalışan bir speechSynthesis'i yoktur, yeniden yönlendirmenin var olmasının nedeni budur.

Kendi başına değil, grubu Metinden konuşmaya tarafından açıklanır.

Örnek

Telefonun metinden konuşmaya motoruyla metni okumaya başlar. Sayfalar normalde bunu sizin için çağıran standart speechSynthesis API'sini kullanır.

Döndürür: hiçbir şey. İlerleme daha sonra appmint:tts olayı (ve window.onAppMintTts(detail) kancası) ile detail = { id, event } olarak gelir; burada event, 'start', 'end' veya 'error' olur ve id, ilettiğiniz utteranceId değeridir. Gerekir: hiçbir şey.

Herkese açık yol (bunu kullanın):

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

Kendi kimliklerinizi istiyorsanız ham çağrı. Argümanlar: 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'); });

Bir adım listesini kendi kimliklerinizle sırayla okuyun ve okunan adımı vurgulayın:

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

Notlar: Söylemler art arda sıraya girer. lang '' olabilir (motorun varsayılan sesi); rate ve pitch 0,1-4 aralığına sıkıştırılır. Motor hâlâ başlıyorsa metin bekler ve hazır olunca okunur; motor başlayamazsa bekleyen her söylem 'error' alır. Kendi kimlik önekinizi kullanın; wta_u ile başlayan kimlikler speechSynthesis katmanına aittir. Android 8+'da appmint:tts her sözcükten önce {id, event: 'boundary', charIndex, charLength} de taşır. Bu ham çağrıda ses düzeyi veya ses yoktur - speechSynthesis ikisine de sahiptir.

ttsWarmUp köprü#

window.WebToApk.ttsWarmUp()

window.speechSynthesis polyfill'ini destekler; bu, her çerçevede belge başlangıcında kurulur - sayfalar STANDART speechSynthesis API'sini kullanmalıdır ve bunlar onlar için çağrılır. Android WebView'in kendi çalışan bir speechSynthesis'i yoktur, yeniden yönlendirmenin var olmasının nedeni budur.

Kendi başına değil, grubu Metinden konuşmaya tarafından açıklanır.

Örnek

Telefonun metinden konuşmaya motorunu erken başlatır, böylece ilk speak() gecikmesiz olur ve getVoices() dolar. Uygulamanın speechSynthesis katmanı bunu sayfa başlangıcında zaten çağırır, bu yüzden sayfalar nadiren buna ihtiyaç duyar.

Döndürür: hiçbir şey. Motor hazır olduğunda appmint:tts olayı detail = { id: '', event: 'voiceschanged' } ile tetiklenir (ve speechSynthesis.onvoiceschanged çalışır). Gerekir: hiçbir şey.

Herkese açık yol (bunu kullanın): sesleri hazır olduklarında okuyun.

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

Ham çağrı, sonra hazır olayını bekleyin:

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
}

Bir "Sesli oku" ekranı açıldığında motoru başlatın ve motor hazır olunca düğmesini etkinleştirin:

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

Notlar: voiceschanged motor başlamayı bitirdiğinde bir kez tetiklenir. Zaten başladıysa (örneğin speechSynthesis katmanı onu ısıttığı için) tekrar almazsınız; doğrudan ttsGetVoices() çağırın.

Her belge derlemesinde uygulama çalışma zamanından ve örnek dosyalarından oluşturulur. Markdown olarak okuyun · Tüm aileler.

22.10.2026 tarihinde yayınlanan köprüyle karşılaştırılarak kontrol edildi.