video switcher
Browse files
frontend/src/lib/components/MediaListSwitcher.svelte
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<script lang="ts">
|
2 |
+
import { mediaDevices, mediaStreamActions } from '$lib/mediaStream';
|
3 |
+
import { onMount } from 'svelte';
|
4 |
+
|
5 |
+
let deviceId: string = '';
|
6 |
+
$: {
|
7 |
+
console.log($mediaDevices);
|
8 |
+
}
|
9 |
+
$: {
|
10 |
+
console.log(deviceId);
|
11 |
+
}
|
12 |
+
onMount(() => {
|
13 |
+
deviceId = $mediaDevices[0].deviceId;
|
14 |
+
});
|
15 |
+
</script>
|
16 |
+
|
17 |
+
<div class="text-xs">
|
18 |
+
{#if $mediaDevices}
|
19 |
+
<select
|
20 |
+
bind:value={deviceId}
|
21 |
+
on:change={() => mediaStreamActions.switchCamera(deviceId)}
|
22 |
+
id="devices-list"
|
23 |
+
class="border-1 cursor-pointer rounded-md border-gray-500 border-opacity-50 bg-slate-100 bg-opacity-30 p-1 font-medium text-white"
|
24 |
+
>
|
25 |
+
{#each $mediaDevices as device, i}
|
26 |
+
<option value={device.deviceId}>{device.label}</option>
|
27 |
+
{/each}
|
28 |
+
</select>
|
29 |
+
{/if}
|
30 |
+
</div>
|
frontend/src/lib/components/VideoInput.svelte
CHANGED
@@ -5,14 +5,19 @@
|
|
5 |
mediaStreamStatus,
|
6 |
MediaStreamStatusEnum,
|
7 |
onFrameChangeStore,
|
8 |
-
mediaStream
|
|
|
9 |
} from '$lib/mediaStream';
|
|
|
10 |
|
11 |
let videoEl: HTMLVideoElement;
|
12 |
let videoFrameCallbackId: number;
|
13 |
const WIDTH = 512;
|
14 |
const HEIGHT = 512;
|
15 |
-
|
|
|
|
|
|
|
16 |
onDestroy(() => {
|
17 |
if (videoFrameCallbackId) videoEl.cancelVideoFrameCallback(videoFrameCallbackId);
|
18 |
});
|
@@ -20,7 +25,6 @@
|
|
20 |
$: if (videoEl) {
|
21 |
videoEl.srcObject = $mediaStream;
|
22 |
}
|
23 |
-
|
24 |
async function onFrameChange(now: DOMHighResTimeStamp, metadata: VideoFrameCallbackMetadata) {
|
25 |
const blob = await grapBlobImg();
|
26 |
onFrameChangeStore.set({ blob });
|
@@ -55,8 +59,13 @@
|
|
55 |
|
56 |
<div class="relative mx-auto max-w-lg overflow-hidden rounded-lg border border-slate-300">
|
57 |
<div class="relative z-10 aspect-square w-full object-cover">
|
|
|
|
|
|
|
|
|
|
|
58 |
<video
|
59 |
-
class="aspect-square w-full object-cover"
|
60 |
bind:this={videoEl}
|
61 |
playsinline
|
62 |
autoplay
|
|
|
5 |
mediaStreamStatus,
|
6 |
MediaStreamStatusEnum,
|
7 |
onFrameChangeStore,
|
8 |
+
mediaStream,
|
9 |
+
mediaDevices
|
10 |
} from '$lib/mediaStream';
|
11 |
+
import MediaListSwitcher from './MediaListSwitcher.svelte';
|
12 |
|
13 |
let videoEl: HTMLVideoElement;
|
14 |
let videoFrameCallbackId: number;
|
15 |
const WIDTH = 512;
|
16 |
const HEIGHT = 512;
|
17 |
+
let selectedDevice: string = '';
|
18 |
+
$: {
|
19 |
+
console.log(selectedDevice);
|
20 |
+
}
|
21 |
onDestroy(() => {
|
22 |
if (videoFrameCallbackId) videoEl.cancelVideoFrameCallback(videoFrameCallbackId);
|
23 |
});
|
|
|
25 |
$: if (videoEl) {
|
26 |
videoEl.srcObject = $mediaStream;
|
27 |
}
|
|
|
28 |
async function onFrameChange(now: DOMHighResTimeStamp, metadata: VideoFrameCallbackMetadata) {
|
29 |
const blob = await grapBlobImg();
|
30 |
onFrameChangeStore.set({ blob });
|
|
|
59 |
|
60 |
<div class="relative mx-auto max-w-lg overflow-hidden rounded-lg border border-slate-300">
|
61 |
<div class="relative z-10 aspect-square w-full object-cover">
|
62 |
+
{#if $mediaDevices.length > 0}
|
63 |
+
<div class="absolute bottom-0 right-0">
|
64 |
+
<MediaListSwitcher />
|
65 |
+
</div>
|
66 |
+
{/if}
|
67 |
<video
|
68 |
+
class="pointer-events-none aspect-square w-full object-cover"
|
69 |
bind:this={videoEl}
|
70 |
playsinline
|
71 |
autoplay
|
frontend/src/lib/mediaStream.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { writable, type Writable } from 'svelte/store';
|
2 |
|
3 |
export enum MediaStreamStatusEnum {
|
4 |
INIT = "init",
|
@@ -44,6 +44,9 @@ export const mediaStreamActions = {
|
|
44 |
});
|
45 |
},
|
46 |
async switchCamera(mediaDevicedID: string) {
|
|
|
|
|
|
|
47 |
const constraints = {
|
48 |
audio: false,
|
49 |
video: { width: 1024, height: 1024, deviceId: mediaDevicedID }
|
|
|
1 |
+
import { writable, type Writable, get } from 'svelte/store';
|
2 |
|
3 |
export enum MediaStreamStatusEnum {
|
4 |
INIT = "init",
|
|
|
44 |
});
|
45 |
},
|
46 |
async switchCamera(mediaDevicedID: string) {
|
47 |
+
if (get(mediaStreamStatus) !== MediaStreamStatusEnum.CONNECTED) {
|
48 |
+
return;
|
49 |
+
}
|
50 |
const constraints = {
|
51 |
audio: false,
|
52 |
video: { width: 1024, height: 1024, deviceId: mediaDevicedID }
|