ref – https://codesandbox.io/s/audio-experiments-w7yz8?file=/src/App.js:0-2208
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
import React, { useState, useRef } from "react"; import "./styles.css"; export default function App() { const [stream, setStream] = useState({ access: false, recorder: null, error: "" }); const [recording, setRecording] = useState({ active: false, available: false, url: "" }); const chunks = useRef([]); function getAccess() { navigator.mediaDevices .getUserMedia({ audio: true }) .then((mic) => { let mediaRecorder; try { mediaRecorder = new MediaRecorder(mic, { mimeType: "audio/webm" }); } catch (err) { console.log(err); } const track = mediaRecorder.stream.getTracks()[0]; track.onended = () => console.log("ended"); mediaRecorder.onstart = function () { setRecording({ active: true, available: false, url: "" }); }; mediaRecorder.ondataavailable = function (e) { console.log("data available"); chunks.current.push(e.data); }; mediaRecorder.onstop = async function () { console.log("stopped"); const url = URL.createObjectURL(chunks.current[0]); chunks.current = []; setRecording({ active: false, available: true, url }); }; setStream({ ...stream, access: true, recorder: mediaRecorder }); }) .catch((error) => { console.log(error); setStream({ ...stream, error }); }); } return ( <div className="App"> {stream.access ? ( <div className="audio-container"> <button className={recording.active ? "active" : null} onClick={() => !recording.active && stream.recorder.start()} > Start Recording </button> <button onClick={() => stream.recorder.stop()}>Stop Recording</button> {recording.available && <audio controls src={recording.url} />} </div> ) : ( <button onClick={getAccess}>Get Mic Access</button> )} </div> ); } |