summaryrefslogtreecommitdiff
path: root/animism-align/frontend/app/views/editor/sidebar/components/waveUpload.component.js
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align/frontend/app/views/editor/sidebar/components/waveUpload.component.js')
-rw-r--r--animism-align/frontend/app/views/editor/sidebar/components/waveUpload.component.js191
1 files changed, 191 insertions, 0 deletions
diff --git a/animism-align/frontend/app/views/editor/sidebar/components/waveUpload.component.js b/animism-align/frontend/app/views/editor/sidebar/components/waveUpload.component.js
new file mode 100644
index 0000000..3ca19f0
--- /dev/null
+++ b/animism-align/frontend/app/views/editor/sidebar/components/waveUpload.component.js
@@ -0,0 +1,191 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import extractPeaks from 'webaudio-peaks'
+
+import actions from 'app/actions'
+import { formatSize, timestampHMS } from 'app/utils'
+import { Loader } from 'app/common'
+
+class WaveUpload extends Component {
+ state = {
+ working: false,
+ status: "",
+ filename: "",
+ duration: 0,
+ }
+
+ upload(e) {
+ e.preventDefault()
+ document.body.className = ''
+ const files = e.dataTransfer ? e.dataTransfer.files : e.target.files
+ let i
+ let file
+ for (i = 0; i < files.length; i++) {
+ file = files[i]
+ if (file && file.type.match('image.*')) break
+ }
+ if (!file) {
+ console.log('No file specified')
+ return
+ }
+ this.setState({ working: true, status: "Loading MP3...", filename: file.name, size: file.size, duration: 0 })
+ const fileReader = new FileReader()
+ fileReader.onload = event => {
+ fileReader.onload = null
+ this.processAudioFile(file, event.target.result)
+ }
+ fileReader.readAsArrayBuffer(file)
+ }
+
+ processAudioFile(audioFile, arrayBuffer) {
+ this.setState({ working: true, status: "Extracting peaks..." })
+ var audioContext = new (window.AudioContext || window.webkitAudioContext)();
+ audioContext.decodeAudioData(arrayBuffer, (audioBuffer) => {
+ // buffer, samplesPerPixel, isMono, startOffset, endOffset, bitResolution
+ this.setState({ duration: audioBuffer.duration })
+ var peaks = extractPeaks(audioBuffer, 441, true);
+ console.log(peaks)
+ const array = Array.from(peaks.data[0])
+ const peaksBlob = new Blob([ JSON.stringify(array) ], {type: "application/json"});
+ this.uploadAudioAndPeaks(audioFile, peaksBlob)
+ })
+ }
+
+ uploadAudioAndPeaks(audioFile, peaksBlob) {
+ const { episode } = this.props
+ const updatedEpisode = { ...episode }
+ this.setState({ status: "Removing old files..." })
+ this.destroyTaggedFile('peaks')
+ this.destroyTaggedFile('audio')
+ .then(() => {
+ return (
+ this.uploadTaggedFile(
+ peaksBlob,
+ 'peaks',
+ 'episode-' + this.props.episode.id + '-peaks.json',
+ {}
+ )
+ )
+ })
+ .then(peaksResult => {
+ updatedEpisode.settings.peaks = peaksResult
+ return (
+ this.uploadTaggedFile(
+ audioFile,
+ 'audio',
+ this.state.filename,
+ {
+ size: this.state.size,
+ duration: this.state.duration,
+ }
+ )
+ )
+ })
+ .then(audioResult => {
+ updatedEpisode.settings.audio = audioResult
+ return actions.episode.update(updatedEpisode)
+ })
+ .then(res => {
+ this.setState({
+ status: "Upload complete",
+ working: false,
+ filename: null,
+ duration: null,
+ size: null,
+ })
+ })
+ }
+
+ uploadTaggedFile(file, tag, fn, meta) {
+ return new Promise((resolve, reject) => {
+ this.setState({ status: "Uploading " + tag + "..." })
+ const uploadData = {
+ tag,
+ file,
+ __file_filename: fn,
+ username: this.props.currentUser.username,
+ }
+ // console.log(uploadData)
+ return actions.upload.upload(uploadData).then(data => {
+ // console.log(data)
+ resolve({
+ ...data.res,
+ ...meta
+ })
+ })
+ })
+ }
+
+ destroyTaggedFile(tag) {
+ return new Promise((resolve, reject) => {
+ if (!this.props.episode.settings[tag]) {
+ return resolve();
+ }
+ actions.upload.destroy(this.props.episode.settings[tag])
+ .then(() => {
+ console.log('Destroy successful')
+ resolve()
+ })
+ .catch(() => {
+ console.log('Error deleting the image')
+ reject()
+ })
+ })
+ }
+
+ render() {
+ const { episode, peaks } = this.props
+ // console.log(episode)
+ return (
+ <div className="sidebar-content wave-upload">
+ {episode.settings.audio && (
+ <div>
+ <small>{episode.settings.audio.fn}</small>
+ <small>{'Size: '}{formatSize(episode.settings.audio.size)}</small>
+ <small>{'Duration: '}{timestampHMS(episode.settings.audio.duration)}</small>
+ </div>
+ )}
+ {peaks.length && (
+ <div>
+ Peaks: {peaks.length}
+ </div>
+ )}
+ <div className="uploadButton">
+ <button>
+ <span>
+ {episode.settings.audio
+ ? "Upload a new audio file"
+ : "Upload an audio file"
+ }
+ </span>
+ </button>
+ <input
+ type="file"
+ accept="audio/mp3"
+ onChange={this.upload.bind(this)}
+ required={this.props.required}
+ />
+ </div>
+ <small>Upload an MP3, encoded 192kbit constant bitrate, 44.1kHz stereo</small>
+ {this.state.status && (
+ <div className='status'>
+ {this.state.working && <Loader />}
+ <div className='status-message'>{this.state.status}</div>
+ {this.state.filename && <small>{this.state.filename}</small>}
+ {this.state.size && <small>{'Size: '}{formatSize(this.state.size)}</small>}
+ {!!this.state.duration && <small>{'Duration: '}{timestampHMS(this.state.duration)}</small>}
+ </div>
+ )}
+ </div>
+ )
+ }
+}
+
+const mapStateToProps = state => ({
+ peaks: state.align.peaks,
+ currentUser: state.auth.user,
+ project: state.site.project,
+ episode: state.site.episode,
+})
+
+export default connect(mapStateToProps)(WaveUpload)