MSzgy commited on
Commit ·
e810f2f
1
Parent(s): 5379333
Return public URLs from MCP media tools
Browse files
app.py
CHANGED
|
@@ -1800,6 +1800,38 @@ def build_gradio_media_url(media_path: Optional[str]) -> str:
|
|
| 1800 |
return f"{API_PREFIX or ''}/file={quote(source, safe='/:')}"
|
| 1801 |
|
| 1802 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1803 |
def _normalize_media_kind(media_kind: str) -> str:
|
| 1804 |
normalized = str(media_kind or "auto").strip().lower()
|
| 1805 |
if normalized in {"img", "image"}:
|
|
@@ -1943,9 +1975,9 @@ def prepare_media_input(media_value: Any, media_kind: str, required: bool = Fals
|
|
| 1943 |
|
| 1944 |
|
| 1945 |
def upload_file_to_gradio(file_url: str, media_type: str = "image") -> tuple[str, str]:
|
| 1946 |
-
"""Upload a remote image/video URL into this Gradio app and return a reusable local path plus a Gradio file URL."""
|
| 1947 |
local_path = prepare_media_input(file_url, _normalize_media_kind(media_type), required=True)
|
| 1948 |
-
return local_path,
|
| 1949 |
|
| 1950 |
|
| 1951 |
def build_example_media_html(media_path: Optional[str], media_type: str, fallback_media_path: Optional[str] = None) -> str:
|
|
@@ -3890,7 +3922,8 @@ def _format_mcp_media_result(result: tuple[Any, Any, str, str], output_kind: str
|
|
| 3890 |
output_video, output_image, _output_text, status = result
|
| 3891 |
output_path = output_video if output_kind == "video" else output_image
|
| 3892 |
if output_path:
|
| 3893 |
-
|
|
|
|
| 3894 |
return "", status or f"No output {output_kind} was produced."
|
| 3895 |
|
| 3896 |
|
|
@@ -3911,7 +3944,7 @@ def mcp_generate_video(
|
|
| 3911 |
validation_timestep_shift: float = DEFAULT_TIMESTEP_SHIFT,
|
| 3912 |
cfg_text_scale: float = DEFAULT_CFG_TEXT_SCALE,
|
| 3913 |
) -> tuple[str, str]:
|
| 3914 |
-
"""Generate a video from a text prompt. Returns the generated MP4
|
| 3915 |
result = _run_mcp_task(
|
| 3916 |
task=TASK_T2V,
|
| 3917 |
prompt=prompt,
|
|
@@ -3940,7 +3973,7 @@ def mcp_edit_video(
|
|
| 3940 |
validation_timestep_shift: float = DEFAULT_TIMESTEP_SHIFT,
|
| 3941 |
cfg_text_scale: float = DEFAULT_CFG_TEXT_SCALE,
|
| 3942 |
) -> tuple[str, str]:
|
| 3943 |
-
"""Edit an input video from a local path, Gradio file URL, or HTTP(S) URL. Returns the edited MP4
|
| 3944 |
result = _run_mcp_task(
|
| 3945 |
task=TASK_VIDEO_EDIT,
|
| 3946 |
prompt=prompt,
|
|
@@ -3994,7 +4027,7 @@ def mcp_generate_image(
|
|
| 3994 |
validation_timestep_shift: float = DEFAULT_TIMESTEP_SHIFT,
|
| 3995 |
cfg_text_scale: float = DEFAULT_CFG_TEXT_SCALE,
|
| 3996 |
) -> tuple[str, str]:
|
| 3997 |
-
"""Generate an image from a text prompt. Returns the generated image
|
| 3998 |
result = _run_mcp_task(
|
| 3999 |
task=TASK_T2I,
|
| 4000 |
prompt=prompt,
|
|
@@ -4021,7 +4054,7 @@ def mcp_edit_image(
|
|
| 4021 |
validation_timestep_shift: float = DEFAULT_TIMESTEP_SHIFT,
|
| 4022 |
cfg_text_scale: float = DEFAULT_CFG_TEXT_SCALE,
|
| 4023 |
) -> tuple[str, str]:
|
| 4024 |
-
"""Edit an input image from a local path, Gradio file URL, or HTTP(S) URL. Returns the edited image
|
| 4025 |
result = _run_mcp_task(
|
| 4026 |
task=TASK_IMAGE_EDIT,
|
| 4027 |
prompt=prompt,
|
|
@@ -4422,13 +4455,13 @@ def build_demo() -> gr.Blocks:
|
|
| 4422 |
video_steps = mcp_number("validation_num_timesteps", DEFAULT_TIMESTEPS)
|
| 4423 |
video_shift = mcp_number("validation_timestep_shift", DEFAULT_TIMESTEP_SHIFT)
|
| 4424 |
video_cfg = mcp_number("cfg_text_scale", DEFAULT_CFG_TEXT_SCALE)
|
| 4425 |
-
|
| 4426 |
video_status = mcp_text("status")
|
| 4427 |
video_button = gr.Button("MCP generate_video", visible=False)
|
| 4428 |
video_button.click(
|
| 4429 |
fn=mcp_generate_video,
|
| 4430 |
inputs=[video_prompt, video_resolution, video_aspect_ratio, video_duration, video_seed, video_steps, video_shift, video_cfg],
|
| 4431 |
-
outputs=[
|
| 4432 |
api_name="generate_video",
|
| 4433 |
show_progress="minimal",
|
| 4434 |
)
|
|
@@ -4442,7 +4475,7 @@ def build_demo() -> gr.Blocks:
|
|
| 4442 |
video_edit_steps = mcp_number("validation_num_timesteps", DEFAULT_TIMESTEPS)
|
| 4443 |
video_edit_shift = mcp_number("validation_timestep_shift", DEFAULT_TIMESTEP_SHIFT)
|
| 4444 |
video_edit_cfg = mcp_number("cfg_text_scale", DEFAULT_CFG_TEXT_SCALE)
|
| 4445 |
-
|
| 4446 |
video_edit_status = mcp_text("status")
|
| 4447 |
video_edit_button = gr.Button("MCP edit_video", visible=False)
|
| 4448 |
video_edit_button.click(
|
|
@@ -4458,7 +4491,7 @@ def build_demo() -> gr.Blocks:
|
|
| 4458 |
video_edit_shift,
|
| 4459 |
video_edit_cfg,
|
| 4460 |
],
|
| 4461 |
-
outputs=[
|
| 4462 |
api_name="edit_video",
|
| 4463 |
show_progress="minimal",
|
| 4464 |
)
|
|
@@ -4497,13 +4530,13 @@ def build_demo() -> gr.Blocks:
|
|
| 4497 |
image_steps = mcp_number("validation_num_timesteps", DEFAULT_TIMESTEPS)
|
| 4498 |
image_shift = mcp_number("validation_timestep_shift", DEFAULT_TIMESTEP_SHIFT)
|
| 4499 |
image_cfg = mcp_number("cfg_text_scale", DEFAULT_CFG_TEXT_SCALE)
|
| 4500 |
-
|
| 4501 |
image_status = mcp_text("status")
|
| 4502 |
image_button = gr.Button("MCP generate_image", visible=False)
|
| 4503 |
image_button.click(
|
| 4504 |
fn=mcp_generate_image,
|
| 4505 |
inputs=[image_prompt, image_aspect_ratio, image_seed, image_steps, image_shift, image_cfg],
|
| 4506 |
-
outputs=[
|
| 4507 |
api_name="generate_image",
|
| 4508 |
show_progress="minimal",
|
| 4509 |
)
|
|
@@ -4515,7 +4548,7 @@ def build_demo() -> gr.Blocks:
|
|
| 4515 |
image_edit_steps = mcp_number("validation_num_timesteps", DEFAULT_TIMESTEPS)
|
| 4516 |
image_edit_shift = mcp_number("validation_timestep_shift", DEFAULT_TIMESTEP_SHIFT)
|
| 4517 |
image_edit_cfg = mcp_number("cfg_text_scale", DEFAULT_CFG_TEXT_SCALE)
|
| 4518 |
-
|
| 4519 |
image_edit_status = mcp_text("status")
|
| 4520 |
image_edit_button = gr.Button("MCP edit_image", visible=False)
|
| 4521 |
image_edit_button.click(
|
|
@@ -4529,7 +4562,7 @@ def build_demo() -> gr.Blocks:
|
|
| 4529 |
image_edit_shift,
|
| 4530 |
image_edit_cfg,
|
| 4531 |
],
|
| 4532 |
-
outputs=[
|
| 4533 |
api_name="edit_image",
|
| 4534 |
show_progress="minimal",
|
| 4535 |
)
|
|
|
|
| 1800 |
return f"{API_PREFIX or ''}/file={quote(source, safe='/:')}"
|
| 1801 |
|
| 1802 |
|
| 1803 |
+
def get_public_app_base_url() -> str:
|
| 1804 |
+
"""Return the public base URL for absolute MCP media links when available."""
|
| 1805 |
+
configured = os.getenv("LANCE_PUBLIC_BASE_URL", "").strip()
|
| 1806 |
+
if configured:
|
| 1807 |
+
return configured.rstrip("/")
|
| 1808 |
+
|
| 1809 |
+
for env_name in ("SPACE_HOST", "HF_SPACE_HOST"):
|
| 1810 |
+
host = os.getenv(env_name, "").strip()
|
| 1811 |
+
if host:
|
| 1812 |
+
if host.startswith(("http://", "https://")):
|
| 1813 |
+
return host.rstrip("/")
|
| 1814 |
+
return f"https://{host.rstrip('/')}"
|
| 1815 |
+
|
| 1816 |
+
space_id = os.getenv("SPACE_ID", "").strip()
|
| 1817 |
+
if "/" in space_id:
|
| 1818 |
+
return f"https://{space_id.replace('/', '-').lower()}.hf.space"
|
| 1819 |
+
|
| 1820 |
+
return ""
|
| 1821 |
+
|
| 1822 |
+
|
| 1823 |
+
def build_public_gradio_media_url(media_path: Optional[str]) -> str:
|
| 1824 |
+
"""Build a client-readable Gradio file URL for MCP outputs."""
|
| 1825 |
+
media_url = build_gradio_media_url(media_path)
|
| 1826 |
+
if not media_url or _is_http_url(media_url):
|
| 1827 |
+
return media_url
|
| 1828 |
+
|
| 1829 |
+
base_url = get_public_app_base_url()
|
| 1830 |
+
if not base_url:
|
| 1831 |
+
return media_url
|
| 1832 |
+
return f"{base_url}{media_url if media_url.startswith('/') else '/' + media_url}"
|
| 1833 |
+
|
| 1834 |
+
|
| 1835 |
def _normalize_media_kind(media_kind: str) -> str:
|
| 1836 |
normalized = str(media_kind or "auto").strip().lower()
|
| 1837 |
if normalized in {"img", "image"}:
|
|
|
|
| 1975 |
|
| 1976 |
|
| 1977 |
def upload_file_to_gradio(file_url: str, media_type: str = "image") -> tuple[str, str]:
|
| 1978 |
+
"""Upload a remote image/video URL into this Gradio app and return a reusable local path plus a public Gradio file URL."""
|
| 1979 |
local_path = prepare_media_input(file_url, _normalize_media_kind(media_type), required=True)
|
| 1980 |
+
return local_path, build_public_gradio_media_url(local_path)
|
| 1981 |
|
| 1982 |
|
| 1983 |
def build_example_media_html(media_path: Optional[str], media_type: str, fallback_media_path: Optional[str] = None) -> str:
|
|
|
|
| 3922 |
output_video, output_image, _output_text, status = result
|
| 3923 |
output_path = output_video if output_kind == "video" else output_image
|
| 3924 |
if output_path:
|
| 3925 |
+
output_url = build_public_gradio_media_url(str(output_path))
|
| 3926 |
+
return output_url, status or f"Success. Local output path: {output_path}"
|
| 3927 |
return "", status or f"No output {output_kind} was produced."
|
| 3928 |
|
| 3929 |
|
|
|
|
| 3944 |
validation_timestep_shift: float = DEFAULT_TIMESTEP_SHIFT,
|
| 3945 |
cfg_text_scale: float = DEFAULT_CFG_TEXT_SCALE,
|
| 3946 |
) -> tuple[str, str]:
|
| 3947 |
+
"""Generate a video from a text prompt. Returns a public Gradio URL for the generated MP4 and a status message."""
|
| 3948 |
result = _run_mcp_task(
|
| 3949 |
task=TASK_T2V,
|
| 3950 |
prompt=prompt,
|
|
|
|
| 3973 |
validation_timestep_shift: float = DEFAULT_TIMESTEP_SHIFT,
|
| 3974 |
cfg_text_scale: float = DEFAULT_CFG_TEXT_SCALE,
|
| 3975 |
) -> tuple[str, str]:
|
| 3976 |
+
"""Edit an input video from a local path, Gradio file URL, or HTTP(S) URL. Returns a public Gradio URL for the edited MP4 and status."""
|
| 3977 |
result = _run_mcp_task(
|
| 3978 |
task=TASK_VIDEO_EDIT,
|
| 3979 |
prompt=prompt,
|
|
|
|
| 4027 |
validation_timestep_shift: float = DEFAULT_TIMESTEP_SHIFT,
|
| 4028 |
cfg_text_scale: float = DEFAULT_CFG_TEXT_SCALE,
|
| 4029 |
) -> tuple[str, str]:
|
| 4030 |
+
"""Generate an image from a text prompt. Returns a public Gradio URL for the generated image and a status message."""
|
| 4031 |
result = _run_mcp_task(
|
| 4032 |
task=TASK_T2I,
|
| 4033 |
prompt=prompt,
|
|
|
|
| 4054 |
validation_timestep_shift: float = DEFAULT_TIMESTEP_SHIFT,
|
| 4055 |
cfg_text_scale: float = DEFAULT_CFG_TEXT_SCALE,
|
| 4056 |
) -> tuple[str, str]:
|
| 4057 |
+
"""Edit an input image from a local path, Gradio file URL, or HTTP(S) URL. Returns a public Gradio URL for the edited image and status."""
|
| 4058 |
result = _run_mcp_task(
|
| 4059 |
task=TASK_IMAGE_EDIT,
|
| 4060 |
prompt=prompt,
|
|
|
|
| 4455 |
video_steps = mcp_number("validation_num_timesteps", DEFAULT_TIMESTEPS)
|
| 4456 |
video_shift = mcp_number("validation_timestep_shift", DEFAULT_TIMESTEP_SHIFT)
|
| 4457 |
video_cfg = mcp_number("cfg_text_scale", DEFAULT_CFG_TEXT_SCALE)
|
| 4458 |
+
video_output_url = mcp_text("output_video_url")
|
| 4459 |
video_status = mcp_text("status")
|
| 4460 |
video_button = gr.Button("MCP generate_video", visible=False)
|
| 4461 |
video_button.click(
|
| 4462 |
fn=mcp_generate_video,
|
| 4463 |
inputs=[video_prompt, video_resolution, video_aspect_ratio, video_duration, video_seed, video_steps, video_shift, video_cfg],
|
| 4464 |
+
outputs=[video_output_url, video_status],
|
| 4465 |
api_name="generate_video",
|
| 4466 |
show_progress="minimal",
|
| 4467 |
)
|
|
|
|
| 4475 |
video_edit_steps = mcp_number("validation_num_timesteps", DEFAULT_TIMESTEPS)
|
| 4476 |
video_edit_shift = mcp_number("validation_timestep_shift", DEFAULT_TIMESTEP_SHIFT)
|
| 4477 |
video_edit_cfg = mcp_number("cfg_text_scale", DEFAULT_CFG_TEXT_SCALE)
|
| 4478 |
+
video_edit_output_url = mcp_text("output_video_url")
|
| 4479 |
video_edit_status = mcp_text("status")
|
| 4480 |
video_edit_button = gr.Button("MCP edit_video", visible=False)
|
| 4481 |
video_edit_button.click(
|
|
|
|
| 4491 |
video_edit_shift,
|
| 4492 |
video_edit_cfg,
|
| 4493 |
],
|
| 4494 |
+
outputs=[video_edit_output_url, video_edit_status],
|
| 4495 |
api_name="edit_video",
|
| 4496 |
show_progress="minimal",
|
| 4497 |
)
|
|
|
|
| 4530 |
image_steps = mcp_number("validation_num_timesteps", DEFAULT_TIMESTEPS)
|
| 4531 |
image_shift = mcp_number("validation_timestep_shift", DEFAULT_TIMESTEP_SHIFT)
|
| 4532 |
image_cfg = mcp_number("cfg_text_scale", DEFAULT_CFG_TEXT_SCALE)
|
| 4533 |
+
image_output_url = mcp_text("output_image_url")
|
| 4534 |
image_status = mcp_text("status")
|
| 4535 |
image_button = gr.Button("MCP generate_image", visible=False)
|
| 4536 |
image_button.click(
|
| 4537 |
fn=mcp_generate_image,
|
| 4538 |
inputs=[image_prompt, image_aspect_ratio, image_seed, image_steps, image_shift, image_cfg],
|
| 4539 |
+
outputs=[image_output_url, image_status],
|
| 4540 |
api_name="generate_image",
|
| 4541 |
show_progress="minimal",
|
| 4542 |
)
|
|
|
|
| 4548 |
image_edit_steps = mcp_number("validation_num_timesteps", DEFAULT_TIMESTEPS)
|
| 4549 |
image_edit_shift = mcp_number("validation_timestep_shift", DEFAULT_TIMESTEP_SHIFT)
|
| 4550 |
image_edit_cfg = mcp_number("cfg_text_scale", DEFAULT_CFG_TEXT_SCALE)
|
| 4551 |
+
image_edit_output_url = mcp_text("output_image_url")
|
| 4552 |
image_edit_status = mcp_text("status")
|
| 4553 |
image_edit_button = gr.Button("MCP edit_image", visible=False)
|
| 4554 |
image_edit_button.click(
|
|
|
|
| 4562 |
image_edit_shift,
|
| 4563 |
image_edit_cfg,
|
| 4564 |
],
|
| 4565 |
+
outputs=[image_edit_output_url, image_edit_status],
|
| 4566 |
api_name="edit_image",
|
| 4567 |
show_progress="minimal",
|
| 4568 |
)
|