You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
2.8 KiB

  1. <template>
  2. <div>
  3. <div id="waveform" />
  4. <v-row
  5. no-gutters
  6. align="center"
  7. class="mb-3 mt-1"
  8. >
  9. <v-col md="8">
  10. <v-slider
  11. v-model="zoom"
  12. min="0"
  13. max="500"
  14. step="10"
  15. :append-icon="mdiMagnifyPlusOutline"
  16. :prepend-icon="mdiMagnifyMinusOutline"
  17. hide-details
  18. @click:append="zoomIn"
  19. @click:prepend="zoomOut"
  20. @change="onChangeZoom"
  21. />
  22. </v-col>
  23. <v-col md="2">
  24. <v-slider
  25. v-model="volume"
  26. min="0"
  27. max="1"
  28. step="0.1"
  29. :append-icon="mdiVolumeHigh"
  30. hide-details
  31. @change="onChangeVolume"
  32. />
  33. </v-col>
  34. <v-col md="2">
  35. <v-select
  36. v-model="speed"
  37. :items="speeds"
  38. label="Speed"
  39. dense
  40. outlined
  41. hide-details
  42. @change="onChangeSpeed"
  43. />
  44. </v-col>
  45. </v-row>
  46. <v-btn
  47. color="primary"
  48. class="text-capitalize"
  49. @click="play"
  50. >
  51. <v-icon
  52. v-if="!isPlaying"
  53. left
  54. >
  55. {{ mdiPlayCircleOutline }}
  56. </v-icon>
  57. <v-icon
  58. v-else
  59. left
  60. >
  61. {{ mdiPauseCircleOutline }}
  62. </v-icon>
  63. <span v-if="!isPlaying">Play</span>
  64. <span v-else>Pause</span>
  65. </v-btn>
  66. </div>
  67. </template>
  68. <script>
  69. import Vue from 'vue'
  70. import WaveSurfer from 'wavesurfer.js'
  71. import { mdiPlayCircleOutline, mdiPauseCircleOutline, mdiVolumeHigh, mdiMagnifyPlusOutline, mdiMagnifyMinusOutline } from '@mdi/js'
  72. export default Vue.extend({
  73. props: {
  74. source: {
  75. type: String,
  76. default: '',
  77. required: true
  78. }
  79. },
  80. data() {
  81. return {
  82. wavesurfer: null,
  83. isPlaying: false,
  84. zoom: 0,
  85. volume: 0.6,
  86. speed: 1,
  87. speeds: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0],
  88. mdiPlayCircleOutline,
  89. mdiPauseCircleOutline,
  90. mdiVolumeHigh,
  91. mdiMagnifyPlusOutline,
  92. mdiMagnifyMinusOutline
  93. }
  94. },
  95. watch: {
  96. source() {
  97. this.load()
  98. this.isPlaying = false
  99. }
  100. },
  101. mounted() {
  102. this.wavesurfer = WaveSurfer.create({
  103. container: '#waveform',
  104. backend: "MediaElement"
  105. })
  106. this.load()
  107. },
  108. methods: {
  109. load() {
  110. this.wavesurfer.load(this.source)
  111. },
  112. play() {
  113. this.isPlaying = !this.isPlaying
  114. this.wavesurfer.playPause()
  115. },
  116. zoomOut() {
  117. this.zoom = (this.zoom - 10) || 0
  118. this.onChangeZoom(this.zoom)
  119. },
  120. zoomIn() {
  121. this.zoom = (this.zoom + 10) || 500
  122. this.onChangeZoom(this.zoom)
  123. },
  124. onChangeVolume(value) {
  125. this.wavesurfer.setVolume(value)
  126. },
  127. onChangeZoom(value) {
  128. this.wavesurfer.zoom(value)
  129. },
  130. onChangeSpeed(value) {
  131. this.wavesurfer.setPlaybackRate(value)
  132. }
  133. }
  134. })
  135. </script>