mirror of
https://github.com/gradio-app/gradio.git
synced 2025-03-25 12:10:31 +08:00
implement autoplay for Video and Audio (#4453)
This commit is contained in:
parent
6888e30e79
commit
3d334e245f
@ -3,6 +3,7 @@
|
||||
## New Features:
|
||||
|
||||
- Add `start_recording` and `stop_recording` events to `Video` and `Audio` components by [@pngwn](https://github.com/pngwn) in [PR 4422](https://github.com/gradio-app/gradio/pull/4422)
|
||||
- Add `autoplay` kwarg to `Video` and `Audio` components by [@pngwn](https://github.com/pngwn) in [PR 4453](https://github.com/gradio-app/gradio/pull/4453)
|
||||
|
||||
## Bug Fixes:
|
||||
|
||||
|
@ -2172,6 +2172,7 @@ class Video(
|
||||
elem_classes: list[str] | str | None = None,
|
||||
mirror_webcam: bool = True,
|
||||
include_audio: bool | None = None,
|
||||
autoplay: bool = False,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
@ -2195,6 +2196,7 @@ class Video(
|
||||
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.
|
||||
"""
|
||||
self.format = format
|
||||
self.autoplay = autoplay
|
||||
valid_sources = ["upload", "webcam"]
|
||||
if source not in valid_sources:
|
||||
raise ValueError(
|
||||
@ -2231,6 +2233,7 @@ class Video(
|
||||
"width": self.width,
|
||||
"mirror_webcam": self.mirror_webcam,
|
||||
"include_audio": self.include_audio,
|
||||
"autoplay": self.autoplay,
|
||||
**IOComponent.get_config(self),
|
||||
}
|
||||
|
||||
@ -2250,6 +2253,7 @@ class Video(
|
||||
min_width: int | None = None,
|
||||
interactive: bool | None = None,
|
||||
visible: bool | None = None,
|
||||
autoplay: bool | None = None,
|
||||
):
|
||||
return {
|
||||
"source": source,
|
||||
@ -2263,6 +2267,7 @@ class Video(
|
||||
"interactive": interactive,
|
||||
"visible": visible,
|
||||
"value": value,
|
||||
"autoplay": autoplay,
|
||||
"__type__": "update",
|
||||
}
|
||||
|
||||
@ -2518,6 +2523,7 @@ class Audio(
|
||||
elem_id: str | None = None,
|
||||
elem_classes: list[str] | str | None = None,
|
||||
format: Literal["wav", "mp3"] = "wav",
|
||||
autoplay: bool = False,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
@ -2572,12 +2578,14 @@ class Audio(
|
||||
)
|
||||
TokenInterpretable.__init__(self)
|
||||
self.format = format
|
||||
self.autoplay = autoplay
|
||||
|
||||
def get_config(self):
|
||||
return {
|
||||
"source": self.source,
|
||||
"value": self.value,
|
||||
"streaming": self.streaming,
|
||||
"autoplay": self.autoplay,
|
||||
**IOComponent.get_config(self),
|
||||
}
|
||||
|
||||
@ -2598,6 +2606,7 @@ class Audio(
|
||||
min_width: int | None = None,
|
||||
interactive: bool | None = None,
|
||||
visible: bool | None = None,
|
||||
autoplay: bool | None = None,
|
||||
):
|
||||
return {
|
||||
"source": source,
|
||||
@ -2609,6 +2618,7 @@ class Audio(
|
||||
"interactive": interactive,
|
||||
"visible": visible,
|
||||
"value": value,
|
||||
"autoplay": autoplay,
|
||||
"__type__": "update",
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
if (!files) return;
|
||||
const _files = Array.from(files);
|
||||
request_data[i] = files.length === 1 ? _files[0] : _files;
|
||||
console.log(request_data);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
export let scale: number = 1;
|
||||
export let min_width: number | undefined = undefined;
|
||||
export let loading_status: LoadingStatus;
|
||||
export let autoplay: boolean = false;
|
||||
|
||||
let _value: null | FileData;
|
||||
$: _value = normalise_file(value, root, root_url);
|
||||
@ -75,6 +76,7 @@
|
||||
{source}
|
||||
{pending}
|
||||
{streaming}
|
||||
{autoplay}
|
||||
on:edit
|
||||
on:play
|
||||
on:pause
|
||||
@ -93,6 +95,7 @@
|
||||
</Audio>
|
||||
{:else}
|
||||
<StaticAudio
|
||||
{autoplay}
|
||||
{show_label}
|
||||
value={_value}
|
||||
name={_value?.name || "audio_file"}
|
||||
|
@ -30,6 +30,8 @@
|
||||
export let scale: number = 1;
|
||||
export let min_width: number | undefined = undefined;
|
||||
export let mode: "static" | "dynamic";
|
||||
export let autoplay: boolean = false;
|
||||
|
||||
let _video: FileData | null = null;
|
||||
let _subtitle: FileData | null = null;
|
||||
|
||||
@ -91,6 +93,7 @@
|
||||
subtitle={_subtitle}
|
||||
{label}
|
||||
{show_label}
|
||||
{autoplay}
|
||||
on:play
|
||||
on:pause
|
||||
on:stop
|
||||
@ -111,6 +114,7 @@
|
||||
{source}
|
||||
{mirror_webcam}
|
||||
{include_audio}
|
||||
{autoplay}
|
||||
on:clear
|
||||
on:play
|
||||
on:pause
|
||||
|
@ -24,6 +24,7 @@
|
||||
export let source: "microphone" | "upload" | "none";
|
||||
export let pending: boolean = false;
|
||||
export let streaming: boolean = false;
|
||||
export let autoplay: boolean;
|
||||
|
||||
// TODO: make use of this
|
||||
// export let type: "normal" | "numpy" = "normal";
|
||||
@ -34,7 +35,7 @@
|
||||
let header: Uint8Array | undefined = undefined;
|
||||
let pending_stream: Array<Uint8Array> = [];
|
||||
let submit_pending_stream_on_pending_end: boolean = false;
|
||||
let player;
|
||||
let player: HTMLAudioElement;
|
||||
let inited = false;
|
||||
let crop_values = [0, 100];
|
||||
const STREAM_TIMESLICE = 500;
|
||||
@ -259,8 +260,18 @@
|
||||
dispatch("end");
|
||||
}
|
||||
|
||||
let old_val: any;
|
||||
function value_has_changed(val: any) {
|
||||
if (val === old_val) return false;
|
||||
else {
|
||||
old_val = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export let dragging = false;
|
||||
$: dispatch("drag", dragging);
|
||||
$: autoplay && player && value_has_changed(value?.data) && player.play();
|
||||
</script>
|
||||
|
||||
<BlockLabel
|
||||
|
@ -17,6 +17,7 @@
|
||||
export let label: string;
|
||||
export let name: string;
|
||||
export let show_label: boolean = true;
|
||||
export let autoplay: boolean;
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
change: AudioData;
|
||||
@ -32,6 +33,19 @@
|
||||
data: value?.data
|
||||
});
|
||||
|
||||
let el: HTMLAudioElement;
|
||||
|
||||
let old_val: any;
|
||||
function value_has_changed(val: any) {
|
||||
if (val === old_val) return false;
|
||||
else {
|
||||
old_val = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$: autoplay && el && value_has_changed(value) && el.play();
|
||||
|
||||
function handle_ended() {
|
||||
dispatch("stop");
|
||||
dispatch("end");
|
||||
@ -45,6 +59,7 @@
|
||||
</Empty>
|
||||
{:else}
|
||||
<audio
|
||||
bind:this={el}
|
||||
controls
|
||||
preload="metadata"
|
||||
src={value.data}
|
||||
|
@ -5,6 +5,7 @@
|
||||
export let src: string;
|
||||
export let subtitle: string | null = null;
|
||||
export let mirror: boolean;
|
||||
export let autoplay: boolean;
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
play: undefined;
|
||||
@ -18,15 +19,6 @@
|
||||
let paused: boolean = true;
|
||||
let video: HTMLVideoElement;
|
||||
|
||||
let show_controls = true;
|
||||
let show_controls_timeout: NodeJS.Timeout;
|
||||
|
||||
function video_move() {
|
||||
clearTimeout(show_controls_timeout);
|
||||
show_controls_timeout = setTimeout(() => (show_controls = false), 500);
|
||||
show_controls = true;
|
||||
}
|
||||
|
||||
function handleMove(e: TouchEvent | MouseEvent) {
|
||||
if (!duration) return;
|
||||
|
||||
@ -79,22 +71,17 @@
|
||||
}
|
||||
|
||||
async function checkforVideo() {
|
||||
transition = "0s";
|
||||
await tick();
|
||||
wrap_opacity = 0.8;
|
||||
opacity = 0;
|
||||
|
||||
await tick();
|
||||
|
||||
var b = setInterval(async () => {
|
||||
if (video.readyState >= 3) {
|
||||
video.currentTime = 9999;
|
||||
paused = true;
|
||||
transition = "0.2s";
|
||||
|
||||
setTimeout(async () => {
|
||||
video.currentTime = 0.0;
|
||||
opacity = 1;
|
||||
wrap_opacity = 1;
|
||||
}, 50);
|
||||
clearInterval(b);
|
||||
}
|
||||
@ -105,23 +92,20 @@
|
||||
checkforVideo();
|
||||
}
|
||||
|
||||
let opacity: number = 0;
|
||||
let wrap_opacity: number = 0;
|
||||
let transition: string = "0.5s";
|
||||
|
||||
$: src && _load();
|
||||
|
||||
function handle_end() {
|
||||
dispatch("stop");
|
||||
dispatch("end");
|
||||
}
|
||||
|
||||
$: autoplay && video && src && video.play();
|
||||
</script>
|
||||
|
||||
<div class="wrap">
|
||||
<video
|
||||
{src}
|
||||
preload="auto"
|
||||
on:mousemove={video_move}
|
||||
on:click={play_pause}
|
||||
on:play
|
||||
on:pause
|
||||
|
@ -10,6 +10,8 @@
|
||||
export let subtitle: FileData | null = null;
|
||||
export let label: string | undefined = undefined;
|
||||
export let show_label: boolean = true;
|
||||
export let autoplay: boolean;
|
||||
|
||||
let old_value: FileData | null = null;
|
||||
let old_subtitle: FileData | null = null;
|
||||
|
||||
@ -49,6 +51,7 @@
|
||||
<Player
|
||||
src={value.data}
|
||||
subtitle={subtitle?.data}
|
||||
{autoplay}
|
||||
on:play
|
||||
on:pause
|
||||
on:ended
|
||||
|
@ -16,6 +16,7 @@
|
||||
export let show_label: boolean = true;
|
||||
export let mirror_webcam: boolean = false;
|
||||
export let include_audio: boolean;
|
||||
export let autoplay: boolean;
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
change: any;
|
||||
@ -68,6 +69,7 @@
|
||||
{#if playable()}
|
||||
<!-- svelte-ignore a11y-media-has-caption -->
|
||||
<Player
|
||||
{autoplay}
|
||||
src={value.data}
|
||||
subtitle={subtitle?.data}
|
||||
on:play
|
||||
|
@ -1154,6 +1154,7 @@ class TestSpecificUpdate:
|
||||
}
|
||||
)
|
||||
assert specific_update == {
|
||||
"autoplay": None,
|
||||
"source": None,
|
||||
"label": None,
|
||||
"show_label": None,
|
||||
|
@ -822,6 +822,7 @@ class TestAudio:
|
||||
|
||||
audio_input = gr.Audio(label="Upload Your Audio")
|
||||
assert audio_input.get_config() == {
|
||||
"autoplay": False,
|
||||
"source": "upload",
|
||||
"name": "audio",
|
||||
"streaming": False,
|
||||
@ -856,6 +857,7 @@ class TestAudio:
|
||||
audio_output = gr.Audio(type="filepath")
|
||||
assert filecmp.cmp(y_audio.name, audio_output.postprocess(y_audio.name)["name"])
|
||||
assert audio_output.get_config() == {
|
||||
"autoplay": False,
|
||||
"name": "audio",
|
||||
"streaming": False,
|
||||
"show_label": True,
|
||||
@ -1306,6 +1308,7 @@ class TestVideo:
|
||||
|
||||
video_input = gr.Video(label="Upload Your Video")
|
||||
assert video_input.get_config() == {
|
||||
"autoplay": False,
|
||||
"source": "upload",
|
||||
"name": "video",
|
||||
"show_label": True,
|
||||
|
Loading…
x
Reference in New Issue
Block a user