Skip to content

Commit

Permalink
feat: add UseMediaRecorder component
Browse files Browse the repository at this point in the history
  • Loading branch information
OrbisK committed Nov 28, 2024
1 parent 0e58bf0 commit b0c39ba
Show file tree
Hide file tree
Showing 13 changed files with 406 additions and 105 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v4
5 changes: 1 addition & 4 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ outline: deep

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


<script setup>
import BasicExample from './basic-example.vue'
import TimesliceExample from './timeslice-example.vue'
Expand All @@ -20,7 +19,6 @@ import TimesliceExample from './timeslice-example.vue'

<<< @/basic-example.vue


## Set timeslice

You can control the timeslice of the data Blob creation. See [
Expand All @@ -30,5 +28,4 @@ stopping).

<TimesliceExample />


<<< @/timeslice-example.vue {40}
<<< @/timeslice-example.vue {40}
3 changes: 1 addition & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ hero:
text: Installation
link: /installation
- theme: secondary
text: Usage
text: Usage
link: /usage


features:
- title: Plug & play
icon: 🚀
Expand Down
2 changes: 1 addition & 1 deletion docs/timeslice-example.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const audio = computed(() => {
<div style="display: flex; flex-direction: column">
<label for="timeslice">
Timeslice (ms):
<input id="timeslice" type="number" v-model="timeslice"/>
<input id="timeslice" v-model="timeslice" type="number">
</label>
<button style="border-radius: 5px; background-color: greenyellow; color: black" @click="handleStartClick">
{{ startBtnText }}
Expand Down
43 changes: 21 additions & 22 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,24 @@ outline: deep
## `useMediaRecorder`

```vue
<script setup>
import { useMediaRecorder } from '@orbisk/vue-use-media-recorder'
const {
data,
stream,
start,
pause,
resume,
stop,
state,
isSupported,
isMimeTypeSupported,
mimeType,
mediaRecorder,
} = useMediaRecorder({ constraints: { audio: true, video: true } })
start()
import { useMediaRecorder } from '@orbisk/vue-use-media-recorder'
const {
data,
stream,
start,
pause,
resume,
stop,
state,
isSupported,
isMimeTypeSupported,
mimeType,
mediaRecorder,
} = useMediaRecorder({ constraints: { audio: true, video: true } })
start()
</script>
```

Expand Down Expand Up @@ -71,10 +70,10 @@ Type: `mediaRecorderOptions?: MaybeRef<MediaRecorderOptions>`

```ts
interface MediaRecorderOptions {
audioBitsPerSecond?: number;
bitsPerSecond?: number;
mimeType?: string;
videoBitsPerSecond?: number;
audioBitsPerSecond?: number
bitsPerSecond?: number
mimeType?: string
videoBitsPerSecond?: number
}
```

Expand Down
1 change: 1 addition & 0 deletions playgrounds/nuxt/app/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<template>
<ClientOnly>
<RecorderDemo />
<RecorderDemoComponent />
</ClientOnly>
</template>
40 changes: 40 additions & 0 deletions playgrounds/nuxt/app/components/recorder-demo-component.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<script setup lang="ts">
// import { UseMediaRecorder} from '@orbisk/vue-use-media-recorder' // TODO: why?
// function handleStop() {
// stop()
// const blob = new Blob(data.value)
// const blobVideo = new Blob(data.value)
// audio.value.src = URL.createObjectURL(blob)
// video.value.src = URL.createObjectURL(blobVideo)
// }
const stopped = ref(false)
</script>

<template>
<UseMediaRecorder :constraints="{ audio: true }" @stop="stopped = true" @start="stopped = false">
<template #default="slotProps">
<button @click="() => slotProps.start()">
start
</button>
<button @click="slotProps.pause">
pause
</button>
<button @click="slotProps.resume">
resume
</button>
<button @click="slotProps.stop">
stop
</button>
<audio controls>
<source v-if="stopped" :src="URL.createObjectURL(new Blob(slotProps.data))">
</audio>
<pre>state: {{ slotProps.state }}</pre>
<pre>supported: {{ slotProps.isSupported }}</pre>
<pre>mime type: {{ slotProps.mimeType }}</pre>
<pre>mime supported: {{ slotProps.isMimeTypeSupported }}</pre>
<pre>data length: {{ slotProps.data?.length }}</pre>
</template>
</UseMediaRecorder>
</template>
28 changes: 11 additions & 17 deletions playgrounds/nuxt/app/components/recorder-demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,32 @@
const audio = ref()
const video = ref()
const onStop = ()=>{
console.log("onstop")
}
const { start, stop, pause, resume, data, state, isMimeTypeSupported, isSupported, mimeType } = useMediaRecorder({
constraints: {
audio: true,
video: false,
},
onStop,
onStop: () => {
const blob = new Blob(data.value)
const blobVideo = new Blob(data.value)
audio.value.src = URL.createObjectURL(blob)
video.value.src = URL.createObjectURL(blobVideo)
},
})
function handleStop() {
console.log('stop')
stop()
const blob = new Blob(data.value)
const blobVideo = new Blob(data.value)
audio.value.src = URL.createObjectURL(blob)
video.value.src = URL.createObjectURL(blobVideo)
}
</script>

<template>
<div>
<button @click="()=>start()">
<button @click="() => start()">
start
</button>
<button @click="pause">
<button @click="() => pause()">
pause
</button>
<button @click="resume">
<button @click="() => resume()">
resume
</button>
<button @click="handleStop">
<button @click="() => stop()">
stop
</button>
<audio ref="audio" controls />
Expand All @@ -42,6 +36,6 @@ function handleStop() {
<pre>supported: {{ isSupported }}</pre>
<pre>mime type: {{ mimeType }}</pre>
<pre>mime supported: {{ isMimeTypeSupported }}</pre>
<pre>data length: {{ data?.length}}</pre>
<pre>data length: {{ data?.length }}</pre>
</div>
</template>
63 changes: 63 additions & 0 deletions src/components/UseMediaRecorder.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<script setup lang="ts">
import { useMediaRecorder } from '@orbisk/vue-use-media-recorder'
const props = defineProps({
constraints: {
type: Object,
required: true,
validator(value: unknown): boolean {
if (!value.audio && !value.video) {
console.error('constraints must have at least one of audio or video')
return false
}
},
},
mediaRecorderOptions: {
type: Object,
default: () => ({}),
},
})
const emit = defineEmits<{
start: [ev: Event]
stop: [ev: Event]
pause: [ev: Event]
resume: [ev: Event]
error: [ev: Event]
}>()
const onStart = (...args) => emit('start', ...args)
const onStop = (...args) => emit('stop', ...args)
const onPause = (...args) => emit('pause', ...args)
const onResume = (...args) => emit('resume', ...args)
const onError = (...args) => emit('error', ...args)
const {
data,
stream,
mimeType,
isSupported,
isMimeTypeSupported,
mediaRecorder,
start,
pause,
resume,
stop,
state,
} = useMediaRecorder({ constraints: props.constraints, mediaRecorderOptions: props.mediaRecorderOptions, onStart, onResume, onPause, onStop, onError })
defineExpose({
start,
stop,
resume,
pause,
})
</script>

<template>
<slot
:data="data" :stream="stream" :mime-type="mimeType" :media-recorder="mediaRecorder" :is-supported="isSupported"
:is-mime-type-supported="isMimeTypeSupported" :state="state" :start="start" :stop="stop" :pause="pause" :resume="resume"
/>
</template>
10 changes: 5 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Components
// export { default as Toggle } from './components/Toggle.vue'
export { default as UseMediaRecorder } from './components/UseMediaRecorder.vue'

// Plugin
export { default as MediaRecorderPlugin } from './plugin'

// Types
export type { MediaRecorderPluginOptions } from './types'

// Composables
export { useMediaRecorder } from './useMediaRecorder'

// Types
export type {MediaRecorderPluginOptions} from './types'
export type {UseMediaRecorderReturn} from './useMediaRecorder'
export type { UseMediaRecorderReturn } from './useMediaRecorder'
Loading

0 comments on commit b0c39ba

Please sign in to comment.