@MichelB (Michel Bouchet)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

NextJS アプリで、音声の扱い

下記のコードには問題があります。

'use client'

import {useState,useRef,useEffect} from "react";


const AudioRecorderPlayer = () => {
  const [permission, setPermission] = useState(false);
  const [recordComplete, setRcdComplete] = useState(false);
  const [stream, setStream] = useState<MediaStream>();
  const [recordingStatus, setRecordingStatus] = useState("inactive");
  const mrRef = useRef<MediaRecorder | null>(null);
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const audioChunksRef = useRef<Blob[]>([]);
  const [audio, setAudio] = useState('');

  const dataType = "video/webm";

  const getMicrophonePermission = async () => {
    if ("MediaRecorder" in window) {
      try {
        const streamData = await navigator.mediaDevices.getUserMedia({
            audio: true,
            video: false,
        });
        setPermission(true);
        setStream(streamData);
      } catch (err) {
        alert("err.message");
      }
    } else {
      alert("The MediaRecorder API is not supported in your browser.");
    }
  }; /* End of getMicrophonePermission */


  const startRecording = async () => {
      URL.revokeObjectURL(audio);
      mrRef.current = null
      audioChunksRef.current = []
  
      setRecordingStatus("recording");
      const mediaRecorder = new MediaRecorder(stream!, {
          mimeType: dataType,
          audioBitsPerSecond: 16*44100
      });
      mrRef.current = mediaRecorder;
  
      let localAudioChunks = [];//[Blob];
      mediaRecorder.start()
      mediaRecorder.ondataavailable = (event) => {
          if (typeof event.data === "undefined") return;
          if (event.data.size === 0) return;
          localAudioChunks.push(event.data);
          audioChunksRef.current.push(event.data);
      };
  }; /* End of startRecording */


  const stopRecording = () => {
      setRecordingStatus("inactive");
      if (!mrRef.current) return
      mrRef.current?.stop();
      mrRef.current.onstop = async () => {
          console.log("Here dataType = ",dataType)
          const audioBlob = new Blob(audioChunksRef.current, {type: dataType});
          const audioUrl = URL.createObjectURL(audioBlob);
          setAudio(audioUrl);
          setRcdComplete(true);
      };
  }; /* End of stopRecording */


  const handlePlay = () => {
        if (audioRef.current) {
            console.log('currentTime-handlePlay(1) =',audioRef.current.currentTime)
            audioRef.current.play();
            console.log('currentTime-handlePlay(2) =',audioRef.current.currentTime)
        }
  }; /* End of handlePlay */


  const handleEnd = () => {
        console.log('Passage +',audioRef.current?'OK':'à vide')
        if (audioRef.current) {
            console.log('currentTime(1) =',audioRef.current.currentTime)
            audioRef.current.currentTime = 0.0;
            console.log('currentTime(2) =',audioRef.current.currentTime)
        }
        console.log('Passage +',audioRef.current?'OK':'à vide')
  }; /* End of handleEnd */


  return (
    <div>
      <main>
          {!permission ? (
              <button onClick={getMicrophonePermission} type="button">
                  Get Microphone
              </button>
          ): null}
          {permission && recordingStatus === "inactive" ? (
          <button onClick={startRecording} type="button">
            Start Recording
                    </button>
                ) : null}
                {recordingStatus === "recording" ? (
            <button onClick={stopRecording} type="button">
                        Stop Recording
                    </button>
                ) : null}
        <audio src={audio}
                    ref={audioRef}
                    id="audio-player"
                    onPlay={handlePlay}
                    onEnded={handleEnd}
                    onEmptied = {(event) => {console.log('--onEmptied--')}}
                    onCanPlayThrough = {(event) => {console.log('--onCanPlayThrough--')}}
                    controls />
      </main>
    </div>
  );
}; /* End of AudioRecorderPlayer */

export default AudioRecorderPlayer;

この NextJS コンポネントはユーザに音声録音をやらせ、音声の再生もできます。

たまには次のような不具合になります。

録音した後2回目から再生すると、再生の前にほぼ20秒くらい待たされます。
なぜでしょうか。

NextJS アプリで、こういう音声の扱いをするのは初めてなんで、とこかでコードを間違っているかも知れません。

0 likes

Your answer might help someone💌