Как создать форму волны с аудио компонентом, используя машинопись? - PullRequest
0 голосов
/ 08 февраля 2019

Я не знаю, как заставить компонент работать с 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 реального аудио.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...