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