mirror of
https://github.com/kevin-DL/vue-audio-recorder.git
synced 2026-01-12 19:25:18 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
206216643a | ||
|
|
fc0c9c824a | ||
|
|
261d7a80ec | ||
|
|
860f7e6158 | ||
|
|
83ccce2374 | ||
|
|
cb7a410ae5 |
2
dist/vue-audio-recorder.min.js
vendored
2
dist/vue-audio-recorder.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/vue-audio-recorder.min.js.map
vendored
2
dist/vue-audio-recorder.min.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vue-audio-recorder",
|
||||
"description": "Audio recorder for Vue.js. It allows to create, play, download and store records on a server",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"author": "Gennady Grishkovtsov <grishkovelli@gmail.com>",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -88,20 +88,20 @@
|
||||
id="download"
|
||||
class="ar-icon ar-icon__sm"
|
||||
name="download"
|
||||
@click.native="download"/>
|
||||
@click.native="decorator(download)"/>
|
||||
|
||||
<icon-button
|
||||
id="play"
|
||||
class="ar-icon ar-icon__lg ar-player__play"
|
||||
:name="playBtnIcon"
|
||||
:class="{'ar-player__play--active': isPlaying}"
|
||||
@click.native="playback"/>
|
||||
@click.native="decorator(playback)"/>
|
||||
|
||||
<icon-button
|
||||
id="upload"
|
||||
class="ar-icon ar-icon__sm"
|
||||
name="save"
|
||||
@click.native="upload"/>
|
||||
@click.native="decorator(upload)"/>
|
||||
</div>
|
||||
|
||||
<div class="ar-player-bar">
|
||||
@@ -163,22 +163,23 @@
|
||||
this.player.addEventListener('timeupdate', this._onTimeUpdate)
|
||||
},
|
||||
computed: {
|
||||
audioSource () {
|
||||
let url = this.src || this.record.url
|
||||
if (url) {
|
||||
return url
|
||||
} else {
|
||||
this._resetProgress()
|
||||
}
|
||||
},
|
||||
playBtnIcon () {
|
||||
return this.isPlaying ? 'pause' : 'play'
|
||||
},
|
||||
audioSource () {
|
||||
return this.src || this.record.url
|
||||
},
|
||||
playerUniqId () {
|
||||
return `audio-player${this._uid}`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
playback () {
|
||||
if (!this.audioSource) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.isPlaying) {
|
||||
this.player.pause()
|
||||
} else {
|
||||
@@ -188,10 +189,6 @@
|
||||
this.isPlaying = !this.isPlaying
|
||||
},
|
||||
upload () {
|
||||
if (!this.audioSource) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.startUpload) {
|
||||
this.startUpload()
|
||||
}
|
||||
@@ -216,18 +213,27 @@
|
||||
})
|
||||
},
|
||||
download () {
|
||||
if (!this.audioSource) {
|
||||
return
|
||||
}
|
||||
|
||||
let link = document.createElement('a')
|
||||
link.href = this.record.url
|
||||
link.download = 'record.wav'
|
||||
link.click()
|
||||
},
|
||||
decorator (func) {
|
||||
if (!this.audioSource) {
|
||||
return
|
||||
}
|
||||
func()
|
||||
},
|
||||
_resetProgress () {
|
||||
this.isPlaying = false
|
||||
this.progress = 0
|
||||
if (this.isPlaying) {
|
||||
this.player.pause()
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.duration = convertTimeMMSS(0)
|
||||
this.playedTime = convertTimeMMSS(0)
|
||||
this.progress = 0
|
||||
this.isPlaying = false
|
||||
}, 0)
|
||||
},
|
||||
_onTimeUpdate () {
|
||||
this.playedTime = convertTimeMMSS(this.player.currentTime)
|
||||
|
||||
@@ -23,12 +23,14 @@
|
||||
|
||||
&__record {
|
||||
width: 320px;
|
||||
height: 45px;
|
||||
padding: 0 10px;
|
||||
margin: 0 auto;
|
||||
line-height: 45px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #E8E8E8;
|
||||
position: relative;
|
||||
|
||||
&--selected {
|
||||
border: 1px solid #E8E8E8;
|
||||
@@ -105,7 +107,7 @@
|
||||
|
||||
@keyframes blink {
|
||||
0% { opacity: .2; }
|
||||
20% { opacity: 1; }
|
||||
20% { opacity: 1; }
|
||||
100% { opacity: .2; }
|
||||
}
|
||||
}
|
||||
@@ -144,6 +146,20 @@
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
&__rm {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
padding: 6px;
|
||||
line-height: 6px;
|
||||
margin: auto;
|
||||
left: 10px;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
color: rgb(244, 120, 90);
|
||||
}
|
||||
}
|
||||
|
||||
@import '../scss/icons';
|
||||
@@ -182,9 +198,14 @@
|
||||
<div class="ar-records">
|
||||
<div
|
||||
class="ar-records__record"
|
||||
:class="{'ar-records__record--selected': idx === selectedRecord.idx}"
|
||||
:class="{'ar-records__record--selected': record.id === selected.id}"
|
||||
:key="record.id"
|
||||
v-for="(record, idx) in recordList"
|
||||
@click="selectRecord(idx, record)">
|
||||
@click="selected = record">
|
||||
<div
|
||||
class="ar__rm"
|
||||
v-if="record.id === selected.id"
|
||||
@click="removeRecord(idx)">×</div>
|
||||
<div class="ar__text">Record {{idx + 1}}</div>
|
||||
<div class="ar__text">{{record.duration}}</div>
|
||||
</div>
|
||||
@@ -192,7 +213,7 @@
|
||||
|
||||
<audio-player
|
||||
:compact="compact"
|
||||
:record="selectedRecord"
|
||||
:record="selected"
|
||||
:upload-url="uploadUrl"
|
||||
:start-upload="startUpload"
|
||||
:successful-upload="successfulUpload"
|
||||
@@ -244,7 +265,7 @@
|
||||
time: this.time
|
||||
}),
|
||||
recordList: [],
|
||||
selectedRecord: {},
|
||||
selected: {},
|
||||
uploadStatus: null
|
||||
}
|
||||
},
|
||||
@@ -277,8 +298,9 @@
|
||||
|
||||
this.recorder.stop()
|
||||
},
|
||||
selectRecord (idx, record) {
|
||||
this.selectedRecord = { idx: idx, url: record.url, blob: record.blob }
|
||||
removeRecord (idx) {
|
||||
this.recordList.splice(idx, 1)
|
||||
this.$set(this.selected, 'url', null)
|
||||
},
|
||||
onStartUpload () {
|
||||
this.isUploading = true
|
||||
|
||||
@@ -23,7 +23,7 @@ export default class {
|
||||
navigator.mediaDevices.getUserMedia({audio: true})
|
||||
.then(this._micCaptured.bind(this))
|
||||
.catch(this._micError.bind(this))
|
||||
this.isPause = false
|
||||
this.isPause = false
|
||||
this.isRecording = true
|
||||
}
|
||||
|
||||
@@ -34,26 +34,28 @@ export default class {
|
||||
this.context.close()
|
||||
|
||||
let encoder = new WavEncoder({
|
||||
bufferSize: this.bufferSize,
|
||||
sampleRate: this.context.sampleRate,
|
||||
samples: this.samples
|
||||
bufferSize : this.bufferSize,
|
||||
sampleRate : this.context.sampleRate,
|
||||
samples : this.samples
|
||||
})
|
||||
|
||||
let audioBlob = encoder.getData()
|
||||
let audioUrl = URL.createObjectURL(audioBlob)
|
||||
let audioUrl = URL.createObjectURL(audioBlob)
|
||||
|
||||
this.samples = []
|
||||
|
||||
this.records.push({
|
||||
blob: audioBlob,
|
||||
url: audioUrl,
|
||||
duration: convertTimeMMSS(this.duration)
|
||||
id : Date.now(),
|
||||
blob : audioBlob,
|
||||
duration : convertTimeMMSS(this.duration),
|
||||
url : audioUrl
|
||||
})
|
||||
|
||||
this.isPause = false
|
||||
this.isRecording = false
|
||||
this._duration = 0
|
||||
this.duration = 0
|
||||
this.duration = 0
|
||||
|
||||
this.isPause = false
|
||||
this.isRecording = false
|
||||
|
||||
if (this.afterStop) {
|
||||
this.afterStop()
|
||||
@@ -79,11 +81,11 @@ export default class {
|
||||
}
|
||||
|
||||
_micCaptured (stream) {
|
||||
this.context = new(window.AudioContext || window.webkitAudioContext)()
|
||||
this.input = this.context.createMediaStreamSource(stream)
|
||||
this.processor = this.context.createScriptProcessor(this.bufferSize, 1, 1)
|
||||
this.duration = this._duration
|
||||
this.stream = stream
|
||||
this.context = new(window.AudioContext || window.webkitAudioContext)()
|
||||
this.duration = this._duration
|
||||
this.input = this.context.createMediaStreamSource(stream)
|
||||
this.processor = this.context.createScriptProcessor(this.bufferSize, 1, 1)
|
||||
this.stream = stream
|
||||
|
||||
this.processor.onaudioprocess = (ev) => {
|
||||
let sample = ev.inputBuffer.getChannelData(0)
|
||||
|
||||
Reference in New Issue
Block a user