Commit ·
3847eb5
1
Parent(s): 1a0c4c0
Patch Gradio's video-conversion race that kills the generation connection
Browse filesconvert_video_to_playable_mp4() writes ffmpeg output to
Path(video_path).with_suffix(".mp4"), a no-op rename when the upload
is already *.mp4 (e.g. HEVC-in-mp4). It overwrites that file in place
while the browser is still streaming it for the preview widget, which
corrupts the response and — since HF Spaces multiplexes a tab over one
HTTP/2 connection — takes the whole connection down, including the
live generation job's SSE queue. Convert a copy instead so the file
being served is never mutated mid-stream.
app.py
CHANGED
|
@@ -29,6 +29,31 @@ import spaces
|
|
| 29 |
import gradio as gr
|
| 30 |
from huggingface_hub import HfApi, hf_hub_download, snapshot_download
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
# ================================================================== #
|
| 33 |
# CHECKPOINT CONFIGURATION #
|
| 34 |
# ================================================================== #
|
|
|
|
| 29 |
import gradio as gr
|
| 30 |
from huggingface_hub import HfApi, hf_hub_download, snapshot_download
|
| 31 |
|
| 32 |
+
# ------------------------------------------------------------------ #
|
| 33 |
+
# Gradio's own Video component (processing_utils.convert_video_to_ #
|
| 34 |
+
# playable_mp4) writes its ffmpeg output to Path(video_path) #
|
| 35 |
+
# .with_suffix(".mp4") — a no-op rename whenever the upload is #
|
| 36 |
+
# already named *.mp4 (e.g. HEVC-in-mp4). That makes it overwrite the #
|
| 37 |
+
# exact file the browser is concurrently streaming for the live #
|
| 38 |
+
# preview widget, corrupting the response mid-flight. Since HF Spaces #
|
| 39 |
+
# multiplexes a whole browser tab over one HTTP/2 connection, that #
|
| 40 |
+
# corrupted stream takes the *entire* connection down with it — even #
|
| 41 |
+
# unrelated in-flight requests like the generation job's SSE queue. #
|
| 42 |
+
# Patch it to convert a same-named copy instead, so the file the #
|
| 43 |
+
# browser already has a handle on is never mutated in place. #
|
| 44 |
+
import gradio.processing_utils as _gr_processing_utils
|
| 45 |
+
_gr_convert_video_to_playable_mp4 = _gr_processing_utils.convert_video_to_playable_mp4
|
| 46 |
+
|
| 47 |
+
def _patched_convert_video_to_playable_mp4(video_path: str) -> str:
|
| 48 |
+
p = Path(video_path)
|
| 49 |
+
if p.suffix.lower() == ".mp4":
|
| 50 |
+
copy_path = str(p.with_name(p.stem + "_gr_conv.mp4"))
|
| 51 |
+
shutil.copy2(video_path, copy_path)
|
| 52 |
+
video_path = copy_path
|
| 53 |
+
return _gr_convert_video_to_playable_mp4(video_path)
|
| 54 |
+
|
| 55 |
+
_gr_processing_utils.convert_video_to_playable_mp4 = _patched_convert_video_to_playable_mp4
|
| 56 |
+
|
| 57 |
# ================================================================== #
|
| 58 |
# CHECKPOINT CONFIGURATION #
|
| 59 |
# ================================================================== #
|