Repository: gradio-app/gradio
Pull request: Fix issue with Webcam Recording
## Description
Fix issue with no video being passed to backend when recording with webcam.

Closes: #6872

## 🎯 PRs Should Target Issues

Before your create a PR, please check to see if there is [an existing issue](https://github.com/gradio-app/gradio/issues) for this change. If not, please create an issue before you create this PR, unless the fix is very small. 

Not adhering to this guideline will result in the PR being closed. 

## Tests

1. PRs will only be merged if tests pass on CI. To run the tests locally, please set up [your Gradio environment locally](https://github.com/gradio-app/gradio/blob/main/CONTRIBUTING.md) and run the tests: `bash scripts/run_all_tests.sh`

2. You may need to run the linters: `bash scripts/format_backend.sh` and `bash scripts/format_frontend.sh`
  


Problem statement:
gr.Video output showing empty 
### Describe the bug

**Problem statment:**
Trying to use gradio Video feature to allow apps to capture video from webcam, when clicking on record and submit video button a function process_video() get trigger, this function takes video as input and process further, looks like the gr.Video is not sending the video bytes to the function, hence, function call return None every time.

**Expected behaviour:**

The user should be able to capture gr.Video output and pass it to the function


### Have you searched existing issues?  🔎

- [X] I have searched and found no existing issues

### Reproduction

```python
import gradio as gr


def video_flip(video):
    if video is None:
        print("No Video")
    return video


iface = gr.Interface(video_flip, gr.Video(sources="webcam"), "playable_video")

iface.launch(share=False, debug=True)
```


### Screenshot

_No response_

### Logs

_No response_

### System Info

```shell
gradio                           4.11.0
gradio_client                    0.7.3

OS: MacOS
Notebook: Colab
```


### Severity

Blocking usage of gradio

Hints from issue discussion:
Hi @abidlabs Can you please help on this?. Thanks


I can repro this issue, we'll take a look!

Commit message: add changeset

Patch to review:
diff --git a/.changeset/few-toes-clap.md b/.changeset/few-toes-clap.md
new file mode 100644
index 0000000000..5c3451c1f7
--- /dev/null
+++ b/.changeset/few-toes-clap.md
@@ -0,0 +1,7 @@
+---
+"@gradio/image": patch
+"@gradio/video": patch
+"gradio": patch
+---
+
+fix:Fix issue with Webcam Recording
diff --git a/js/image/shared/Webcam.svelte b/js/image/shared/Webcam.svelte
index a1385ef1c3..7e98741c4b 100644
--- a/js/image/shared/Webcam.svelte
+++ b/js/image/shared/Webcam.svelte
@@ -1,12 +1,15 @@
 <script lang="ts">
-	import { createEventDispatcher, onMount, tick } from "svelte";
+	import { createEventDispatcher, onMount } from "svelte";
 	import { Camera, Circle, Square, DropdownArrow } from "@gradio/icons";
 	import type { I18nFormatter } from "@gradio/utils";
+	import type { FileData } from "@gradio/client";
+	import { prepare_files, upload } from "@gradio/client";
 
 	let video_source: HTMLVideoElement;
 	let canvas: HTMLCanvasElement;
 	export let streaming = false;
 	export let pending = false;
+	export let root = "";
 
 	export let mode: "image" | "video" = "image";
 	export let mirror_webcam: boolean;
@@ -15,7 +18,7 @@
 
 	const dispatch = createEventDispatcher<{
 		stream: undefined;
-		capture: Blob;
+		capture: FileData;
 		error: string;
 		start_recording: undefined;
 		stop_recording: undefined;
@@ -88,15 +91,14 @@
 			media_recorder.stop();
 			let video_blob = new Blob(recorded_blobs, { type: mimeType });
 			let ReaderObj = new FileReader();
-			ReaderObj.onload = function (e): void {
+			ReaderObj.onload = async function (e): Promise<void> {
 				if (e.target) {
-					dispatch("capture", {
-						//@ts-ignore
-						data: e.target.result,
-						name: "sample." + mimeType.substring(6),
-						is_example: false,
-						is_file: false
-					});
+					let _video_blob = new File([video_blob], "video.mp4");
+					const val = await prepare_files([_video_blob]);
+					let value = (
+						(await upload(val, root))?.filter(Boolean) as FileData[]
+					)[0];
+					dispatch("capture", value);
 					dispatch("stop_recording");
 				}
 			};
diff --git a/js/video/shared/InteractiveVideo.svelte b/js/video/shared/InteractiveVideo.svelte
index 2b01da2d7c..7ca4b3a675 100644
--- a/js/video/shared/InteractiveVideo.svelte
+++ b/js/video/shared/InteractiveVideo.svelte
@@ -57,6 +57,10 @@
 		dispatch("change", video);
 	}
 
+	function handle_capture({ detail }: CustomEvent<FileData | null>): void {
+		dispatch("change", detail);
+	}
+
 	let dragging = false;
 	$: dispatch("drag", dragging);
 </script>
@@ -77,11 +81,12 @@
 				</Upload>
 			{:else if active_source === "webcam"}
 				<Webcam
+					{root}
 					{mirror_webcam}
 					{include_audio}
 					mode="video"
 					on:error
-					on:capture={() => dispatch("change")}
+					on:capture={handle_capture}
 					on:start_recording
 					on:stop_recording
 					{i18n}


Code review comments:
diff_hunk: @@ -88,15 +91,14 @@
 			media_recorder.stop();
 			let video_blob = new Blob(recorded_blobs, { type: mimeType });
 			let ReaderObj = new FileReader();
-			ReaderObj.onload = function (e): void {
+			ReaderObj.onload = async function (e): Promise<void> {
 				if (e.target) {
-					dispatch("capture", {
-						//@ts-ignore
-						data: e.target.result,
-						name: "sample." + mimeType.substring(6),
-						is_example: false,
-						is_file: false
-					});
+					let _video_blob = new File([video_blob], "video.mp4");
path: js/image/shared/Webcam.svelte
text: @user1:
previously we had the logic `"sample." + mimeType.substring(6)` to get the file extension. Now it's always an mp4. Is that a safe assumption?

@author:
Good point, it can be `.webm` or `.mp4`. Fixed.