mexili / incogly

Incogly is a video conferencing app aimed to remove any implicit bias in an interview and easing the process of remote collaboration.
https://incogly.mexili.org/
GNU Affero General Public License v3.0
28 stars 30 forks source link

Feature request: Audio Visualizer #89

Open ZohebMOPO opened 3 years ago

ZohebMOPO commented 3 years ago

Is your feature request related to a problem? Please describe.

At the time of joining the client should be able to know that how loud his/her voice is. For that Meet has a voice visualizer. image In the left corner, there is the voice visualizer.

Describe the solution you'd like

There are two ways of doing it which I figured out. 1) to collect the decibel of the client in the backend and according to that, we will send a response to the client via visualizer. For that, we can use a package called decibel-meter. 2) A package that does it all like getting the sound and sending the amplitude on its own. The package is called p5.js.

Describe alternatives you've considered

Well, after googling many times, I found this video which can make you clear what I am trying to say.

welcome[bot] commented 3 years ago

Hello there!πŸ‘‹ Welcome to the project!πŸš€βš‘

Thank you and congratsπŸŽ‰for opening your very first issue in this project. Please adhere to our Contributing Guidelines.πŸ™Œ You may submit a PR if you like, make sure to follow our Pull Request Template. If you want to report a bug🐞 please follow our Issue Template. Also make sure you include steps to reproduce it and be patient while we get back to you.πŸ˜„

Feel free to join our Discord Community.πŸ’– We have different channels for active discussions.✨ Hope you have a great time there!πŸ˜„

ZohebMOPO commented 3 years ago

ezgif com-gif-maker

@sansyrox @shivaylamba @raghavdhingra @midopooler

The Audio visualizer thing is working rn. This one is in a separate environment. I just wanna ask that in which part of the video call we should add the visualizer?

sansyrox commented 3 years ago

@ZohebMOPO , on the screen where you select the username

sansyrox commented 3 years ago

Also, once you integrate that, try using hooks instead of class components. Let us know if you face any issues.

ZohebMOPO commented 3 years ago

Yeah sure. I am not in home rn. Will let you know about that :)

ZohebMOPO commented 3 years ago

I will not be at my house for 2days because of the festival. Like I have changed them to functional components but haven't used the hooks properly. Sorry for that :(

sansyrox commented 3 years ago

No worries @ZohebMOPO . You can take your time.

ZohebMOPO commented 3 years ago

import AudioVisualiser from "./Visualizer";

class AudioAnalyser extends Component {
  constructor(props) {
    super(props);
    this.state = { audioData: new Uint8Array(0) };
    this.tick = this.tick.bind(this);
  }

  componentDidMount() {
    this.audioContext = new (window.AudioContext ||
      window.webkitAudioContext)();
    this.analyser = this.audioContext.createAnalyser();
    this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
    this.source = this.audioContext.createMediaStreamSource(this.props.audio);
    this.source.connect(this.analyser);
    this.rafId = requestAnimationFrame(this.tick);
  }

  tick() {
    this.analyser.getByteTimeDomainData(this.dataArray);
    this.setState({ audioData: this.dataArray });
    this.rafId = requestAnimationFrame(this.tick);
  }

  componentWillUnmount() {
    cancelAnimationFrame(this.rafId);
    this.analyser.disconnect();
    this.source.disconnect();
  }

  render() {
    return <AudioVisualiser audioData={this.state.audioData} />;
  }
}

export default AudioAnalyser;

This was the class component, I am literally confused on how to use the DOM updates in useEffect.

Functional component..... 

import React, { useState, useEffect } from "react";
import Visualizerf from "./AudioAnalyserf";
function AudioAnalyserf({ audio }) {
  const [audioData, setaudioData] = useState(new Uint8Array(0));

  const audioContext = new window.AudioContext();
  const analyser = audioContext.createAnalyser();
  const dataArray = new Uint8Array(analyser.frequencyBinCount);
  const source = audioContext.createMediaElementSource(audio);
  source.connect(analyser);
  const rafId = requestAnimationFrame(tick);

  const tick = () => {
    analyser.getByteTimeDomainData(dataArray);
    setaudioData(dataArray);
    rafId = requestAnimationFrame(this.tick);
  };

  const unMount = () => {
    cancelAnimationFrame(this.rafId);
    analyser.disconnect();
    source.disconnect();
  };

  useEffect(() => {
    // Idk what I am doing :((((
  }, []);
  return (
    <div>
      <Visualizerf audioData={audioData} />
    </div>
  );
}

export default AudioAnalyserf;

``
ZohebMOPO commented 3 years ago

How do I make updates using useEffect @raghavdhingra

raghavdhingra commented 3 years ago

useEffect is a life cycle hook. It has a dependency list, over which the function call itself when ever any of the value from that list changes. For e.g. const callBackFunction = () => { // do some changes } const dependencyArray = [value, object, list, ...] useEffect(callBackFunction, dependencyArray); So, if any of the values changes within the list via state change, or any hook change, the callback function will call itself. Hence you can define the callback function as per the way you want

ZohebMOPO commented 3 years ago

Class component:-


class AudioAnalyser extends Component {
  constructor(props) {
    super(props);
    this.state = { audioData: new Uint8Array(0) };
    this.tick = this.tick.bind(this);
  }

  componentDidMount() {
    this.audioContext = new (window.AudioContext ||
      window.webkitAudioContext)();
    this.analyser = this.audioContext.createAnalyser();
    this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
    this.source = this.audioContext.createMediaStreamSource(this.props.audio);
    this.source.connect(this.analyser);
    this.rafId = requestAnimationFrame(this.tick);
  }

  tick() {
    this.analyser.getByteTimeDomainData(this.dataArray);
    this.setState({ audioData: this.dataArray });
    this.rafId = requestAnimationFrame(this.tick);
  }

  componentWillUnmount() {
    cancelAnimationFrame(this.rafId);
    this.analyser.disconnect();
    this.source.disconnect();
  }

  render() {
    return <AudioVisualiser audioData={this.state.audioData} />;
  }
}

export default AudioAnalyser;

import Visualizerf from "./AudioAnalyserf";
function AudioAnalyserf({ audio }) {
  const [audioData, setaudioData] = useState(new Uint8Array(0));

  const audioContext = new window.AudioContext();
  const analyser = audioContext.createAnalyser();
  const dataArray = new Uint8Array(analyser.frequencyBinCount);
  const source = audioContext.createMediaElementSource(audio);
  source.connect(analyser);
  const rafId = requestAnimationFrame(tick);

  const tick = () => {
    analyser.getByteTimeDomainData(dataArray);
    setaudioData(dataArray);
    rafId = requestAnimationFrame(tick);
  };

  const unMount = () => {
    cancelAnimationFrame(rafId);
    analyser.disconnect();
    source.disconnect();
  };

  useEffect(() => {
    return unMount;
  }, []);

  return (
    <div>
      <Visualizerf audioData={audioData} />
    </div>
  );
}

export default AudioAnalyserf;```

so it will look like this?
ZohebMOPO commented 3 years ago

@raghavdhingra Sorry for the late reply. Schools are going offline and I am kinda stuck in that thing cuz I didn't do anything the whole summer haha. Anyways, will the functional component look like this?

ZohebMOPO commented 3 years ago

I am hella confused about converting this to functional components. I am used to class components cuz my first programming lang was Java. I am not sure when I will come out of this learning curve :(