Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
5dfff7a
first pass
dawoodkhan82 Mar 11, 2025
92e92e7
Merge branch 'main' into screen-recording
dawoodkhan82 Mar 12, 2025
99eda92
canvas version comp
dawoodkhan82 Mar 17, 2025
1bd8626
add changeset
gradio-pr-bot Mar 18, 2025
706e863
process video backend using ffmpeg
dawoodkhan82 Mar 20, 2025
07d52a3
fix
dawoodkhan82 Mar 20, 2025
2059eaa
remove zoom effects
dawoodkhan82 Mar 21, 2025
97fafe9
Merge branch 'main' into screen-recording
dawoodkhan82 Mar 22, 2025
39febed
fixes
dawoodkhan82 Mar 22, 2025
1a991a7
format
dawoodkhan82 Mar 22, 2025
7ef6dbf
mp4
dawoodkhan82 Mar 22, 2025
ce5e8c2
add changeset
gradio-pr-bot Mar 22, 2025
a342fe6
remove watermark
dawoodkhan82 Mar 22, 2025
f870faf
add back processing
dawoodkhan82 Apr 9, 2025
4dfb2b5
Merge branch 'main' into screen-recording
dawoodkhan82 Apr 10, 2025
83641fd
zoom working
dawoodkhan82 Apr 12, 2025
f7d6b2e
gradual zoom
dawoodkhan82 Apr 14, 2025
b3c66c3
zoom fix
dawoodkhan82 Apr 15, 2025
806ecdf
convert to mp4
dawoodkhan82 Apr 15, 2025
a924c82
zoom speed
dawoodkhan82 Apr 15, 2025
87dd4bd
remove padding
dawoodkhan82 Apr 15, 2025
dfb55ed
resolution and fps fix
dawoodkhan82 Apr 21, 2025
2037af3
Merge branch 'main' into screen-recording
dawoodkhan82 Apr 22, 2025
28a84a3
zoom level
dawoodkhan82 Apr 22, 2025
52a5070
remove comments
dawoodkhan82 Apr 22, 2025
732fbc2
adjust zoom level + format
dawoodkhan82 Apr 22, 2025
bf8aac7
fix
dawoodkhan82 Apr 22, 2025
6151e1d
Merge branch 'main' into screen-recording
dawoodkhan82 Apr 22, 2025
864fadf
fix
dawoodkhan82 Apr 23, 2025
4a174e6
Merge branch 'main' into screen-recording
dawoodkhan82 Apr 23, 2025
a7454c6
notebooks
dawoodkhan82 Apr 23, 2025
f22710a
changes
dawoodkhan82 Apr 23, 2025
0d8ae75
adjust pan
dawoodkhan82 Apr 23, 2025
99882c2
format
dawoodkhan82 Apr 23, 2025
455a253
Merge branch 'main' into screen-recording
dawoodkhan82 Apr 23, 2025
d7a1e53
lint
dawoodkhan82 Apr 23, 2025
37d393f
ui changes
dawoodkhan82 Apr 24, 2025
3123392
format
dawoodkhan82 Apr 24, 2025
2aefa95
fix examples issue
dawoodkhan82 Apr 24, 2025
101ee21
better centering
dawoodkhan82 Apr 25, 2025
d55867f
merge
dawoodkhan82 Apr 25, 2025
ff2f6c9
fix time remap issue
dawoodkhan82 Apr 25, 2025
0b3ad9e
check for overlapping zooms
dawoodkhan82 Apr 25, 2025
12ed8bc
Merge branch 'main' into screen-recording
dawoodkhan82 Apr 28, 2025
41451ab
show ffmpeg error message
dawoodkhan82 Apr 28, 2025
2403257
enfore 30 fps
dawoodkhan82 Apr 28, 2025
1d0b448
Merge branch 'main' into screen-recording
dawoodkhan82 Apr 28, 2025
f73e48d
remove info toast + better zoom on safari
dawoodkhan82 Apr 30, 2025
4f6c57f
Merge branch 'main' into screen-recording
dawoodkhan82 Apr 30, 2025
e02b1b6
fix tests
dawoodkhan82 Apr 30, 2025
fd6691f
format
dawoodkhan82 May 1, 2025
5452caf
Merge branch 'main' into screen-recording
dawoodkhan82 May 1, 2025
5fb7f7a
Merge branch 'main' into screen-recording
abidlabs May 14, 2025
dbffed8
examples + trim start
dawoodkhan82 May 15, 2025
a6bf4e7
move recording to settings
dawoodkhan82 May 15, 2025
6cdb60e
Merge branch 'main' into screen-recording
dawoodkhan82 May 15, 2025
d949e7f
add settings for zoom/trim
dawoodkhan82 May 15, 2025
833363b
temp file fix
dawoodkhan82 May 16, 2025
b763c13
Merge branch 'main' into screen-recording
dawoodkhan82 May 16, 2025
1f0ee69
tempfile
dawoodkhan82 May 19, 2025
4165cd1
format
dawoodkhan82 May 19, 2025
a67ffa9
Merge branch 'main' into screen-recording
dawoodkhan82 May 19, 2025
31d5c51
test fix
dawoodkhan82 May 20, 2025
2814878
Merge branch 'main' into screen-recording
dawoodkhan82 May 20, 2025
76dd5d4
format
dawoodkhan82 May 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/old-coins-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@gradio/core": minor
"gradio": minor
---

feat:Screen recording
106 changes: 105 additions & 1 deletion gradio/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
create_lifespan_handler,
move_uploaded_files_to_cache,
)
from gradio.screen_recording_utils import process_video_with_ffmpeg
from gradio.server_messages import (
CloseStreamMessage,
EstimationMessage,
Expand All @@ -117,6 +118,8 @@
if TYPE_CHECKING:
from gradio.blocks import Block

import shutil
import tempfile

mimetypes.init()

Expand Down Expand Up @@ -152,6 +155,10 @@
"application/json",
}

DEFAULT_TEMP_DIR = os.environ.get("GRADIO_TEMP_DIR") or str(
Path(tempfile.gettempdir()) / "gradio"
)


class ORJSONResponse(JSONResponse):
media_type = "application/json"
Expand Down Expand Up @@ -1769,8 +1776,105 @@ async def analytics_dashboard(key: str):
else:
raise HTTPException(status_code=403, detail="Invalid key.")

app.include_router(router)
@router.post("/process_recording", dependencies=[Depends(login_check)])
async def process_recording(
request: fastapi.Request,
):
try:
content_type_header = request.headers.get("Content-Type")
content_type: bytes
content_type, _ = parse_options_header(content_type_header or "")
if content_type != b"multipart/form-data":
raise HTTPException(status_code=400, detail="Invalid content type.")

app = request.app
max_file_size = (
app.get_blocks().max_file_size
if hasattr(app, "get_blocks")
else None
)
max_file_size = max_file_size if max_file_size is not None else math.inf

multipart_parser = GradioMultiPartParser(
request.headers,
request.stream(),
max_files=1,
max_fields=10,
max_file_size=max_file_size,
)
form = await multipart_parser.parse()
except MultiPartException as exc:
code = 413 if "maximum allowed size" in exc.message else 400
return PlainTextResponse(exc.message, status_code=code)

video_files = form.getlist("video")
if not video_files or not isinstance(video_files[0], GradioUploadFile):
raise HTTPException(status_code=400, detail="No video file provided")

video_file = video_files[0]

params = {}
if (
form.get("remove_segment_start") is not None
and form.get("remove_segment_end") is not None
):
params["remove_segment_start"] = form.get("remove_segment_start")
params["remove_segment_end"] = form.get("remove_segment_end")

zoom_effects_json = form.get("zoom_effects")
if zoom_effects_json:
try:
params["zoom_effects"] = json.loads(str(zoom_effects_json))
except json.JSONDecodeError:
params["zoom_effects"] = []

with tempfile.NamedTemporaryFile(
delete=False, suffix=".mp4", dir=DEFAULT_TEMP_DIR
) as input_file:
video_file.file.seek(0)
shutil.copyfileobj(video_file.file, input_file)
input_path = input_file.name

if wasm_utils.IS_WASM or shutil.which("ffmpeg") is None:
return FileResponse(
input_path,
media_type="video/mp4",
filename="gradio-screen-recording.mp4",
background=BackgroundTask(lambda: cleanup_files([input_path])),
)

output_path = tempfile.mkstemp(
suffix="_processed.mp4", dir=DEFAULT_TEMP_DIR
)[1]

try:
processed_path, temp_files = await process_video_with_ffmpeg(
input_path, output_path, params
)

return FileResponse(
processed_path,
media_type="video/mp4",
filename="gradio-screen-recording.mp4",
background=BackgroundTask(lambda: cleanup_files(temp_files)),
)
except Exception:
return FileResponse(
input_path,
media_type="video/mp4",
filename="gradio-screen-recording.mp4",
background=BackgroundTask(lambda: cleanup_files([input_path])),
)

def cleanup_files(files):
for file in files:
try:
if file and os.path.exists(file):
os.unlink(file)
except Exception as e:
print(f"Error cleaning up file {file}: {str(e)}")

app.include_router(router)
return app


Expand Down
Loading
Loading