0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

見切り発車と2024の振り返りAdvent Calendar 2024

Day 6

見切り発車で平仮名の学習アプリを作る【6日目】

Posted at

2024年のアドベントカレンダー6日目の記事です。

音声入力を実施したい#2

5日目に引き続き音声入力処理を作成します。
音声入力をするにあたってリアルタイムで発声内容を描画していくことも考えましたが、テストと同じように回答した後に採点したほうが(つくりやすくて)いいかなと思ったのでリアルタイムでの描画は行わないこととしました。

それに伴い、web speech apiの制御はuseStateではなくuseRefを利用することにしました。
(useStateとuseRefの違いは再レンダリングの有無くらいのざっくり知識しかないのでこの選択が正しいかは不明です)

ドキュメントを見た感じだと以下のイベントがあれば動かせそうだったため、useRefを利用してそのあたりの制御を行っていきます。

1.start
2.error
3.result
4.end

また、結果を格納するstateも追加して最終的に以下のようなコードで落ち着きました。

App.js
import './App.css';
import { Provider } from './components/ui/provider';
import { Box, AbsoluteCenter, Heading, VStack, HStack } from '@chakra-ui/react';
import { useState, useRef } from 'react';
import { Button } from './components/ui/button';

function App() {
  const [question, setQuestion] = useState('あとですぷしからしゅとくするようにします');
  const [answer, setAnswer] = useState('ここがおんせいにゅうりょくでかわるところ');
  const [isRecording, setIsRecording] = useState(false);
  const recognitionRef = useRef(null);

  const startRecording = () => {
    if (!('webkitSpeechRecognition' in window)) {
      alert('なんかだめみたい。おじさんにきいてみて');
      return;
    }

    recognitionRef.current = new window.webkitSpeechRecognition();
    recognitionRef.current.lang = 'ja-JP';
    recognitionRef.current.continuous = false;
    recognitionRef.current.interimResults = false;

    recognitionRef.current.onstart = () => {
      setIsRecording(true);
    };

    recognitionRef.current.onresult = (event) => {
      const transcript = event.results[0][0].transcript;
      setAnswer(transcript);
    };

    recognitionRef.current.onerror = (event) => {
      console.error(event.error);
    };

    recognitionRef.current.onend = () => {
      setIsRecording(false);
    };

    recognitionRef.current.start();
  };

  const stopRecording = () => {
    if (recognitionRef.current) {
      recognitionRef.current.stop();
    }
  };

  return (
    <Provider>
      <Box bg="blue.100" w="100vw" h="100vh">
        <AbsoluteCenter>
          <VStack gap="20">
            <Heading size="5xl">
              {question}
            </Heading>
            <HStack gap="20">
              <Button size="2xl" variant="outline" borderColor="green.600" color="green.600"onClick={isRecording ? stopRecording : startRecording}>
                {isRecording ? "こたえた" : "こたえる"}
              </Button>
              <Button size="2xl" variant="outline" borderColor="orange.600" color="orange.600">
                わからない
              </Button>
            </HStack>
            <Heading size="5xl">
              {answer}
            </Heading>
          </VStack>
        </AbsoluteCenter>
      </Box>
    </Provider>
  );
}

export default App;

結果として音声入力自体は無事に動きました。

2.gif

ただし回答が自動的に漢字になってしまったりするので、ここは最終的にすべて平仮名で保持されるように変換する必要があり、今後どこかで改修しようかとおもいます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?