Сохранение аудио, отредактированного с помощью Web Audio API, в другом аудиоэлементе - PullRequest
0 голосов
/ 05 мая 2020

Я хочу сохранить изменения, сделанные с помощью API веб-аудио, в новый файл, который можно будет загрузить. На данный момент я просто хочу, чтобы он сохранялся во втором элементе <audio>.

Я применяю 3 фильтра к представленному аудио, которые могут изменять высокие, низкие частоты и панорамирование. Я хотел бы, чтобы внесенные изменения были перенесены в новый аудиоэлемент, который будет представлять отредактированный / сохраненный аудиофайл (чтобы позже сохранить его на моем express сервере).

Я не знаю, как это сделать go о сохранении этих изменений в новом аудиоэлементе.

class Home extends Component {
    constructor(props) {
        super(props)
        this.state = {
            submittedAudio: false,
            fileName: '',
            audioFile: '',
            submitInfo: '',
            savedAudioFile: '',
        }
    }

    componentDidUpdate({ prevProps }, prevState) {
        if (prevState.fileName === this.state.fileName) {
            console.log('same shit')
            return
        }
        console.log('Home.js updated')
        this.mountAudioContext()
    }

    mountAudioContext() {
        this.chunks = []

        this.audioContext = new AudioContext()
        this.track = this.audioContext.createMediaElementSource(this.audioPlayer.current)
        this.track.connect(this.audioContext.destination)
        this.gainNode = this.audioContext.createGain()

        this.baseFilter = this.audioContext.createBiquadFilter()
        this.baseFilter.type = 'lowshelf'
        this.baseFilter.frequency.value = 200

        this.trebleFilter = this.audioContext.createBiquadFilter()
        this.trebleFilter.type = 'highshelf'
        this.trebleFilter.frequency.value = 2000

        this.pannerOptions = { pan: 0 }
        this.panner = new StereoPannerNode(this.audioContext, this.pannerOptions)
        this.track.connect(this.gainNode).connect(this.trebleFilter).connect(this.baseFilter).connect(this.panner).connect(this.audioContext.destination)
        this.dest = this.audioContext.createMediaStreamDestination()
        this.recorder = new MediaRecorder(this.dest.stream)

        this.recorder.ondataavailable = (evt) => {
            this.chunks.push(evt.data)
        }

        this.recorder.onstop = (evt) => {
            let blob = new Blob(this.chunks, { 'type': 'audio/ogg; codecs=opus' })
            let outSide = URL.createObjectURL(blob)
            this.setState(state => ({
                savedAudioFile: outSide
            }))
        }
    }

    async handleSubmit(event) {
        event.preventDefault()
        try {
            const inpFile = this.fileInput.current.files[0]
            let outSide = URL.createObjectURL(inpFile)
            this.setState(state => ({
                submittedAudio: true,
                audioFile: outSide,
                fileName: this.fileInput.current.files[0].name,
            }))
        } catch (error) { 
            console.log('No file provided', error)
            this.setState(state => ({
                submittedAudio: false,
            }))
        }
    }

    handlePlayButton(event) {
        if (!this.state.submittedAudio) return
        const playButton = this.playButton.current
        const audioPlayer = this.audioPlayer.current
        if (this.audioContext.state === 'suspended') {
            this.audioContext.resume()
        }
        if (playButton.dataset.playing === 'false') {
            audioPlayer.play()
            playButton.dataset.playing = 'true'
        } else if (playButton.dataset.playing === 'true') {
            audioPlayer.pause()
            playButton.dataset.playing = 'false'
        }

    }

    handleVolume(event) {
        if (!this.state.submittedAudio) return
        this.gainNode.gain.value = this.volumeRange.current.value
    }

    handlePanning(event) {
        if (!this.state.submittedAudio) return
        console.log(this.pannerRange.current.value)
        this.panner.pan.value = this.pannerRange.current.value
    }

    handleBassFilter(event) {
        if (!this.state.submittedAudio) return
        this.baseFilter.gain.value = this.bassRange.current.value
        console.log(this.baseFilter)
    }

    handleTrebleFilter(event) {
        if (!this.state.submittedAudio) return
        this.trebleFilter.gain.value = this.trebleRange.current.value
        console.log(this.trebleFilter)
    }

    handleFinishedAudio(event) {
        const playButton = this.playButton.current
        playButton.dataset.playing = 'false'
    }


    handleRecord(event) {
        this.recorder.start()
    }

    handleRecordStop(event) {
        this.recorder.stop()
        this.chunks.push()
    }

    render() {
        return (
            <div style={{ backgroundColor: "gray" }}>
                <p>Home</p>
                <form onSubmit={this.handleSubmit}
                    encType="multipart/form-data">
                    <input type="file" ref={this.fileInput} />
                    <input type="submit" value="Submit" />
                </form>

                <div>
                    {this.state.submittedAudio && <p>{this.state.fileName} submitted.</p>}
                    {!this.state.submittedAudio && <p>No file submitted</p>}
                </div>

                <audio controls
                    crossOrigin=""
                    ref={this.audioPlayer}
                    src={this.state.audioFile}
                    onEnded={this.handleFinishedAudio}>
                </audio>
                <br />

                <Button data-playing="false"
                    role="switch"
                    aria-checked="false"
                    onClick={this.handlePlayButton}
                    ref={this.playButton}>
                    <span>Player/Pause</span></Button>


                <br />

                <RangeSlider min={0} max={10} size={"sm"}></RangeSlider>

                <br />

                Volume<input type="range"
                    min="-1"
                    max="3.4"
                    step="0.01"
                    defaultValue="1"
                    onInput={this.handleVolume}
                    ref={this.volumeRange}></input>

                <br />
                <br />
                Steroe panning<input type="range"
                    min="-1"
                    max="1"
                    defaultValue="0"
                    step="0.01"
                    onInput={this.handlePanning}
                    ref={this.pannerRange}
                ></input>
                <br />
                <br />

                Filter Base<input type="range"
                    min="-3.4"
                    max="10"
                    defaultValue="0"
                    step="0.01"
                    onInput={this.handleBassFilter}
                    ref={this.bassRange}
                ></input>
                <br />
                <br />
                Filter Treble<input type="range"
                    min="-20"
                    max="20"
                    defaultValue="0"
                    step="0.01"
                    onInput={this.handleTrebleFilter}
                    ref={this.trebleRange}
                ></input>
                <br />
                <Button onClick={this.postFile}>
                    PostFile
                </Button>
                <Button onClick={this.handleRecord}>
                    Record
                </Button>
                <Button onClick={this.handleRecordStop}>
                    Stop record
                </Button>

                <audio controls
                    crossOrigin=""
                    ref={this.savedAudioPlayer}
                    src={this.state.savedAudioFile}
                >
                </audio>
            </div>
        );
    }
}
...