Skip to content

Examples

WARNING

Due to a bug in WebKit (Safari), the <audio> source blob does only work if you set an explicit type attribute. This is not a problem with the composable, but with the browser itself.

Basic Example

This is a basic example of how to use the <script setup> syntax in a Vue component.

state: undefined (no interaction)
recorded data (array length): 0

Code

vue
<script setup>
import { useMediaRecorder } from '@orbisk/vue-use-media-recorder'
import { computed } from 'vue'

const {
  data,
  start,
  stop,
  pause,
  resume,
  mimeType,
  state,
} = useMediaRecorder({ constraints: { audio: true } })

const length = computed(() => {
  return data.value.length ?? 0
})

const startBtnText = computed(() => {
  switch (state.value) {
    case 'recording':
      return 'Pause'
    case 'paused':
      return 'Resume'
    default:
      return 'Start'
  }
})

function handleStartClick() {
  switch (state.value) {
    case 'recording':
      pause()
      break
    case 'paused':
      resume()
      break
    default:
      start()
  }
}

const audio = computed(() => {
  if (!data.value?.length || state.value !== 'inactive')
    return
  const blob = new Blob(data.value, { type: mimeType.value })
  return URL.createObjectURL(blob)
})
</script>

<template>
  <div style="display: flex; flex-direction: column">
    <button style="border-radius: 5px; background-color: greenyellow; color: black" @click="handleStartClick">
      {{ startBtnText }}
    </button>
    <button style="border-radius: 5px; background-color: orangered; color: white" @click="stop">
      Stop
    </button>
    <pre>state: {{ state ? state : 'undefined (no interaction)' }}</pre>
    <pre>recorded data (array length): {{ length }}</pre>
    <audio v-if="audio" controls>
      <source :src="audio">
    </audio>
  </div>
</template>

Set timeslice

You can control the timeslice of the data Blob creation. See MediaRecorder.start(timeslice) for more information. The default value is undefined (this means that the timeslice is not set -> data.value will be set when stopping).

state: undefined (no interaction)
recorded data (array length): 0
vue
<script setup>
import { useMediaRecorder } from '@orbisk/vue-use-media-recorder'
import { computed, ref } from 'vue'

const {
  data,
  start,
  stop,
  pause,
  resume,
  mimeType,
  state,
} = useMediaRecorder({ constraints: { audio: true } })

const timeslice = ref(1000)

const length = computed(() => {
  return data.value.length ?? 0
})

const startBtnText = computed(() => {
  switch (state.value) {
    case 'recording':
      return 'Pause'
    case 'paused':
      return 'Resume'
    default:
      return 'Start'
  }
})

function handleStartClick() {
  switch (state.value) {
    case 'recording':
      pause()
      break
    case 'paused':
      resume()
      break
    default:
      start(timeslice.value)
  }
}

const audio = computed(() => {
  if (!data.value?.length || state.value !== 'inactive')
    return
  const blob = new Blob(data.value, { type: mimeType.value })
  return URL.createObjectURL(blob)
})
</script>

<template>
  <div style="display: flex; flex-direction: column">
    <label for="timeslice">
      Timeslice (ms):
      <input id="timeslice" v-model="timeslice" type="number">
    </label>
    <button style="border-radius: 5px; background-color: greenyellow; color: black" @click="handleStartClick">
      {{ startBtnText }}
    </button>
    <button style="border-radius: 5px; background-color: orangered; color: white" @click="stop">
      Stop
    </button>
    <pre>state: {{ state ? state : 'undefined (no interaction)' }}</pre>
    <pre>recorded data (array length): {{ length }}</pre>
    <audio v-if="audio" controls>
      <source :src="audio">
    </audio>
  </div>
</template>