Skip to content

Commit

Permalink
Merge pull request #147 from Sunbird-ALL/all-1.2-tn-dev
Browse files Browse the repository at this point in the history
All 1.2 tn dev
  • Loading branch information
gouravmore authored Aug 23, 2024
2 parents 1e114d3 + a1e04c1 commit 16a9025
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 84 deletions.
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"canvas-confetti": "^1.9.2",
"character-error-rate": "^1.1.4",
"classnames": "^2.3.1",
"eslint-plugin-import": "^2.28.0",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.1",
"faker": "^5.5.3",
"homophones": "^1.0.1",
"jwt-decode": "^4.0.0",
Expand All @@ -38,15 +41,13 @@
"react-virtualized": "^9.22.3",
"react-virtualized-auto-sizer": "^1.0.6",
"react-window": "^1.8.6",
"recordrtc": "^5.6.2",
"redux": "^4.1.2",
"redux-saga": "^1.1.3",
"sass": "^1.44.0",
"split-graphemes": "^0.5.0",
"use-sound": "^4.0.1",
"web-vitals": "^2.1.4",
"eslint-plugin-import": "^2.28.0",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.1"
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
Expand Down Expand Up @@ -87,16 +88,16 @@
]
},
"devDependencies": {
"@mui/styles": "^5.15.10",
"eslint": "^7.32.0",
"prettier": "^2.3.2",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"husky": "^9.0.11",
"lint-staged": "^11.0.0",
"react": "^18.2.0",
"@mui/styles": "^5.15.10"
"prettier": "^2.3.2",
"react": "^18.2.0"
},
"lint-staged": {
"lint-staged": {
"src/**/*.{js,jsx}": [
"npx eslint --fix",
"npx prettier --write"
Expand Down
182 changes: 106 additions & 76 deletions src/utils/AudioCompare.js
Original file line number Diff line number Diff line change
@@ -1,87 +1,104 @@
import React, { useState } from "react";
import AudioAnalyser from "react-audio-analyser";
import React, { useState, useEffect, useRef } from "react";
import RecordRTC from "recordrtc";
import { Box } from "@mui/material";
import { ListenButton, RetryIcon, SpeakButton, StopButton } from "./constants";
import RecordVoiceVisualizer from "./RecordVoiceVisualizer";
import useAudioDetection from "./useAudioDetection";

const AudioRecorderCompair = (props) => {
const { startDetection, stopDetection, isSilent, isRunning, audioDetected } = useAudioDetection();
const AudioRecorder = (props) => {
const [isRecording, setIsRecording] = useState(false);
const [status, setStatus] = useState("");
const [audioSrc, setAudioSrc] = useState("");
const [recordingInitialized, setRecordingInitialized] = useState(false);
const audioType = "audio/wav";
const [audioBlob, setAudioBlob] = useState(null);
const recorderRef = useRef(null);
const mediaStreamRef = useRef(null);

const controlAudio = async (status) => {
if (status === "recording") {
await startDetection();
} else {
stopDetection();
}
setStatus(status);
};

const resetRecording = () => {
setAudioSrc("");
setRecordingInitialized(false);
};
useEffect(() => {
// Cleanup when component unmounts
return () => {
if (recorderRef.current) {
recorderRef.current.destroy();
}
if (mediaStreamRef.current) {
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
}
};
}, []);

const handleMic = async () => {
const startRecording = async () => {
setStatus("recording");
if (props.setEnableNext) {
props.setEnableNext(false);
}
document.getElementById("startaudio_compair").click();
resetRecording();
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaStreamRef.current = stream;

// Use RecordRTC with specific configurations to match the blob structure
recorderRef.current = new RecordRTC(stream, {
type: "audio",
mimeType: "audio/wav", // Ensuring the same MIME type as AudioRecorderCompair
recorderType: RecordRTC.StereoAudioRecorder, // Use StereoAudioRecorder for better compatibility
numberOfAudioChannels: 1, // Match the same number of audio channels
desiredSampRate: 16000, // Adjust the sample rate if necessary to match
});

recorderRef.current.startRecording();

setIsRecording(true);
} catch (err) {
console.error("Failed to start recording:", err);
}
};

const handleStop = () => {
const stopRecording = () => {
setStatus("inactive");
if (recorderRef.current) {
recorderRef.current.stopRecording(() => {
const blob = recorderRef.current.getBlob();

if (blob) {
setAudioBlob(blob);
saveBlob(blob); // Persist the blob
} else {
console.error("Failed to retrieve audio blob.");
}

// Stop the media stream
if (mediaStreamRef.current) {
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
}

setIsRecording(false);
});
}
if (props.setEnableNext) {
props.setEnableNext(true);
}
document.getElementById("stopaudio_compair").click();
};

const audioProps = {
audioType,
status,
audioSrc,
timeslice: 1000,
startCallback: (e) => {
setAudioSrc("");
setRecordingInitialized(true);
props.setRecordedAudio("");
},
pauseCallback: (e) => {},
stopCallback: (e) => {
const temp_audioSrc = window.URL.createObjectURL(e);
setAudioSrc(temp_audioSrc);
if (!audioDetected) {
props?.setOpenMessageDialog({
message: "Please Speak Louder and Clear",
isError: true,
});
if (props.setEnableNext) {
props.setEnableNext(false);
}
} else {
props.setRecordedAudio(temp_audioSrc);
}
setRecordingInitialized(false);
},
onRecordCallback: (e) => {},
errorCallback: (err) => {},
backgroundColor: "hsla(0, 100%, 0%, 0)",
strokeColor: "#73DD24",
const saveBlob = (blob) => {
const url = window.URL.createObjectURL(blob);
props?.setRecordedAudio(url);
};

return (
<div>
<div>
{(() => {
if (status === "recording" && recordingInitialized) {
if (status === "recording") {
return (
<div style={{ display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center", margin: "0 auto" }}>
<Box sx={{ cursor: "pointer", height: "38px" }} onClick={handleStop}>
<div
style={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
margin: "0 auto",
}}
>
<Box
sx={{ cursor: "pointer", height: "38px" }}
onClick={stopRecording}
>
<StopButton />
</Box>
<Box style={{ marginTop: "50px", marginBottom: "50px" }}>
Expand All @@ -91,17 +108,33 @@ const AudioRecorderCompair = (props) => {
);
} else {
return (
<div style={{ display: "flex", justifyContent: "space-between", margin: "0 auto" }} className="game-action-button">
<div
style={{
display: "flex",
justifyContent: "space-between",
margin: "0 auto",
}}
className="game-action-button"
>
{(!props.dontShowListen || props.recordedAudio) && (
<>
{!props.pauseAudio ? (
<div role="button" tabIndex="0" onClick={() => { props.playAudio(true); }} aria-label="Play audio">
<div
onClick={() => {
props.playAudio(true);
}}
>
<Box sx={{ cursor: "pointer" }}>
<ListenButton />
</Box>
</div>
) : (
<Box sx={{ cursor: "pointer" }} onClick={() => { props.playAudio(false); }}>
<Box
sx={{ cursor: "pointer" }}
onClick={() => {
props.playAudio(false);
}}
>
<StopButton />
</Box>
)}
Expand All @@ -110,7 +143,15 @@ const AudioRecorderCompair = (props) => {

<div>
{!props.showOnlyListen && (
<Box marginLeft={!props.dontShowListen || props.recordedAudio ? "32px" : "0px"} sx={{ cursor: "pointer" }} onClick={handleMic}>
<Box
marginLeft={
!props.dontShowListen || props.recordedAudio
? "32px"
: "0px"
}
sx={{ cursor: "pointer" }}
onClick={startRecording}
>
{!props.recordedAudio ? <SpeakButton /> : <RetryIcon />}
</Box>
)}
Expand All @@ -119,20 +160,9 @@ const AudioRecorderCompair = (props) => {
);
}
})()}
<AudioAnalyser {...audioProps} className="hide">
<div className="btn-box">
<br />
<button className="btn" id="startaudio_compair" onClick={() => controlAudio("recording")}>
Start
</button>
<button className="btn" id="stopaudio_compair" onClick={() => controlAudio("inactive")}>
Stop
</button>
</div>
</AudioAnalyser>
</div>
</div>
);
};

export default AudioRecorderCompair;
export default AudioRecorder;

0 comments on commit 16a9025

Please sign in to comment.