Skip to content

Commit

Permalink
reimplement webcam video (#928)
Browse files Browse the repository at this point in the history
* reimplement webcam video

* remove logs

* fix image webcam input
  • Loading branch information
pngwn authored Apr 6, 2022
1 parent 6e4e877 commit af5b555
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 11 deletions.
4 changes: 4 additions & 0 deletions ui/packages/image/src/Image.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
$: dispatch("change", value);
let dragging = false;
$: console.log($$props);
</script>

<Block
Expand Down Expand Up @@ -99,6 +101,8 @@
editable
/>

<img class="w-full h-full object-contain" src={value} alt="" />
{:else}
<img class="w-full h-full object-contain" src={value} alt="" />
{/if}
</div>
Expand Down
87 changes: 77 additions & 10 deletions ui/packages/image/src/Webcam.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<script lang="ts">
import { createEventDispatcher, onMount } from "svelte";
import camera from "./camera.svg";
import camera_icon from "./camera.svg";
import circle_icon from "./circle.svg";
import square_icon from "./square.svg";
let video_source: HTMLVideoElement;
let canvas: HTMLCanvasElement;
export let mode: "image" | "video" = "image";
const dispatch = createEventDispatcher();
onMount(() => (canvas = document.createElement("canvas")));
async function access_webcam() {
try {
const stream = await navigator.mediaDevices.getUserMedia({
stream = await navigator.mediaDevices.getUserMedia({
video: true
});
video_source.srcObject = stream;
Expand All @@ -27,7 +31,7 @@
context.fillRect(0, 0, canvas.width, canvas.height);
}
function takepicture() {
function take_picture() {
var context = canvas.getContext("2d")!;
if (video_source.videoWidth && video_source.videoHeight) {
Expand All @@ -46,23 +50,86 @@
}
}
let recording = false;
let recorded_blobs: BlobPart[] = [];
let stream: MediaStream;
let mimeType: string;
let media_recorder: MediaRecorder;
function take_recording() {
if (recording) {
media_recorder.stop();
let video_blob = new Blob(recorded_blobs, { type: mimeType });
let ReaderObj = new FileReader();
ReaderObj.onload = function (e) {
if (e.target) {
dispatch("capture", {
data: e.target.result,
name: "sample." + mimeType.substring(6),
is_example: false
});
}
};
ReaderObj.readAsDataURL(video_blob);
} else {
recorded_blobs = [];
let validMimeTypes = ["video/webm", "video/mp4"];
for (let validMimeType of validMimeTypes) {
if (MediaRecorder.isTypeSupported(validMimeType)) {
mimeType = validMimeType;
break;
}
}
if (mimeType === null) {
console.error("No supported MediaRecorder mimeType");
return;
}
media_recorder = new MediaRecorder(stream, {
mimeType: mimeType
});
media_recorder.addEventListener("dataavailable", function (e) {
recorded_blobs.push(e.data);
});
media_recorder.start(200);
}
recording = !recording;
}
access_webcam();
</script>

<div class="h-full w-full relative">
<!-- svelte-ignore a11y-media-has-caption -->
<video bind:this={video_source} class=" h-full w-full" />
<button
on:click={takepicture}
on:click={mode === "image" ? take_picture : take_recording}
style="background-color: #333;"
class="rounded-full w-10 h-10 flex justify-center items-center absolute inset-x-0 bottom-2 m-auto drop-shadow-lg"
>
<img
style="color: white"
src={camera}
alt="take a screenshot"
class="w-2/4 h-2/4"
/>
{#if mode === "video"}
{#if recording}
<img
style="color: white"
src={square_icon}
alt="take a screenshot"
class="w-2/4 h-2/4"
/>
{:else}
<img
style="color: white"
src={circle_icon}
alt="take a screenshot"
class="w-2/4 h-2/4"
/>
{/if}
{:else}
<img
style="color: white"
src={camera_icon}
alt="take a screenshot"
class="w-2/4 h-2/4"
/>
{/if}
</button>
</div>

Expand Down
2 changes: 1 addition & 1 deletion ui/packages/image/src/camera.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions ui/packages/image/src/circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions ui/packages/image/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as Image } from "./Image.svelte";
export { default as Webcam } from "./Webcam.svelte";
1 change: 1 addition & 0 deletions ui/packages/image/src/square.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions ui/packages/video/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"private": true,
"dependencies": {
"@gradio/atoms": "workspace:^0.0.1",
"@gradio/image": "workspace:^0.0.1",
"@gradio/upload": "workspace:^0.0.1"
}
}
3 changes: 3 additions & 0 deletions ui/packages/video/src/Video.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { Upload, ModifyUpload } from "@gradio/upload";
import type { FileData } from "@gradio/upload";
import { Block, BlockLabel } from "@gradio/atoms";
import { Webcam } from "@gradio/image";
import { prettyBytes, playable } from "./utils";
import video_icon from "./video.svg";
Expand Down Expand Up @@ -55,6 +56,8 @@
<br />- {or_text} -<br />
{upload_text}
</Upload>
{:else if source === "webcam"}
<Webcam mode="video" on:capture={({ detail }) => (value = detail)} />
{/if}
{:else}
<ModifyUpload on:clear={handle_clear} {theme} />
Expand Down
2 changes: 2 additions & 0 deletions ui/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit af5b555

Please sign in to comment.