Skip to content

Commit c7c689b

Browse files
authored
feat(recording): add frame rate, resolution and bitrate controls (#2175)
1 parent 584c000 commit c7c689b

File tree

2 files changed

+59
-5
lines changed

2 files changed

+59
-5
lines changed

packages/client/internals/RecordingDialog.vue

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
import { useVModel } from '@vueuse/core'
33
import { nextTick } from 'vue'
4-
import { getFilename, mimeType, recordCamera, recorder, recordingName } from '../logic/recording'
4+
import { bitRate, frameRate, getFilename, mimeType, recordCamera, recorder, recordingName, resolution } from '../logic/recording'
55
import DevicesSelectors from './DevicesSelectors.vue'
66
import Modal from './Modal.vue'
77
@@ -18,6 +18,14 @@ const value = useVModel(props, 'modelValue', emit)
1818
1919
const { startRecording } = recorder
2020
21+
const frameRateOptions = [15, 24, 30, 60]
22+
const resolutionOptions = [
23+
{ value: '1280x720', label: '720p (1280x720)' },
24+
{ value: '1920x1080', label: '1080p (1920x1080)' },
25+
{ value: '2560x1440', label: '1440p (2560x1440)' },
26+
{ value: '3840x2160', label: '2160p (3840x2160)' },
27+
]
28+
2129
function close() {
2230
value.value = false
2331
}
@@ -27,6 +35,7 @@ async function start() {
2735
await nextTick()
2836
startRecording({
2937
mimeType: mimeType.value,
38+
bitsPerSecond: bitRate.value * 1024,
3039
})
3140
}
3241
</script>
@@ -51,6 +60,48 @@ async function start() {
5160
<div>This will be used in the output filename that might <br>help you better organize your recording chips.</div>
5261
</div>
5362
</div>
63+
64+
<div class="form-text">
65+
<label for="framerate">Frame Rate</label>
66+
<select
67+
v-model="frameRate"
68+
class="bg-transparent text-current border border-main rounded px-2 py-1"
69+
name="framerate"
70+
>
71+
<option v-for="rate in frameRateOptions" :key="rate" :value="rate">
72+
{{ rate }} fps
73+
</option>
74+
</select>
75+
</div>
76+
77+
<div class="form-text">
78+
<label for="resolution">Resolution</label>
79+
<select
80+
v-model="resolution"
81+
class="bg-transparent text-current border border-main rounded px-2 py-1"
82+
name="resolution"
83+
>
84+
<option v-for="res in resolutionOptions" :key="res.value" :value="res.value">
85+
{{ res.label }}
86+
</option>
87+
</select>
88+
</div>
89+
90+
<div class="form-text">
91+
<label for="bitrate">Bitrate</label>
92+
<div class="relative">
93+
<input
94+
v-model.number="bitRate"
95+
type="number"
96+
min="1000"
97+
step="1000"
98+
class="bg-transparent text-current border border-main rounded px-2 py-1 w-full pr-12"
99+
name="bitrate"
100+
>
101+
<span class="absolute right-3 top-1/2 transform -translate-y-1/2 text-sm opacity-50">kbps</span>
102+
</div>
103+
</div>
104+
54105
<div class="form-check">
55106
<input
56107
v-model="recordCamera"

packages/client/logic/recording.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ type MimeType = Defined<RecorderOptions['mimeType']>
1212
export const recordingName = ref('')
1313
export const recordCamera = ref(true)
1414
export const mimeType = useLocalStorage<MimeType>('slidev-record-mimetype', 'video/webm')
15+
export const frameRate = useLocalStorage<number>('slidev-record-framerate', 30)
16+
export const bitRate = useLocalStorage<number>('slidev-record-bitrate', 8192)
17+
export const resolution = useLocalStorage<string>('slidev-record-resolution', '1920x1080')
1518

1619
export const mimeExtMap: Record<string, string> = {
1720
'video/webm': 'webm',
@@ -78,7 +81,6 @@ export function useRecording() {
7881

7982
const config: RecorderOptions = {
8083
type: 'video',
81-
bitsPerSecond: 4 * 256 * 8 * 1024,
8284
// Extending recording limit as default is only 1h (see https://github.com/muaz-khan/RecordRTC/issues/144)
8385
timeSlice: 24 * 60 * 60 * 1000,
8486
}
@@ -141,12 +143,13 @@ export function useRecording() {
141143
const { default: Recorder } = await import('recordrtc')
142144
await startCameraStream()
143145

146+
const [width, height] = resolution.value.split('x').map(Number)
144147
streamCapture.value = await navigator.mediaDevices.getDisplayMedia({
145148
video: {
146149
// aspectRatio: 1.6,
147-
frameRate: 15,
148-
width: 3840,
149-
height: 2160,
150+
frameRate: frameRate.value,
151+
width,
152+
height,
150153
// @ts-expect-error missing types
151154
cursor: 'motion',
152155
resizeMode: 'crop-and-scale',

0 commit comments

Comments
 (0)