CakePHP5入門【コラム⑬】faviconと音声入力
A子
ちなみに、解像度は256×256ドットね
C菜
B美
A子
C菜
ブラウザを強制更新([Ctrl]+[F5])すると~
A子
あ、あとさー
スマホでチャットするときってフリック入力してるんだけど、これって声で入力することはできないかな?
B美
PHP言語じゃなくて、JavaScriptのコードになるけど…
A子
んじゃ、ぜひやろう!
(いちいち入力するのが面倒くさいんだもん…(苦笑))
B美
一つは「マイクが存在するかのチェック関数」で、もう一つは「マイク(音声)入力を処理する関数」ね
C菜
一つ目の「マイクが存在するかのチェック関数」はいつ実行するのでしょうか~?
B美
チャットページがロードされた際(画面表示されたとき)に実行されるよう、「DOMContentLoaded」イベントに追加すれば良いのよ
A子
B美
まずは「マイクが存在するかのチェック関数」だけど…
|
function checkMicrophone() {
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { document.getElementById('mic-status').textContent = "(音声入力チェックはサポートされていません)"; return; } navigator.mediaDevices.enumerateDevices() .then(function(devices) { const hasMicrophone = devices.some(device => device.kind === 'audioinput'); if (hasMicrophone) { //マイクがある場合、ボタンを表示 document.getElementById('start-recognition-btn').style.display = 'inline'; } else { document.getElementById('mic-status').textContent = "(マイクが見つかりませんでした)"; } }) .catch(function(err) { document.getElementById('mic-status').textContent = "(エラーが発生しました)"; }); } |
あ、上記コードを見れば分かると思うけど、HTML要素として「id」が「mic-status」であるタグ(pタグまたはdivタグ)と、「id」が「start-recognition-btn」であるボタンが必要だからね
C菜
|
<div style="padding: 10px;">
<div id="mic-status"></div> <button id="start-recognition-btn" class="button is-link">音声入力開始</button> </div> |
という感じで、いかがでしょう~?
B美
ボタンの初期状態は「非表示」にしておいてね
それとボタンの「onclick」イベントに(このあと記述する)「startRecognition」関数を割り当てておいてちょうだい
C菜
|
<div style="padding: 10px;">
<div id="mic-status"></div> <button id="start-recognition-btn" onclick="startRecognition()" style="display: none;" class="button is-link">音声入力開始</button> </div> |
で、どうでしょうか~?
B美
それじゃ、チャットページが表示されたタイミングで、この関数(マイクが存在するかのチェック関数)が実行されるようにしましょう
てか、すでに存在する「DOMContentLoaded」イベントの最後に一行追加するだけなんだけどね
|
document.addEventListener("DOMContentLoaded", function () {
const messageInput = document.getElementById("message"); const sendButton = document.getElementById("sendBtn"); //Enterキーで送信(Shift + Enterで改行) messageInput.addEventListener("keydown", function (event) { if (event.key === "Enter" && !event.shiftKey) { event.preventDefault(); sendButton.click(); } }); checkMicrophone(); }); |
C菜
B美
「navigator.mediaDevices」という機能って、HTTPプロトコルのもとでは実行できないから注意してね
(これってマイクなどのデバイスリストを取得する機能なんだけど、「HTTPSの環境下じゃないと動作しない」決まりだから…)
なお、HTTPアクセスの場合は「(音声入力チェックはサポートされていません)」って表示されるようにしているわ
(下記はHTTPS環境なので、「(マイクが見つかりませんでした)」を表示 ← マイクの無いデスクトップPCなので…)
A子
B美
あと、入力欄のカーソル位置に挿入するための関数「insertTextAtCursor」を別に作成しておきましょう
(その関数を「startRecognition」関数の中から呼び出している…ってこと)
|
function startRecognition() {
if (!('webkitSpeechRecognition' in window)) { document.getElementById('mic-status').textContent = "(音声入力はサポートされていません)"; return; } const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; const recognition = new SpeechRecognition(); recognition.lang = 'ja-JP'; //日本語を指定 recognition.interimResults = false; //暫定結果を無効 recognition.maxAlternatives = 1; //最大の候補数を設定 recognition.onstart = function() { document.getElementById('start-recognition-btn').style.display = 'none'; document.getElementById('mic-status').textContent = "(音声入力中)"; }; recognition.onresult = function(event) { const speechResult = event.results[0][0].transcript; insertTextAtCursor(speechResult); }; recognition.onerror = function(event) { document.getElementById('mic-status').textContent = "(エラー: " + event.error + ")"; }; recognition.onend = function() { document.getElementById('start-recognition-btn').style.display = 'inline'; document.getElementById('mic-status').textContent = ""; }; recognition.start(); } function insertTextAtCursor(text) { const inputField = document.getElementById('message'); const startPos = inputField.selectionStart; const endPos = inputField.selectionEnd; const currentValue = inputField.value; inputField.value = currentValue.substring(0, startPos) + text + currentValue.substring(endPos); inputField.selectionStart = inputField.selectionEnd = startPos + text.length; inputField.focus(); } |
A子
B美
強引に二つにしても良かったんだけど、「insertTextAtCursor」関数を独立させたほうが分かりやすいでしょ?
C菜
B美
マイク内蔵のノートPCからアクセスしてみるわね
A子
B美
(常に出るわけじゃなく、表示されるのは最初の一回だけだから安心してね)
C菜
A子
C菜
すぐに入力欄に埋め込まれましたよ~
(ほとんどタイムラグが無いですねぇ~)
A子
(「音声入力開始」ボタンをクリックして)「こんばんは」
C菜
A子
(「音声入力開始」ボタンをクリックして)「こんにちは」
C菜
きちんと間(カーソル位置)に挿入されました~
A子
次は、漢字変換がうまくいくかを試してみよう
(「音声入力開始」ボタンをクリックして)「これはおんせいにゅうりょくてすとです」
C菜
なにげに頭が良い感じがします~
B美
あ、ただし…
(日本語変換が割とうまく働くのは確かなんだけど)同音異義語はちょっと難しいかも…
例えば、「せんとう」が「先頭」「戦闘」「銭湯」「尖塔」等のどれかに変換されたとしても、それが自分の思ってるものとは違うかもしれないわ
A子
(自分で入力欄を修正できるように…)
まぁ、それでもめっちゃ楽なのは確かだけどね
B美
Androidスマホで使えるのは確認済みなんだけど、iPhoneで使えるかどうかは検証できていないわ
(だって持ってないんだもの)
A子


