Kagami / vmsg

:musical_note: Library for creating voice messages
https://kagami.github.io/vmsg/
Creative Commons Zero v1.0 Universal
348 stars 58 forks source link

Blob comes back null after stop recording React #56

Open rbracco opened 3 years ago

rbracco commented 3 years ago

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/vmsg@0.3.0/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
vinters768 commented 2 weeks ago
import { Recorder } from "vmsg";

const recorder = new Recorder({
  wasmURL: "https://unpkg.com/vmsg@0.3.0/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.