@@ -4,8 +4,7 @@ import { useSupported } from '@vueuse/core'
4
4
import { tryOnScopeDispose } from '@vueuse/shared'
5
5
import { defu } from 'defu'
6
6
import { computed , ref , shallowRef , toValue , watch } from 'vue'
7
-
8
- export { MediaRecorderPlugin } from './plugin'
7
+ import { computedWithControl } from '@vueuse/core'
9
8
10
9
interface UseMediaRecorderOptions extends ConfigurableNavigator {
11
10
/**
@@ -20,13 +19,14 @@ interface UseMediaRecorderOptions extends ConfigurableNavigator {
20
19
21
20
const defaultOptions : UseMediaRecorderOptions = {
22
21
constraints : { audio : false , video : false } ,
23
- mediaRecorderOptions : { } ,
22
+ mediaRecorderOptions : { }
24
23
}
25
24
26
25
export function useMediaRecorder ( options : UseMediaRecorderOptions = { } ) {
27
26
const data = ref < Blob [ ] > ( [ ] )
28
27
const mediaRecorder = shallowRef < MediaRecorder > ( )
29
28
const stream = shallowRef < MediaStream > ( )
29
+ const result = shallowRef < Blob [ ] > ( [ ] )
30
30
31
31
const isMimeTypeSupported = computed ( ( ) => {
32
32
return toValue ( options . mediaRecorderOptions ) ?. mimeType ? MediaRecorder . isTypeSupported ( toValue ( options . mediaRecorderOptions ) ?. mimeType ?? '' ) : true
@@ -35,66 +35,67 @@ export function useMediaRecorder(options: UseMediaRecorderOptions = {}) {
35
35
return ! ! navigator ?. mediaDevices ?. getUserMedia && isMimeTypeSupported . value
36
36
} )
37
37
38
- const state = shallowRef < RecordingState | undefined > ( undefined )
38
+ const state = computedWithControl < RecordingState | undefined > ( ( ) => mediaRecorder . value , ( ) => {
39
+ return mediaRecorder . value ?. state
40
+ } )
39
41
40
- const mimeType = shallowRef < string | undefined > ( undefined )
42
+ const mimeType = computedWithControl < string | undefined > ( ( ) => mediaRecorder . value , ( ) => {
43
+ return mediaRecorder . value ?. mimeType
44
+ } )
41
45
42
46
const updateStates = ( ) => {
43
- state . value = mediaRecorder . value ?. state
47
+ state . trigger ( )
44
48
}
45
49
46
50
const {
47
51
mediaRecorderOptions,
48
- constraints,
52
+ constraints
49
53
} = defu ( options , defaultOptions )
50
54
51
55
const start = async ( timeslice : number | undefined = undefined ) => {
52
56
if ( state . value === 'recording' )
53
57
return // todo warning?
58
+ data . value = [ ]
54
59
stream . value = await navigator ! . mediaDevices . getUserMedia ( toValue ( constraints ) )
55
60
mediaRecorder . value = new MediaRecorder ( stream . value , toValue ( mediaRecorderOptions ) )
56
- data . value = [ ]
57
61
mediaRecorder . value ?. start ( timeslice )
58
- updateStates ( )
59
- }
60
-
61
- const reset = ( ) => {
62
- stream . value ?. getTracks ( ) . forEach ( t => t . stop ( ) )
63
- stream . value = undefined
64
- mediaRecorder . value ?. stop ( )
65
62
}
66
63
67
64
const stop = ( ) => {
68
65
if ( ! state . value || state . value === 'inactive' )
69
66
return // todo warning?
70
- reset ( )
71
- updateStates ( )
67
+ mediaRecorder . value ?. stop ( )
72
68
}
73
69
74
70
const pause = ( ) => {
75
71
if ( state . value !== 'recording' )
76
72
return // todo warning?
77
73
mediaRecorder . value ?. pause ( )
78
- updateStates ( )
79
74
}
80
75
81
76
const resume = ( ) => {
82
77
if ( state . value !== 'paused' )
83
78
return // todo warning?
84
79
mediaRecorder . value ?. resume ( )
85
- updateStates ( )
86
80
}
87
81
88
82
watch ( ( ) => mediaRecorder . value , ( newMediaRecorder ) => {
89
83
if ( ! newMediaRecorder )
90
84
return
91
85
newMediaRecorder . ondataavailable = ( e ) => {
92
86
const blob = e . data
93
- if ( blob . type !== mimeType . value ) {
94
- mimeType . value = blob . type ?? mediaRecorder . value ?. mimeType
95
- }
87
+ mimeType . trigger ( )
96
88
data . value . push ( e . data )
97
89
}
90
+ newMediaRecorder . onstop = ( ) => {
91
+ stream . value ?. getTracks ( ) . forEach ( t => t . stop ( ) )
92
+ result . value = data . value
93
+ updateStates ( )
94
+ }
95
+ newMediaRecorder . onpause = updateStates
96
+ newMediaRecorder . onresume = updateStates
97
+ newMediaRecorder . onstart = updateStates
98
+ newMediaRecorder . onerror = updateStates
98
99
} , { immediate : true } )
99
100
100
101
tryOnScopeDispose ( ( ) => {
@@ -112,7 +113,7 @@ export function useMediaRecorder(options: UseMediaRecorderOptions = {}) {
112
113
isSupported,
113
114
isMimeTypeSupported,
114
115
mimeType : computed ( ( ) => mimeType . value ) ,
115
- mediaRecorder : computed ( ( ) => mediaRecorder . value ) ,
116
+ mediaRecorder : computed ( ( ) => mediaRecorder . value )
116
117
}
117
118
}
118
119
0 commit comments