Я не знаю, как заставить компонент работать с Web Audio API с использованием реакции и машинописи
Я ухожу из этого примера: https://github.com/philnash/react-web-audio,, который написан на javascript.Я просто переписал его, чтобы он соответствовал моей среде реагирования / машинописи.Проблема в том, что автор использует свои периферийные устройства ввода для получения аудиопотока.Я использую компонент с URL в качестве источника, который возвращает HTMLAudioElement.Я не знаю, как перейти от HTMLAudioElement к MediaStream, который мне нужен.Я пытался использовать srcObject, но он всегда нулевой.
файл MyAudio.tsx
import * as React from 'react';
import {fromNullable, none, Option} from 'fp-ts/lib/Option';
import {AudioAnalyser} from './AudioAnalyser';
export type MyAudioProps = {
onAudioError?: (e: any) => void;
};
type State = {
audioElement: Option<HTMLAudioElement>;
};
export class MyAudio extends React.PureComponent<MyAudioProps, State> {
constructor (props: MyAudioProps) {
super(props);
this.state = {audioElement: none};
}
private blobUrl = 'https://archive.org/download/AbdulAzizSurahFateha/'
+ '001Www.quranaudio.info.mp3';
private readonly audioRef = (el: HTMLAudioElement | null) => {
this.state.audioElement.fold(
() => {
this.setState({audioElement: fromNullable(el)});
},
audioEl => {}
);
}
render() {
const audioElement = this.state.audioElement.toUndefined();
// This is alway null - what do I have to do to get a stream?
const srcObject = audioElement ? audioElement.srcObject : undefined;
return (
<div>
<audio controls ref={this.audioRef} src={this.blobUrl}/>
{
srcObject && srcObject instanceof MediaStream
? <AudioAnalyser
audio={srcObject}
/>
: null
}
</div>
);
}
}
файл AudioAnalyser.tsx
import * as React from 'react';
import {AudioVisualiser} from './AudioVisualiser';
type Props = {
audio: MediaStream
};
type State = {
audioData: Uint8Array
};
export class AudioAnalyser extends React.PureComponent<Props, State> {
audioContext: AudioContext;
analyser: AnalyserNode;
dataArray: Uint8Array;
source: MediaStreamAudioSourceNode;
rafId: number;
constructor(props: Props) {
super(props);
this.state = { audioData: new Uint8Array(0) };
this.tick = this.tick.bind(this);
}
componentDidMount() {
this.audioContext = new (AudioContext || 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} />;
}
}
файл AudioVisualiser.tsx
import * as React from 'react';
import {fromNullable, none, Option} from 'fp-ts/lib/Option';
export type Props = {
audioData: Uint8Array
};
export class AudioVisualiser extends React.PureComponent<Props> {
canvas: Option<HTMLCanvasElement> = none;
constructor(props: Props) {
super(props);
}
componentDidUpdate() {
this.draw();
}
private readonly canvasRef = (el: HTMLCanvasElement | null) => {
this.canvas = fromNullable(el);
}
draw() {
const { audioData } = this.props;
this.canvas.fold(
() => {},
canvas => {
// const canvas = canvasElement.current;
const height = canvas.height;
const width = canvas.width;
const context = canvas.getContext('2d');
if (context) {
let x = 0;
const sliceWidth = (width * 1.0) / audioData.length;
context.lineWidth = 2;
context.strokeStyle = '#000000';
context.clearRect(0, 0, width, height);
context.beginPath();
context.moveTo(0, height / 2);
audioData.forEach(item => {
const y = (item / 255.0) * height;
context.lineTo(x, y);
x += sliceWidth;
});
context.lineTo(x, height / 2);
context.stroke();
}
}
);
}
render() {
return <canvas width='600' height='100' ref={this.canvasRef} />;
}
}
Когда я передаю srcObject,это всегда ноль.Если я пытаюсь сделать как другие примеры, которые я видел, и передать аудио ссылку, я получаю ошибку типа машинописного текста, потому что это HTMLAudioElement, а не MediaStream.Если я заменяю тип на «любой», то получаю ошибку времени выполнения, потому что это не MediaStream.
Я не знаю, как получить MediaStream реального аудио.