API jembatan JavaScript
Teks ke ucapan
Suara perangkat, diucapkan dari halaman.
SpeechRecognition standar web#
webkitSpeechRecognition / SpeechRecognition — speech to text
Contoh
Web Speech API standar untuk dikte: pengguna berbicara, halaman mendapat teks. Chrome di Android memilikinya dan WebView Android tidak, jadi aplikasi menyediakannya di atas pengenal suara Android sendiri. Kode yang ditulis untuk Chrome berfungsi tanpa perubahan.
Hasil: start() mulai mendengarkan; event result membawa event.results[i][0].transcript (dan .confidence, .isFinal); event error membawa event.error (not-allowed, no-speech, audio-capture, network, aborted, language-not-supported, service-not-allowed); end selalu datang terakhir. Membutuhkan: mikrofon. Build mengaktifkannya sendiri bila kode Anda menyebut SpeechRecognition, dan Android meminta pengguna saat pertama kali start() berjalan.
<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>Dikte berkelanjutan yang berhenti sesuai permintaan dan melaporkan setiap kesalahan:
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();
}Ucapkan perintah dan lakukan, dalam bahasa ponsel:
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();
}Catatan: continuous = true terus mendengarkan di antara kalimat sampai Anda memanggil stop(); setelah tiga putaran hening ia berakhir dengan no-speech, agar pengenal yang terlupa tidak mendengarkan selamanya. stop() menyerahkan apa yang terdengar; abort() membuangnya. Pengenalan berhenti saat aplikasi masuk latar belakang, seperti saat tab Chrome disembunyikan. Hanya halaman milik aplikasi (file-nya sendiri, atau situs pembuat) yang dapat memakai mikrofon dengan cara ini; situs lain mendapat not-allowed. API tidak ada bila ponsel tidak punya layanan pengenalan suara, jadi periksa seperti di atas. Transport internal: __srStart, __srStop, __srAbort, __srAvailable; hasil tiba sebagai appmint:sr. Aplikasi buatan AI memakai speech.start() dari @/lib/appmintNative.
speechSynthesis standar web#
window.speechSynthesis + SpeechSynthesisUtterance
Contoh
Membacakan teks dengan mesin text-to-speech ponsel sendiri, memakai Web Speech API biasa.
Hasil: speechSynthesis.speak(u) tidak mengembalikan apa pun; event start / boundary / end / error / pause / resume milik ucapan (sebagai properti onstart ... atau dengan addEventListener) memberi tahu apa yang terjadi. getVoices() mengembalikan array { voiceURI, name, lang, localService, default } secara sinkron. Membutuhkan: tidak ada. Android WebView tidak punya API ucapan yang berfungsi sendiri; aplikasi memasang yang ini saat dokumen dimulai di setiap frame.
Ucapkan sebuah kalimat dan ketahui kapan selesai:
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
};Suara tiba beberapa saat setelah startup. Baca lagi saat voiceschanged terpicu:
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);
}Pembaca artikel dengan satu tombol Jeda / Lanjutkan yang menyorot paragraf yang sedang dibacakan:
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';
}Catatan:
volume(0-1),voice(suara persis darigetVoices()),rate,pitch, danlangsemuanya sampai ke mesin ponsel. Denganvoicedanlang, suara yang menang; tanpa keduanya, suara bawaan mesin yang berbicara.boundaryterpicu sebelum setiap kata dengancharIndex/charLength(Android 8+; mesin yang tidak melaporkan posisi kata tidak mengirimnya).pause()/resume(): Mesin Android tidak bisa menjeda di tengah kata, jadipause()menghentikannya danresume()mengucapkan sisa kalimat dari kata terakhir yang dilaporkan mesin (eventpause/resumeterpicu). Pada mesin yang tidak melaporkan posisi kata,resume()memulai ucapan itu lagi dari awal.speakingtetaptruesaat dijeda;pendingbernilaitruesaat ucapan yang mengantre menunggu.cancel()terpicuerrordenganerror: 'interrupted'pada ucapan yang sedang diucapkan dan'canceled'pada yang mengantre, sesuai standar - jangan tampilkan itu sebagai kegagalan.- Jika ponsel tidak memiliki data suara untuk bahasa tersebut, mesin mungkin tetap berbicara dalam bahasa bawaannya. Periksa
getVoices()untuk bahasa itu lebih dulu. - Event mentah di balik ini adalah
appmint:tts(lihatttsSpeak). Anda tidak membutuhkannya saat memakai API ini.
__srAbort jembatan#
window.WebToApk.__srAbort(id: String)
SpeechRecognition.abort(): berhenti seketika, buang.
Contoh
Didokumentasikan bersama WebToApk.__srStart - contoh di sana menunjukkan yang ini juga.
Transport internal di balik webkitSpeechRecognition / SpeechRecognition (mulai, berhenti, batalkan, dan apakah ada pengenal di ponsel). Halaman memakai API standar; jangan panggil ini secara langsung, karena metode __ dapat berubah tanpa pemberitahuan.
Hasil: __srStart(id, options) mengembalikan "" saat mulai mendengarkan, atau nama kesalahan Web Speech (not-allowed, service-not-allowed). Semua setelah itu tiba sebagai event appmint:sr: {id, type} untuk start/audiostart/speechstart/speechend/audioend/end, {id, type:'result', final, alternatives:[{transcript, confidence}]}, dan {id, type:'error', error}. Membutuhkan: mikrofon (diaktifkan dari bentuk panggilan).
Gunakan API publik:
const rec = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
rec.onresult = (e) => console.log(e.results[0][0].transcript);
rec.start();Dikte berkelanjutan dengan teks langsung dan bahasa:
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();
}Laporkan kesalahan seperti mikrofon yang ditolak:
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');Catatan: Diimplementasikan di shell aplikasi (SpeechRecognitionBridge.kt) di atas SpeechRecognizer Android. __srStart ditolak untuk halaman yang bukan milik aplikasi.
__srAvailable jembatan#
window.WebToApk.__srAvailable(): Boolean
Apakah layanan pengenalan suara terpasang (webkitSpeechRecognition hanya ada bila demikian).
Contoh
Didokumentasikan bersama WebToApk.__srStart - contoh di sana menunjukkan yang ini juga.
Transport internal di balik webkitSpeechRecognition / SpeechRecognition (mulai, berhenti, batalkan, dan apakah ada pengenal di ponsel). Halaman memakai API standar; jangan panggil ini secara langsung, karena metode __ dapat berubah tanpa pemberitahuan.
Hasil: __srStart(id, options) mengembalikan "" saat mulai mendengarkan, atau nama kesalahan Web Speech (not-allowed, service-not-allowed). Semua setelah itu tiba sebagai event appmint:sr: {id, type} untuk start/audiostart/speechstart/speechend/audioend/end, {id, type:'result', final, alternatives:[{transcript, confidence}]}, dan {id, type:'error', error}. Membutuhkan: mikrofon (diaktifkan dari bentuk panggilan).
Gunakan API publik:
const rec = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
rec.onresult = (e) => console.log(e.results[0][0].transcript);
rec.start();Dikte berkelanjutan dengan teks langsung dan bahasa:
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();
}Laporkan kesalahan seperti mikrofon yang ditolak:
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');Catatan: Diimplementasikan di shell aplikasi (SpeechRecognitionBridge.kt) di atas SpeechRecognizer Android. __srStart ditolak untuk halaman yang bukan milik aplikasi.
__srStart jembatan#
window.WebToApk.__srStart(id: String, optionsJson: String): String
SpeechRecognition.start(): "" saat dimulai (event tiba sebagai `appmint:sr`), jika tidak nama kesalahan Web Speech. Dibatasi origin: apa yang diucapkan pengguna adalah data pengguna.
Contoh
Transport internal di balik webkitSpeechRecognition / SpeechRecognition (mulai, berhenti, batalkan, dan apakah ada pengenal di ponsel). Halaman memakai API standar; jangan panggil ini secara langsung, karena metode __ dapat berubah tanpa pemberitahuan.
Hasil: __srStart(id, options) mengembalikan "" saat mulai mendengarkan, atau nama kesalahan Web Speech (not-allowed, service-not-allowed). Semua setelah itu tiba sebagai event appmint:sr: {id, type} untuk start/audiostart/speechstart/speechend/audioend/end, {id, type:'result', final, alternatives:[{transcript, confidence}]}, dan {id, type:'error', error}. Membutuhkan: mikrofon (diaktifkan dari bentuk panggilan).
Gunakan API publik:
const rec = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
rec.onresult = (e) => console.log(e.results[0][0].transcript);
rec.start();Dikte berkelanjutan dengan teks langsung dan bahasa:
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();
}Laporkan kesalahan seperti mikrofon yang ditolak:
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');Catatan: Diimplementasikan di shell aplikasi (SpeechRecognitionBridge.kt) di atas SpeechRecognizer Android. __srStart ditolak untuk halaman yang bukan milik aplikasi.
__srStop jembatan#
window.WebToApk.__srStop(id: String)
SpeechRecognition.stop(): berhenti mendengarkan, serahkan apa yang terdengar.
Contoh
Didokumentasikan bersama WebToApk.__srStart - contoh di sana menunjukkan yang ini juga.
Transport internal di balik webkitSpeechRecognition / SpeechRecognition (mulai, berhenti, batalkan, dan apakah ada pengenal di ponsel). Halaman memakai API standar; jangan panggil ini secara langsung, karena metode __ dapat berubah tanpa pemberitahuan.
Hasil: __srStart(id, options) mengembalikan "" saat mulai mendengarkan, atau nama kesalahan Web Speech (not-allowed, service-not-allowed). Semua setelah itu tiba sebagai event appmint:sr: {id, type} untuk start/audiostart/speechstart/speechend/audioend/end, {id, type:'result', final, alternatives:[{transcript, confidence}]}, dan {id, type:'error', error}. Membutuhkan: mikrofon (diaktifkan dari bentuk panggilan).
Gunakan API publik:
const rec = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
rec.onresult = (e) => console.log(e.results[0][0].transcript);
rec.start();Dikte berkelanjutan dengan teks langsung dan bahasa:
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();
}Laporkan kesalahan seperti mikrofon yang ditolak:
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');Catatan: Diimplementasikan di shell aplikasi (SpeechRecognitionBridge.kt) di atas SpeechRecognizer Android. __srStart ditolak untuk halaman yang bukan milik aplikasi.
__ttsSpeak jembatan#
window.WebToApk.__ttsSpeak(json: String)
Fungsi speak lengkap dari polyfill speechSynthesis: `{text, lang, rate, pitch, volume (0-1), voice (nama dari getVoices(), atau ''), id}`. [ttsSpeak] tetap ada untuk halaman yang memanggil bridge secara langsung; tidak memiliki volume atau suara.
Contoh
Transport internal di balik speechSynthesis.speak(utterance): ucapan lengkap - teks, bahasa, kecepatan, nada, volume, dan suara yang dipilih - sebagai satu string JSON. Halaman memakai API speechSynthesis standar; jangan panggil ini secara langsung.
Hasil: tidak ada. Kemajuan tiba sebagai event appmint:tts, yang diubah lapisan speechSynthesis menjadi event start / boundary / end / error milik ucapan. Membutuhkan: tidak ada.
API standar yang dibawa ini:
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);
}Pemilih suara yang dipilih pengguna sekali; setiap ucapan berikutnya memakai suara persis itu:
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);
}Aba-aba latihan: pelan dan cepat untuk hitung mundur, volume penuh dan lebih tinggi untuk pergantian:
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);Catatan: JSON-nya adalah {text, lang, rate, pitch, volume, voice, id} (voice adalah nama dari getVoices() atau ''). ttsSpeak(text, lang, rate, pitch, id) yang lebih lama tetap ada untuk halaman yang memanggil bridge secara langsung; tidak memiliki volume atau suara.
ttsCancel jembatan#
window.WebToApk.ttsCancel()
Mendukung polyfill window.speechSynthesis, yang dipasang saat dokumen dimulai di setiap frame - halaman harus memakai API speechSynthesis STANDAR dan ini akan dipanggil untuk mereka. Android WebView tidak menyertakan speechSynthesis yang berfungsi, itulah sebabnya pengalihan ini ada.
Dijelaskan oleh grupnya, Text-to-speech, bukan secara terpisah.
Contoh
Menghentikan ucapan saat itu juga dan membuang semua yang masih menunggu untuk diucapkan. Halaman biasanya memanggil speechSynthesis.cancel() standar, yang memanggil ini untuk Anda.
Mengembalikan: tidak ada. Membutuhkan: tidak ada.
Cara publik (gunakan ini):
document.getElementById('stop-reading').addEventListener('click', function () {
if ('speechSynthesis' in window) speechSynthesis.cancel();
});Panggilan mentah:
if (window.WebToApk && typeof window.WebToApk.ttsCancel === 'function') {
window.WebToApk.ttsCancel();
}Ucapkan hanya status terbaru dan buang yang lebih lama yang masih mengantre (pelacak pengiriman, skor langsung):
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 offCatatan: Ucapan yang terpotong atau dibatalkan tidak mengirim event appmint:tts end atau error, jadi onend sebuah ucapan tidak berjalan setelah dibatalkan. Jika Anda melacak id ttsSpeak mentah sendiri, lupakan id itu saat Anda memanggil ttsCancel().
ttsGetVoices jembatan#
window.WebToApk.ttsGetVoices(): String
Array JSON suara yang terpasang: [{name, lang, default}]. Kosong sampai mesin selesai inisialisasi - halaman mendapat 'voiceschanged' saat itu dan mengueri ulang, persis seperti kontrak getVoices() asinkron Chrome.
Contoh
Mendaftar suara text-to-speech yang terpasang di ponsel. Halaman biasanya memakai speechSynthesis.getVoices() standar, yang memanggil ini untuk Anda.
Hasil: string JSON, sinkron: [{ "name": "en-us-x-sfg-local", "lang": "en-US", "default": false }, ...]. Nilainya "[]" sampai mesin dimulai. Membutuhkan: tidak ada.
Cara publik (gunakan ini):
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;
}Panggilan mentah (ingat 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;
}
});Berbicara dalam bahasa ponsel bila suara untuknya terpasang, jika tidak biarkan mesin memakai suara bawaannya:
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');
}Catatan: lang adalah tag BCP-47 seperti en-US atau ta-IN. name sebuah suara adalah id milik mesin dan tidak dapat dipilih menurut nama saat berbicara; hanya bahasanya yang dipakai.
ttsIsSpeaking jembatan#
window.WebToApk.ttsIsSpeaking(): Boolean
Mendukung polyfill window.speechSynthesis, yang dipasang saat dokumen dimulai di setiap frame - halaman harus memakai API speechSynthesis STANDAR dan ini akan dipanggil untuk mereka. Android WebView tidak menyertakan speechSynthesis yang berfungsi, itulah sebabnya pengalihan ini ada.
Dijelaskan oleh grupnya, Text-to-speech, bukan secara terpisah.
Contoh
Memberi tahu apakah mesin text-to-speech ponsel sedang berbicara saat ini. Halaman biasanya memakai speechSynthesis.speaking atau onend milik ucapan sebagai gantinya.
Hasil: true / false, sinkron. false sebelum mesin dimulai. Membutuhkan: tidak ada.
Cara publik (gunakan ini):
if ('speechSynthesis' in window && speechSynthesis.speaking) {
speechSynthesis.cancel();
}Panggilan mentah menanyakan langsung ke mesin, jadi akurat meskipun ucapan dimulai dengan mentah 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);Tunggu sampai aplikasi berhenti berbicara sebelum Anda mulai merekam, agar mikrofon tidak menangkap suaranya sendiri:
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
});Catatan: Jangan melakukan polling cepat; event (onend, atau appmint:tts dengan event: 'end') lebih baik bila Anda memulai ucapan sendiri.
ttsSpeak jembatan#
window.WebToApk.ttsSpeak(text: String, lang: String, rate: Double, pitch: Double, utteranceId: String)
Mendukung polyfill window.speechSynthesis, yang dipasang saat dokumen dimulai di setiap frame - halaman harus memakai API speechSynthesis STANDAR dan ini akan dipanggil untuk mereka. Android WebView tidak menyertakan speechSynthesis yang berfungsi, itulah sebabnya pengalihan ini ada.
Dijelaskan oleh grupnya, Text-to-speech, bukan secara terpisah.
Contoh
Mulai mengucapkan teks dengan mesin text-to-speech ponsel. Halaman biasanya memakai API speechSynthesis standar, yang memanggil ini untuk Anda.
Hasil: tidak ada. Kemajuan tiba kemudian sebagai event appmint:tts (dan hook window.onAppMintTts(detail)) dengan detail = { id, event }, di mana event adalah 'start', 'end' atau 'error', dan id adalah utteranceId yang Anda berikan. Membutuhkan: tidak ada.
Cara publik (gunakan ini):
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);
}Panggilan mentah, bila Anda ingin id sendiri. Argumen: 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'); });Bacakan daftar langkah secara berurutan dengan id Anda sendiri, dan sorot langkah yang sedang diucapkan:
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);
});
});Catatan: Ucapan mengantre satu demi satu. lang boleh '' (suara bawaan mesin); rate dan pitch dibatasi ke 0,1-4. Jika mesin masih dimulai, teks menunggu dan diucapkan saat siap; jika mesin tidak bisa dimulai, setiap ucapan yang menunggu mendapat 'error'. Gunakan awalan id Anda sendiri; id yang diawali wta_u milik lapisan speechSynthesis. Di Android 8+ appmint:tts juga membawa {id, event: 'boundary', charIndex, charLength} sebelum setiap kata. Panggilan mentah ini tidak punya volume atau suara - speechSynthesis punya keduanya.
ttsWarmUp jembatan#
window.WebToApk.ttsWarmUp()
Mendukung polyfill window.speechSynthesis, yang dipasang saat dokumen dimulai di setiap frame - halaman harus memakai API speechSynthesis STANDAR dan ini akan dipanggil untuk mereka. Android WebView tidak menyertakan speechSynthesis yang berfungsi, itulah sebabnya pengalihan ini ada.
Dijelaskan oleh grupnya, Text-to-speech, bukan secara terpisah.
Contoh
Memulai mesin text-to-speech ponsel lebih awal, agar speak() pertama tanpa jeda dan getVoices() terisi. Lapisan speechSynthesis aplikasi sudah memanggil ini saat halaman dimulai, jadi halaman hampir tidak pernah membutuhkannya.
Hasil: tidak ada. Saat mesin siap, event appmint:tts terpicu dengan detail = { id: '', event: 'voiceschanged' } (dan speechSynthesis.onvoiceschanged berjalan). Membutuhkan: tidak ada.
Cara publik (gunakan ini): cukup baca suara saat sudah siap.
if ('speechSynthesis' in window) {
speechSynthesis.onvoiceschanged = function () {
console.log('voices:', speechSynthesis.getVoices().length);
};
}Panggilan mentah, lalu tunggu event siap:
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
}Mulai mesin saat layar "Baca dengan suara" terbuka dan aktifkan tombolnya setelah mesin siap:
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;
});Catatan: voiceschanged terpicu sekali, saat mesin selesai dimulai. Jika sudah dimulai (misalnya karena lapisan speechSynthesis memanaskannya), Anda tidak akan mendapatkannya lagi; panggil ttsGetVoices() secara langsung.