Skip to content

Commit 88cdacc

Browse files
committed
feat: allow stopping when paused
1 parent 838586d commit 88cdacc

File tree

7 files changed

+63
-33
lines changed

7 files changed

+63
-33
lines changed

changelog.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ChangelogConfig } from 'changelogen'
22

33
export default {
4-
excludeAuthors: ['robin.kehl@singular-it.de']
5-
} satisfies ChangelogConfig
4+
excludeAuthors: ['robin.kehl@singular-it.de'],
5+
} satisfies ChangelogConfig

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
export { useMediaRecorder } from './useMediaRecorder'
66

77
// Types
8-
// export * from './types'
8+
// export * from './types'

src/plugin/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ import type { App } from 'vue'
22
import type { MediaRecorderPluginOptions } from '../types'
33

44
export const MediaRecorderPlugin = {
5-
install(app: App, _options?: MediaRecorderPluginOptions) {
5+
install(_app: App, _options?: MediaRecorderPluginOptions) {
66
// app.provide(EXAMPLE, options?.example)
77

88
// Add auto imports
99

10-
1110
// app.component('Toggle', ToggleComponent)
1211
},
1312
}

src/useMediaRecorder.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { shallowRef, ref, toValue, computed, watch } from 'vue'
2-
import type { MaybeRef } from 'vue'
31
import type { ConfigurableNavigator } from '@vueuse/core'
2+
import type { MaybeRef } from 'vue'
43
import { useSupported } from '@vueuse/core'
5-
import { defu } from 'defu'
64
import { tryOnScopeDispose } from '@vueuse/shared'
5+
import { defu } from 'defu'
6+
import { computed, ref, shallowRef, toValue, watch } from 'vue'
77

88
export { MediaRecorderPlugin } from './plugin'
99

@@ -20,7 +20,7 @@ interface UseMediaRecorderOptions extends ConfigurableNavigator {
2020

2121
const defaultOptions: UseMediaRecorderOptions = {
2222
constraints: { audio: false, video: false },
23-
mediaRecorderOptions: {}
23+
mediaRecorderOptions: {},
2424
}
2525

2626
export function useMediaRecorder(options: UseMediaRecorderOptions = {}) {
@@ -29,7 +29,7 @@ export function useMediaRecorder(options: UseMediaRecorderOptions = {}) {
2929
const stream = shallowRef<MediaStream>()
3030

3131
const isMimeTypeSupported = computed(() => {
32-
return !!toValue(options.mediaRecorderOptions)?.mimeType ? MediaRecorder.isTypeSupported(toValue(options.mediaRecorderOptions)?.mimeType ?? '') : true
32+
return toValue(options.mediaRecorderOptions)?.mimeType ? MediaRecorder.isTypeSupported(toValue(options.mediaRecorderOptions)?.mimeType ?? '') : true
3333
})
3434
const isSupported = useSupported(() => {
3535
return !!navigator?.mediaDevices?.getUserMedia && isMimeTypeSupported.value
@@ -45,7 +45,7 @@ export function useMediaRecorder(options: UseMediaRecorderOptions = {}) {
4545

4646
const {
4747
mediaRecorderOptions,
48-
constraints
48+
constraints,
4949
} = defu(options, defaultOptions)
5050

5151
const start = async (timeslice: number | undefined = undefined) => {
@@ -65,7 +65,7 @@ export function useMediaRecorder(options: UseMediaRecorderOptions = {}) {
6565
}
6666

6767
const stop = () => {
68-
if (state.value !== 'recording')
68+
if (!state.value || state.value === 'inactive')
6969
return // todo warning?
7070
reset()
7171
updateStates()
@@ -112,8 +112,8 @@ export function useMediaRecorder(options: UseMediaRecorderOptions = {}) {
112112
isSupported,
113113
isMimeTypeSupported,
114114
mimeType,
115-
mediaRecorder: computed(() => mediaRecorder.value)
115+
mediaRecorder: computed(() => mediaRecorder.value),
116116
}
117117
}
118118

119-
export type UseMediaRecorderReturn = ReturnType<typeof useMediaRecorder>
119+
export type UseMediaRecorderReturn = ReturnType<typeof useMediaRecorder>

tests/index.spec.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ describe('useMediaRecorder', () => {
3636
expect(data.value?.length).toBe(0)
3737
await start(10)
3838
await new Promise(resolve => setTimeout(resolve, 100))
39-
console.log(data.value)
4039
expect(data.value?.length).toBeGreaterThan(0)
4140
})
4241

@@ -88,27 +87,59 @@ describe('useMediaRecorder', () => {
8887
it('mime type should be defined after recording', async () => {
8988
const {
9089
start,
91-
mimeType
90+
mimeType,
9291
} = useMediaRecorder({ constraints: { audio: true } })
9392
expect(mimeType.value).toBeUndefined()
9493
await start(10)
9594
await new Promise(resolve => setTimeout(resolve, 200))
9695
expect(mimeType.value).toBeDefined()
9796
})
9897

99-
it('should be supported',()=>{
98+
it('should be supported', () => {
10099
const {
101-
isSupported
100+
isSupported,
102101
} = useMediaRecorder({ constraints: { audio: true } })
103102
expect(isSupported.value).toBe(true)
104103
})
105104

106-
it('should not support unsupported mime type',()=>{
105+
it('should not support unsupported mime type', () => {
107106
const {
108107
isSupported,
109-
isMimeTypeSupported
108+
isMimeTypeSupported,
110109
} = useMediaRecorder({ constraints: { audio: true, video: true }, mediaRecorderOptions: { mimeType: 'video/does-not-exist' } })
111110
expect(isSupported.value).toBe(false)
112111
expect(isMimeTypeSupported.value).toBe(false)
113112
})
113+
114+
it('should be possible to stop recording when paused', async () => {
115+
const {
116+
start,
117+
pause,
118+
stop,
119+
state,
120+
} = useMediaRecorder({ constraints: { audio: true } })
121+
122+
await start()
123+
expect(state.value).toBe('recording')
124+
await pause()
125+
expect(state.value).toBe('paused')
126+
await stop()
127+
expect(state.value).toBe('inactive')
128+
})
129+
130+
it('data should exist when stoping from pause', async () => {
131+
const {
132+
start,
133+
pause,
134+
stop,
135+
data,
136+
} = useMediaRecorder({ constraints: { audio: true } })
137+
138+
expect(data.value).toHaveLength(0)
139+
await start(10)
140+
await new Promise(resolve => setTimeout(resolve, 100))
141+
await pause()
142+
await stop()
143+
expect(data.value.length).toBeGreaterThan(0)
144+
})
114145
})

vitest.config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { defineConfig } from 'vitest/config'
2-
import vue from '@vitejs/plugin-vue'
31
import { resolve } from 'node:path'
2+
import vue from '@vitejs/plugin-vue'
3+
import { defineConfig } from 'vitest/config'
44

55
export default defineConfig({
66
root: __dirname,
77
plugins: [
8-
vue()
8+
vue(),
99
],
1010
define: {
1111
dev: JSON.stringify(false),
@@ -24,4 +24,4 @@ export default defineConfig({
2424
},
2525
],
2626
},
27-
})
27+
})

vitest.workspace.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ export default defineWorkspace([
1414
context: {
1515
permissions: [
1616
'microphone',
17-
'camera'
18-
]
17+
'camera',
18+
],
1919
},
2020
launch: {
2121
args: [
2222
'--disable-web-security',
2323
'--use-fake-ui-for-media-stream',
24-
'--use-fake-device-for-media-stream'
25-
]
26-
}
27-
}
28-
}
29-
}
30-
}
24+
'--use-fake-device-for-media-stream',
25+
],
26+
},
27+
},
28+
},
29+
},
30+
},
3131
])

0 commit comments

Comments
 (0)