Sunday, May 17, 2026
HomeiOS Developmentios - Microphone wavesurfer data empty for iphone safari - React

ios – Microphone wavesurfer data empty for iphone safari – React

[ad_1]

Voice recording comes empty in safari iphone all the time, my code is as under for my frequent element, its working in safari on mac and chrome simply

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

import { useRouter } from "subsequent/router";
import PropTypes from "prop-types";
import { useReactMediaRecorder } from "react-media-recorder";
import WaveSurfer from "wavesurfer.js";
import MicrophonePlugin from "wavesurfer.js/dist/plugin/wavesurfer.microphone";

import Button from "@mui/materials/Button";
import Grid from "@mui/materials/Grid";
import Typography from "@mui/materials/Typography";
import StyledButton from "../StyledButton";
import Fab from "@mui/materials/Fab";

// Icons
import MicIcon from "@mui/icons-material/Mic";
import StopIcon from "@mui/icons-material/Cease";
import DeleteIcon from "@mui/icons-material/Delete";

import Waveform from "./Waveform";

import styled from "@emotion/styled";

const FabAudio = styled(Fab)`
  background-color: #fd0d1b;
  coloration: #fff;
  &:hover {
    background-color: #fd0d1b;
    coloration: #fff;
  }
`;

const Small = styled("div")`
  font-size: 10px;
`;

perform VoiceInput({
  title,
  required,
  id,
  totalQuestions,
  primaryButtonTitle,
  secondaryButtonTitle,
  nextRoute,
  handleEndSurvey,
  handleResponse,
}) {
  const [error, setError] = useState(false);
  const [errorMessage, setErrorMessage] = useState("");
  const [blob, setBlob] = useState(null);

  const router = useRouter();

  const waveSurferRef = useRef();
  const containerRef = useRef();

  let timeout;
  let context, processor;

  const { standing, startRecording, stopRecording, mediaBlobUrl, clearBlobUrl } =
    useReactMediaRecorder({
      audio: true,
      onStop: (blobUrl, blob) => {
        console.log("Testing blob" + blob);
        setBlob(blob);
      },
    });

  const isSafari = /^((?!chrome|android).)*safari/i.check(navigator.userAgent);

  useEffect(() => {
    if (standing === "recording") {
      if (isSafari)  window.webkitAudioContext;
        context = new AudioContext();
        processor = context.createScriptProcessor(1024, 1, 1);
      
      waveSurferRef.present = WaveSurfer.create({
        container: containerRef.present,
        responsive: true,
        barWidth: 2,
        peak: 80,
        barHeight: 3,
        barMinHeight: 1,
        barRadius: 3,
        barWidth: 3,
        barGap: 5,
        cursorWidth: 0,
        waveColor: "pink",
        plugins: [MicrophonePlugin.create()],
      });

      const microphone = waveSurferRef.present.microphone;
      timeout = setTimeout(() => {
        microphone.cease();
        stopRecording();
        waveSurferRef.present.destroy();
      }, 60000);
      microphone.begin();
    }
    if (standing === "stopped") {
      const microphone = waveSurferRef.present.microphone;
      microphone.cease();
      waveSurferRef.present.destroy();
      clearTimeout(timeout);
    }

    return () => {
      if (standing === "recording") {
        const microphone = waveSurferRef.present.microphone;
        microphone.cease();
        waveSurferRef.present.destroy();
        clearTimeout(timeout);
      }
    };
  }, [status]);

  const handleNext = async () => {
    if (required && !mediaBlobUrl) {
      setError(true);
      setErrorMessage("Please document the message");
      return;
    }

    if (["recording", "paused"].consists of(standing)) {
      setError(true);
      setErrorMessage("Please cease the recording");
      return;
    }

    if (mediaBlobUrl) {
      const uniqueId =
        Date.now().toString(36) + Math.random().toString(36).substring(2);
      const audiofile = new File([blob], `${uniqueId}.webm`, {
        sort: "audio/webm",
      });
      const isLastAnswer = +id === totalQuestions ? true : false;
      const res = await handleResponse(audiofile, isLastAnswer);
      if (isLastAnswer) {
        res && handleEndSurvey();
      } else {
        res && router.push(nextRoute);
      }
    } else {
      if (+id === totalQuestions) {
        handleEndSurvey();
      } else {
        router.push(nextRoute);
      }
    }
  };

  const handlePrev = () => {
    router.again();
  };

  const removeAudio = () => {
    setError(false);
    clearBlobUrl();
    setBlob(null);
  };

  return (
    <Grid container spacing={5} peak="100%" alignItems="middle">
      {/* query part */}
      <Grid merchandise xs={12}>
        <Typography variant="h2" fontWeight={550}>
          {title}
        </Typography>
      </Grid>

      {/*Enter Part  */}
      <Grid merchandise md={2} xs={0}></Grid>
      <Grid merchandise md={8} xs={12}>
        {mediaBlobUrl && <Waveform audio={mediaBlobUrl} />}
        {["recording", "paused"].consists of(standing) && (
          <Grid container>
            <Grid merchandise xs={12} ref={containerRef}></Grid>
          </Grid>
        )}

        {mediaBlobUrl && (
          <div>
            <FabAudio aria-label="add" sx={{ mt: 2 }} onClick={removeAudio}>
              <DeleteIcon />
            </FabAudio>
          </div>
        )}

        {["idle", "stopped"].consists of(standing) && !mediaBlobUrl && (
          <>
            <FabAudio
              coloration="secondary"
              aria-label="add"
              sx={{ mt: 2 }}
              onClick={() => {
                startRecording();
                setError(false);
              }}
            >
              <MicIcon />
            </FabAudio>
            <Typography mt={2}>Hit File to Begin</Typography>
            <Small>Communicate near the microphone for higher response.</Small>
          </>
        )}
        {["recording", "paused"].consists of(standing) && (
          <>
            <FabAudio aria-label="add" onClick={stopRecording}>
              <StopIcon />
            </FabAudio>
          </>
        )}
        {error && (
          <Typography mt={2} coloration="pink">
            {errorMessage}
          </Typography>
        )}
      </Grid>

      <Grid merchandise md={2} xs={0}></Grid>

      {/* Button Part */}
      <Grid merchandise md={3} xs={0}></Grid>
      {secondaryButtonTitle && (
        <Grid merchandise md={3} xs={12}>
          <Button
            sx={{ width: "160px" }}
            variant="outlined"
            onClick={handlePrev}
          >
            {secondaryButtonTitle}
          </Button>
        </Grid>
      )}
      <Grid merchandise md={secondaryButtonTitle ? 3 : 6} xs={12}>
        <StyledButton onClick={handleNext}>
          {+id === totalQuestions ? "Submit" : primaryButtonTitle}
        </StyledButton>
      </Grid>
      <Grid merchandise md={3} xs={0}></Grid>
    </Grid>
  );
}

VoiceInput.propTypes = {
  title: PropTypes.string,
  required: PropTypes.bool,
  id: PropTypes.string,
  totalQuestions: PropTypes.quantity,
  primaryButtonTitle: PropTypes.string,
  secondaryButtonTitle: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  nextRoute: PropTypes.string,
};

export default VoiceInput;

[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments