vmsg
vmsg copied to clipboard
Blob comes back null after stop recording React
Hi, thank you for your work on vmsg. I am trying to implement a functional component version of the React demo from the README. Everything seems to work, and it's almost the same code as the example, but the blob comes back null. I am using vmsg 0.3.0, and I traced the code in vmsg.stopRecording and it seems though the worker is null even though I'm calling initWorker(). I'm probably messing up something basic with async/await or promises but I've tried to track it down with no luck. Thank you.
import React, {useState} from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import vmsg from 'vmsg'
function Recorder() {
const [recordings, setRecordings] = useState([])
const [isRecording, setIsRecording] = useState(false)
const [isLoading, setIsLoading] = useState(false)
const [isWorkerInitialized, setIsWorkerInitalized] = useState(false)
const recorder = new vmsg.Recorder({
wasmURL: "https://unpkg.com/[email protected]/vmsg.wasm"
});
const handleRecording = async() => {
setIsLoading(true)
if (isRecording){
console.log("Finish recording")
let blob = await recorder.stopRecording();
console.log("Blob", blob)
setIsRecording(false)
setIsLoading(false)
setRecordings([URL.createObjectURL(blob)])
}
else{
try {
if (!isWorkerInitialized){
await recorder.initAudio();
await recorder.initWorker();
setIsWorkerInitalized(true)
}
recorder.startRecording();
setIsRecording(true)
setIsLoading(false)
} catch (e) {
console.error(e);
setIsLoading(false)
}
}
}
return (
<>
<button disabled={isLoading} onClick={handleRecording}>
{isRecording ? "Stop" : "Record"}
</button>
<ul style={{ listStyle: "none", padding: 0 }}>
{recordings.map(url => (
<li key={url}>
<audio src={url} controls />
</li>
))}
</ul>
</>
)
}
export default Recorder
import { Recorder } from "vmsg";
const recorder = new Recorder({
wasmURL: "https://unpkg.com/[email protected]/vmsg.wasm",
});
export const RecordViewNew = () => {
const [loading, setLoading] = useState(false);
const [isRecording, setIsRecording] = useState(false);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const [recordings, setRecordings] = useState<any[]>([]);
const record = async () => {
setLoading(true);
if (isRecording) {
const blob = await recorder.stopRecording();
setIsRecording(false);
setLoading(false);
setRecordings(recordings.concat(URL.createObjectURL(blob)));
} else {
try {
await recorder.initAudio();
await recorder.initWorker();
recorder.startRecording();
setLoading(false);
setIsRecording(true);
} catch (e) {
console.error(e);
setLoading(false);
}
}
};
return (
<>
<button disabled={loading} onClick={record}>
{isRecording ? "Stop" : "Record"}
</button>
<ul style={{ listStyle: "none", padding: 0 }}>
{recordings.map((url) => (
<li key={url}>
<audio src={url} controls />
</li>
))}
</ul>
</>
);
};
If someone needs functional component.