mirror of
https://github.com/gradio-app/gradio.git
synced 2025-04-12 12:40:29 +08:00
Allow download button for interactive Audio and Video components (#7104)
* allow download button for interactive audio and video components * add changeset * document show_download_button in video.py * ensure show_download_button is by default true for output and false for input components * fix component test * tweak default val * val tweak * fix test and add story * pass editable param where needed * fix another test --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: Dawood Khan <dawoodkhan82@gmail.com>
This commit is contained in:
parent
c35fac049a
commit
bc2cdc1df9
8
.changeset/hot-forks-report.md
Normal file
8
.changeset/hot-forks-report.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
"@gradio/audio": minor
|
||||
"@gradio/upload": minor
|
||||
"@gradio/video": minor
|
||||
"gradio": minor
|
||||
---
|
||||
|
||||
feat:Allow download button for interactive Audio and Video components
|
@ -92,7 +92,7 @@ class Audio(
|
||||
render: bool = True,
|
||||
format: Literal["wav", "mp3"] = "wav",
|
||||
autoplay: bool = False,
|
||||
show_download_button=True,
|
||||
show_download_button: bool | None = None,
|
||||
show_share_button: bool | None = None,
|
||||
editable: bool = True,
|
||||
min_length: int | None = None,
|
||||
@ -118,9 +118,9 @@ class Audio(
|
||||
render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
|
||||
format: The file format to save audio files. Either 'wav' or 'mp3'. wav files are lossless but will tend to be larger files. mp3 files tend to be smaller. Default is wav. Applies both when this component is used as an input (when `type` is "format") and when this component is used as an output.
|
||||
autoplay: Whether to automatically play the audio when the component is used as an output. Note: browsers will not autoplay audio files if the user has not interacted with the page yet.
|
||||
show_download_button: If True, will show a download button in the corner of the component for saving audio. If False, icon does not appear.
|
||||
show_download_button: If True, will show a download button in the corner of the component for saving audio. If False, icon does not appear. By default, it will be True for output components and False for input components.
|
||||
show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.
|
||||
editable: If True, allows users to manipulate the audio file (if the component is interactive).
|
||||
editable: If True, allows users to manipulate the audio file if the component is interactive. Defaults to True.
|
||||
min_length: The minimum length of audio (in seconds) that the user can pass into the prediction function. If None, there is no minimum length.
|
||||
max_length: The maximum length of audio (in seconds) that the user can pass into the prediction function. If None, there is no maximum length.
|
||||
waveform_options: A dictionary of options for the waveform display. Options include: waveform_color (str), waveform_progress_color (str), show_controls (bool), skip_length (int). Default is None, which uses the default values for these options.
|
||||
|
@ -83,6 +83,7 @@ class Video(Component):
|
||||
include_audio: bool | None = None,
|
||||
autoplay: bool = False,
|
||||
show_share_button: bool | None = None,
|
||||
show_download_button: bool | None = None,
|
||||
min_length: int | None = None,
|
||||
max_length: int | None = None,
|
||||
):
|
||||
@ -108,6 +109,7 @@ class Video(Component):
|
||||
include_audio: Whether the component should record/retain the audio track for a video. By default, audio is excluded for webcam videos and included for uploaded videos.
|
||||
autoplay: Whether to automatically play the video when the component is used as an output. Note: browsers will not autoplay video files if the user has not interacted with the page yet.
|
||||
show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.
|
||||
show_download_button: If True, will show a download icon in the corner of the component that allows user to download the output. If False, icon does not appear. By default, it will be True for output components and False for input components.
|
||||
min_length: The minimum length of video (in seconds) that the user can pass into the prediction function. If None, there is no minimum length.
|
||||
max_length: The maximum length of video (in seconds) that the user can pass into the prediction function. If None, there is no maximum length.
|
||||
"""
|
||||
@ -140,6 +142,7 @@ class Video(Component):
|
||||
if show_share_button is None
|
||||
else show_share_button
|
||||
)
|
||||
self.show_download_button = show_download_button
|
||||
self.min_length = min_length
|
||||
self.max_length = max_length
|
||||
super().__init__(
|
||||
|
@ -31,6 +31,35 @@
|
||||
}}
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="Audio Recorder with download button"
|
||||
args={{
|
||||
value: {
|
||||
path: "https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3",
|
||||
url: "https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3",
|
||||
orig_name: "sample-0.mp3"
|
||||
},
|
||||
interactive: true,
|
||||
show_download_button: true,
|
||||
sources: ["microphone"],
|
||||
label: "Audio Recorder"
|
||||
}}
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="output with hidden download button"
|
||||
args={{
|
||||
value: {
|
||||
path: "https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3",
|
||||
url: "https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3",
|
||||
orig_name: "sample-0.mp3"
|
||||
},
|
||||
interactive: false,
|
||||
show_download_button: false,
|
||||
label: "Audio Recorder"
|
||||
}}
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="Upload Audio"
|
||||
args={{
|
||||
@ -57,7 +86,7 @@
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="with disabled editing"
|
||||
name="upload with disabled editing"
|
||||
args={{
|
||||
value: {
|
||||
path: "https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3",
|
||||
|
@ -32,7 +32,7 @@
|
||||
export let min_width: number | undefined = undefined;
|
||||
export let loading_status: LoadingStatus;
|
||||
export let autoplay = false;
|
||||
export let show_download_button = true;
|
||||
export let show_download_button: boolean;
|
||||
export let show_share_button = false;
|
||||
export let editable = true;
|
||||
export let waveform_options: WaveformOptions = {};
|
||||
@ -152,6 +152,7 @@
|
||||
{label}
|
||||
{waveform_settings}
|
||||
{waveform_options}
|
||||
{editable}
|
||||
on:share={(e) => gradio.dispatch("share", e.detail)}
|
||||
on:error={(e) => gradio.dispatch("error", e.detail)}
|
||||
on:play={() => gradio.dispatch("play")}
|
||||
@ -179,6 +180,7 @@
|
||||
<InteractiveAudio
|
||||
{label}
|
||||
{show_label}
|
||||
{show_download_button}
|
||||
value={_value}
|
||||
on:change={({ detail }) => (value = detail)}
|
||||
on:stream={({ detail }) => {
|
||||
|
@ -22,6 +22,7 @@
|
||||
export let label: string;
|
||||
export let root: string;
|
||||
export let show_label = true;
|
||||
export let show_download_button = false;
|
||||
export let sources:
|
||||
| ["microphone"]
|
||||
| ["upload"]
|
||||
@ -235,6 +236,7 @@
|
||||
<AudioRecorder
|
||||
bind:mode
|
||||
{i18n}
|
||||
{editable}
|
||||
{dispatch_blob}
|
||||
{waveform_settings}
|
||||
{waveform_options}
|
||||
@ -258,6 +260,7 @@
|
||||
{i18n}
|
||||
on:clear={clear}
|
||||
on:edit={() => (mode = "edit")}
|
||||
download={show_download_button ? value.url : null}
|
||||
absolute={true}
|
||||
/>
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
show_recording_waveform: true
|
||||
};
|
||||
export let handle_reset_value: () => void;
|
||||
export let editable = true;
|
||||
|
||||
let micWaveform: WaveSurfer;
|
||||
let recordingWaveform: WaveSurfer;
|
||||
@ -238,6 +239,7 @@
|
||||
{playing}
|
||||
{audio_duration}
|
||||
{i18n}
|
||||
{editable}
|
||||
interactive={true}
|
||||
{handle_trim_audio}
|
||||
bind:trimDuration
|
||||
|
@ -18,6 +18,7 @@
|
||||
export let i18n: I18nFormatter;
|
||||
export let waveform_settings: Record<string, any>;
|
||||
export let waveform_options: WaveformOptions;
|
||||
export let editable = true;
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
change: FileData;
|
||||
@ -65,6 +66,7 @@
|
||||
{i18n}
|
||||
{waveform_settings}
|
||||
{waveform_options}
|
||||
{editable}
|
||||
on:pause
|
||||
on:play
|
||||
on:stop
|
||||
|
@ -11,7 +11,8 @@
|
||||
"@gradio/icons": "workspace:^",
|
||||
"@gradio/client": "workspace:^",
|
||||
"@gradio/upload": "workspace:^",
|
||||
"@gradio/utils": "workspace:^"
|
||||
"@gradio/utils": "workspace:^",
|
||||
"@gradio/wasm": "workspace:^"
|
||||
},
|
||||
"main_changeset": true,
|
||||
"exports": {
|
||||
|
@ -1,12 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { IconButton } from "@gradio/atoms";
|
||||
import type { I18nFormatter } from "@gradio/utils";
|
||||
import { Edit, Clear, Undo } from "@gradio/icons";
|
||||
import { Edit, Clear, Undo, Download } from "@gradio/icons";
|
||||
import { DownloadLink } from "@gradio/wasm/svelte";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
export let editable = false;
|
||||
export let undoable = false;
|
||||
export let download: string | null = null;
|
||||
export let absolute = true;
|
||||
export let i18n: I18nFormatter;
|
||||
|
||||
@ -37,6 +39,12 @@
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if download}
|
||||
<DownloadLink href={download} download>
|
||||
<IconButton Icon={Download} label={i18n("common.download")} />
|
||||
</DownloadLink>
|
||||
{/if}
|
||||
|
||||
<IconButton
|
||||
Icon={Clear}
|
||||
label={i18n("common.clear")}
|
||||
|
@ -35,6 +35,7 @@
|
||||
export let min_width: number | undefined = undefined;
|
||||
export let autoplay = false;
|
||||
export let show_share_button = true;
|
||||
export let show_download_button: boolean;
|
||||
export let gradio: Gradio<{
|
||||
change: never;
|
||||
clear: never;
|
||||
@ -146,7 +147,7 @@
|
||||
{show_label}
|
||||
{autoplay}
|
||||
{show_share_button}
|
||||
show_download_button={true}
|
||||
{show_download_button}
|
||||
on:play={() => gradio.dispatch("play")}
|
||||
on:pause={() => gradio.dispatch("pause")}
|
||||
on:stop={() => gradio.dispatch("stop")}
|
||||
@ -185,6 +186,7 @@
|
||||
on:error={handle_error}
|
||||
{label}
|
||||
{show_label}
|
||||
{show_download_button}
|
||||
{sources}
|
||||
{active_source}
|
||||
{mirror_webcam}
|
||||
|
@ -38,6 +38,7 @@
|
||||
},
|
||||
label: "world video",
|
||||
show_label: true,
|
||||
show_download_button: true,
|
||||
interactive: false,
|
||||
height: 200,
|
||||
width: 400
|
||||
@ -55,6 +56,7 @@
|
||||
},
|
||||
label: "world video",
|
||||
show_label: true,
|
||||
show_download_button: false,
|
||||
interactive: false,
|
||||
height: 200,
|
||||
width: 400
|
||||
@ -74,6 +76,26 @@
|
||||
}}
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="Upload video with download button"
|
||||
args={{
|
||||
label: "world video",
|
||||
show_label: true,
|
||||
interactive: true,
|
||||
sources: ["upload", "webcam"],
|
||||
show_download_button: true,
|
||||
width: 400,
|
||||
height: 400,
|
||||
value: {
|
||||
video: {
|
||||
path: "https://gradio-static-files.s3.us-west-2.amazonaws.com/world.mp4",
|
||||
url: "https://gradio-static-files.s3.us-west-2.amazonaws.com/world.mp4",
|
||||
orig_name: "world.mp4"
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="Trim video"
|
||||
args={{
|
||||
|
@ -19,6 +19,7 @@
|
||||
| ["webcam", "upload"]
|
||||
| ["upload", "webcam"] = ["webcam", "upload"];
|
||||
export let label: string | undefined = undefined;
|
||||
export let show_download_button = false;
|
||||
export let show_label = true;
|
||||
export let mirror_webcam = false;
|
||||
export let include_audio: boolean;
|
||||
@ -96,7 +97,11 @@
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<ModifyUpload {i18n} on:clear={handle_clear} />
|
||||
<ModifyUpload
|
||||
{i18n}
|
||||
on:clear={handle_clear}
|
||||
download={show_download_button ? value.url : null}
|
||||
/>
|
||||
{#if playable()}
|
||||
{#key value?.url}
|
||||
<Player
|
||||
|
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@ -1461,6 +1461,9 @@ importers:
|
||||
'@gradio/utils':
|
||||
specifier: workspace:^
|
||||
version: link:../utils
|
||||
'@gradio/wasm':
|
||||
specifier: workspace:^
|
||||
version: link:../wasm
|
||||
|
||||
js/uploadbutton:
|
||||
dependencies:
|
||||
|
@ -816,7 +816,7 @@ class TestAudio:
|
||||
"autoplay": False,
|
||||
"sources": ["upload", "microphone"],
|
||||
"name": "audio",
|
||||
"show_download_button": True,
|
||||
"show_download_button": None,
|
||||
"show_share_button": False,
|
||||
"streaming": False,
|
||||
"show_label": True,
|
||||
@ -867,7 +867,7 @@ class TestAudio:
|
||||
assert audio_output.get_config() == {
|
||||
"autoplay": False,
|
||||
"name": "audio",
|
||||
"show_download_button": True,
|
||||
"show_download_button": None,
|
||||
"show_share_button": False,
|
||||
"streaming": False,
|
||||
"show_label": True,
|
||||
@ -1483,6 +1483,7 @@ class TestVideo:
|
||||
"container": True,
|
||||
"min_width": 160,
|
||||
"scale": None,
|
||||
"show_download_button": None,
|
||||
"height": None,
|
||||
"width": None,
|
||||
"elem_id": None,
|
||||
|
Loading…
x
Reference in New Issue
Block a user