bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/audio/audio-stream-volume/component.jsx

136 lines
3.1 KiB
React
Raw Normal View History

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import logger from '/imports/startup/client/logger';
const propTypes = {
low: PropTypes.number,
optimum: PropTypes.number,
high: PropTypes.number,
deviceId: PropTypes.string,
};
const defaultProps = {
low: 0,
2017-03-27 23:45:24 +08:00
optimum: 0.05,
high: 0.3,
deviceId: undefined,
};
const AudioContext = window.AudioContext || window.webkitAudioContext;
class AudioStreamVolume extends Component {
2021-08-09 22:24:02 +08:00
static handleError(error) {
logger.error({
logCode: 'audiostreamvolume_handleError',
extraInfo: { error },
}, 'Encountered error while creating audio context');
}
constructor(props) {
super(props);
this.createAudioContext = this.createAudioContext.bind(this);
this.closeAudioContext = this.closeAudioContext.bind(this);
this.handleConnectStreamToProcessor = this.handleConnectStreamToProcessor.bind(this);
this.handleAudioProcess = this.handleAudioProcess.bind(this);
2021-08-09 22:24:02 +08:00
this.handleError = AudioStreamVolume.handleError.bind(this);
this.state = {
slow: 0,
};
}
componentDidMount() {
this.createAudioContext();
}
componentDidUpdate(prevProps) {
const { deviceId: nextDeviceId } = this.props;
if (prevProps.deviceId !== nextDeviceId) {
this.closeAudioContext().then(() => {
this.setState({
slow: 0,
});
2016-12-19 19:35:33 +08:00
this.createAudioContext();
});
}
}
componentWillUnmount() {
this.closeAudioContext();
}
2021-08-09 22:24:02 +08:00
handleConnectStreamToProcessor(stream) {
this.source = this.audioContext.createMediaStreamSource(stream);
this.source.connect(this.scriptProcessor);
this.scriptProcessor.connect(this.audioContext.destination);
}
handleAudioProcess(event) {
const input = event.inputBuffer.getChannelData(0);
const sum = input.reduce((a, b) => a + (b * b), 0);
const instant = Math.sqrt(sum / input.length);
this.setState((prevState) => ({
slow: (0.75 * prevState.slow) + (0.25 * instant),
}));
}
createAudioContext() {
this.audioContext = new AudioContext();
this.scriptProcessor = this.audioContext.createScriptProcessor(2048, 1, 1);
this.scriptProcessor.onaudioprocess = this.handleAudioProcess;
this.source = null;
2017-06-03 03:25:02 +08:00
const constraints = {
audio: true,
};
const { deviceId } = this.props;
if (deviceId) {
constraints.audio = {
deviceId,
};
}
return navigator.mediaDevices
.getUserMedia(constraints)
.then(this.handleConnectStreamToProcessor)
.catch(this.handleError);
}
closeAudioContext() {
return this.audioContext.close().then(() => {
this.audioContext = null;
this.scriptProcessor = null;
this.source = null;
});
}
render() {
2018-06-15 03:20:14 +08:00
const {
low, optimum, high, ...props
} = this.props;
const { slow } = this.state;
return (
<meter
{...props}
min={0}
max={high * 1.25}
low={low}
optimum={optimum}
high={high}
value={slow}
/>
);
}
2017-06-03 03:25:02 +08:00
}
AudioStreamVolume.propTypes = propTypes;
AudioStreamVolume.defaultProps = defaultProps;
export default AudioStreamVolume;