2
0
mirror of https://github.com/gradio-app/gradio.git synced 2025-03-31 12:20:26 +08:00

Ensure Audio ouput events are dispatched ()

* ensure ouput events are dispatched

* add changeset

* add output events to e2e tests and remove unknown end event

* Amend audio events e2e test

* add changeset

* remove redundant test

* gen notebook

* tweak test name

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Hannah 2023-11-16 21:55:25 +01:00 committed by GitHub
parent a1e3c61f41
commit 2777f326e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 96 additions and 28 deletions

@ -0,0 +1,6 @@
---
"@gradio/audio": patch
"gradio": patch
---
fix:Ensure Audio ouput events are dispatched

@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: audio_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " input_video = gr.Audio(type=\"filepath\", label=\"Input Audio\", sources=[\"upload\", \"microphone\"])\n", " with gr.Column():\n", " output_video = gr.Audio(label=\"Output Audio\", sources=[\"upload\", \"microphone\"])\n", " with gr.Column():\n", " num_change = gr.Number(label=\"# Change Events\", value=0)\n", " num_load = gr.Number(label=\"# Upload Events\", value=0)\n", " num_play = gr.Number(label=\"# Play Events\", value=0)\n", " num_pause = gr.Number(label=\"# Pause Events\", value=0)\n", " input_video.upload(lambda s, n: (s, n + 1), [input_video, num_load], [output_video, num_load])\n", " input_video.change(lambda n: n + 1, num_change, num_change)\n", " input_video.play(lambda n: n + 1, num_play, num_play)\n", " input_video.pause(lambda n: n + 1, num_pause, num_pause)\n", " input_video.change(lambda n: n + 1, num_change, num_change)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: audio_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " input_video = gr.Audio(type=\"filepath\", label=\"Input Audio\", sources=[\"upload\", \"microphone\"])\n", " with gr.Column():\n", " output_video = gr.Audio(label=\"Output Audio\", sources=[\"upload\", \"microphone\"])\n", "\n", " with gr.Row():\n", " with gr.Column():\n", " input_num_change = gr.Number(label=\"# Input Change Events\", value=0)\n", " input_num_load = gr.Number(label=\"# Input Upload Events\", value=0)\n", " input_num_play = gr.Number(label=\"# Input Play Events\", value=0)\n", " input_num_pause = gr.Number(label=\"# Input Pause Events\", value=0)\n", "\n", " with gr.Column():\n", " output_num_play = gr.Number(label=\"# Output Play Events\", value=0)\n", " output_num_pause = gr.Number(label=\"# Output Pause Events\", value=0)\n", " output_num_stop = gr.Number(label=\"# Output Stop Events\", value=0)\n", "\n", " input_video.upload(lambda s, n: (s, n + 1), [input_video, input_num_load], [output_video, input_num_load])\n", " input_video.change(lambda n: n + 1, input_num_change, input_num_change)\n", " input_video.play(lambda n: n + 1, input_num_play, input_num_play)\n", " input_video.pause(lambda n: n + 1, input_num_pause, input_num_pause)\n", " input_video.change(lambda n: n + 1, input_num_change, input_num_change)\n", "\n", " output_video.play(lambda n: n + 1, output_num_play, output_num_play)\n", " output_video.pause(lambda n: n + 1, output_num_pause, output_num_pause)\n", " output_video.stop(lambda n: n + 1, output_num_stop, output_num_stop)\n", "\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}

@ -6,16 +6,30 @@ with gr.Blocks() as demo:
input_video = gr.Audio(type="filepath", label="Input Audio", sources=["upload", "microphone"])
with gr.Column():
output_video = gr.Audio(label="Output Audio", sources=["upload", "microphone"])
with gr.Row():
with gr.Column():
num_change = gr.Number(label="# Change Events", value=0)
num_load = gr.Number(label="# Upload Events", value=0)
num_play = gr.Number(label="# Play Events", value=0)
num_pause = gr.Number(label="# Pause Events", value=0)
input_video.upload(lambda s, n: (s, n + 1), [input_video, num_load], [output_video, num_load])
input_video.change(lambda n: n + 1, num_change, num_change)
input_video.play(lambda n: n + 1, num_play, num_play)
input_video.pause(lambda n: n + 1, num_pause, num_pause)
input_video.change(lambda n: n + 1, num_change, num_change)
input_num_change = gr.Number(label="# Input Change Events", value=0)
input_num_load = gr.Number(label="# Input Upload Events", value=0)
input_num_play = gr.Number(label="# Input Play Events", value=0)
input_num_pause = gr.Number(label="# Input Pause Events", value=0)
with gr.Column():
output_num_play = gr.Number(label="# Output Play Events", value=0)
output_num_pause = gr.Number(label="# Output Pause Events", value=0)
output_num_stop = gr.Number(label="# Output Stop Events", value=0)
input_video.upload(lambda s, n: (s, n + 1), [input_video, input_num_load], [output_video, input_num_load])
input_video.change(lambda n: n + 1, input_num_change, input_num_change)
input_video.play(lambda n: n + 1, input_num_play, input_num_play)
input_video.pause(lambda n: n + 1, input_num_pause, input_num_pause)
input_video.change(lambda n: n + 1, input_num_change, input_num_change)
output_video.play(lambda n: n + 1, output_num_play, output_num_play)
output_video.pause(lambda n: n + 1, output_num_pause, output_num_pause)
output_video.stop(lambda n: n + 1, output_num_stop, output_num_stop)
if __name__ == "__main__":
demo.launch()

@ -12,11 +12,11 @@ test("Audio click-to-upload uploads audio successfuly. File downloading works an
page.waitForResponse("**/upload?*")
]);
await expect(page.getByLabel("# Change Events")).toHaveValue("1");
await expect(page.getByLabel("# Upload Events")).toHaveValue("1");
await expect(page.getByLabel("# Input Change Events")).toHaveValue("1");
await expect(page.getByLabel("# Input Upload Events")).toHaveValue("1");
await page.getByLabel("Clear").click();
await expect(page.getByLabel("# Change Events")).toHaveValue("2");
await expect(page.getByLabel("# Input Change Events")).toHaveValue("2");
await page
.getByRole("button", { name: "Drop Audio Here - or - Click to Upload" })
.click();
@ -26,8 +26,8 @@ test("Audio click-to-upload uploads audio successfuly. File downloading works an
page.waitForResponse("**/upload?*")
]);
await expect(page.getByLabel("# Change Events")).toHaveValue("3");
await expect(page.getByLabel("# Upload Events")).toHaveValue("2");
await expect(page.getByLabel("# Input Change Events")).toHaveValue("3");
await expect(page.getByLabel("# Input Upload Events")).toHaveValue("2");
const downloadPromise = page.waitForEvent("download");
await page.getByLabel("Download").click();
@ -48,8 +48,8 @@ test("Audio drag-and-drop uploads a file to the server correctly.", async ({
),
page.waitForResponse("**/upload?*")
]);
await expect(page.getByLabel("# Change Events")).toHaveValue("1");
await expect(page.getByLabel("# Upload Events")).toHaveValue("1");
await expect(page.getByLabel("# Input Change Events")).toHaveValue("1");
await expect(page.getByLabel("# Input Upload Events")).toHaveValue("1");
});
test("Audio drag-and-drop displays a warning when the file is of the wrong mime type.", async ({
@ -64,3 +64,25 @@ test("Audio drag-and-drop displays a warning when the file is of the wrong mime
const toast = page.getByTestId("toast-body");
expect(toast).toContainText("warning");
});
test("Play, Pause, and stop events work correctly.", async ({ page }) => {
const uploader = await page.locator("input[type=file]");
await Promise.all([
uploader.setInputFiles(["../../test/test_files/audio_sample.wav"]),
page.waitForResponse("**/upload?*")
]);
await page
.getByTestId("waveform-Output Audio")
.getByLabel("Play", { exact: true })
.click();
await page.getByTestId("waveform-Output Audio").getByLabel("Pause").click();
await page
.getByTestId("waveform-Output Audio")
.getByLabel("Play", { exact: true })
.click();
await expect(page.getByLabel("# Output Play Events")).toHaveValue("1");
await expect(page.getByLabel("# Output Pause Events")).toHaveValue("1");
await expect(page.getByLabel("# Output Stop Events")).toHaveValue("1");
});

@ -150,6 +150,9 @@
{waveform_options}
on:share={(e) => gradio.dispatch("share", e.detail)}
on:error={(e) => gradio.dispatch("error", e.detail)}
on:play={() => gradio.dispatch("play")}
on:pause={() => gradio.dispatch("pause")}
on:stop={() => gradio.dispatch("stop")}
/>
</Block>
{:else}
@ -190,7 +193,6 @@
on:play={() => gradio.dispatch("play")}
on:pause={() => gradio.dispatch("pause")}
on:stop={() => gradio.dispatch("stop")}
on:end={() => gradio.dispatch("end")}
on:start_recording={() => gradio.dispatch("start_recording")}
on:pause_recording={() => gradio.dispatch("pause_recording")}
on:stop_recording={(e) => gradio.dispatch("stop_recording", e.detail)}

@ -215,7 +215,6 @@
<AudioRecorder
bind:mode
{i18n}
{dispatch}
{dispatch_blob}
{waveform_settings}
{waveform_options}
@ -248,13 +247,16 @@
{value}
{label}
{i18n}
{dispatch}
{dispatch_blob}
{waveform_settings}
{waveform_options}
{trim_region_settings}
{handle_reset_value}
interactive
on:stop
on:play
on:pause
on:edit
/>
{/if}

@ -9,12 +9,12 @@
import { resolve_wasm_src } from "@gradio/wasm/svelte";
import type { FileData } from "@gradio/client";
import type { WaveformOptions } from "../shared/types";
import { createEventDispatcher } from "svelte";
export let value: null | FileData = null;
$: url = value?.url;
export let label: string;
export let i18n: I18nFormatter;
export let dispatch: (event: any, detail?: any) => void;
export let dispatch_blob: (
blobs: Uint8Array[] | Blob[],
event: "stream" | "change" | "stop_recording"
@ -38,6 +38,14 @@
let show_volume_slider = false;
const dispatch = createEventDispatcher<{
stop: undefined;
play: undefined;
pause: undefined;
edit: undefined;
end: undefined;
}>();
const formatTime = (seconds: number): string => {
const minutes = Math.floor(seconds / 60);
const secondsRemainder = Math.round(seconds) % 60;
@ -78,7 +86,6 @@
$: waveform?.on("finish", () => {
playing = false;
dispatch("stop");
dispatch("end");
});
$: waveform?.on("pause", () => {
playing = false;

@ -1,6 +1,7 @@
<script lang="ts">
import { onMount } from "svelte";
import type { I18nFormatter } from "@gradio/utils";
import { createEventDispatcher } from "svelte";
import WaveSurfer from "wavesurfer.js";
import { skipAudio, process_audio } from "../shared/utils";
import WSRecord from "wavesurfer.js/dist/plugins/record.js";
@ -11,7 +12,6 @@
export let mode: string;
export let i18n: I18nFormatter;
export let dispatch: (event: any, detail?: any) => void;
export let dispatch_blob: (
blobs: Uint8Array[] | Blob[],
event: "stream" | "change" | "stop_recording"
@ -47,6 +47,17 @@
}, 1000);
};
const dispatch = createEventDispatcher<{
start_recording: undefined;
pause_recording: undefined;
stop_recording: undefined;
stop: undefined;
play: undefined;
pause: undefined;
end: undefined;
edit: undefined;
}>();
const format_time = (seconds: number): string => {
const minutes = Math.floor(seconds / 60);
const secondsRemainder = Math.round(seconds) % 60;
@ -109,7 +120,6 @@
$: recordingWaveform?.on("finish", () => {
dispatch("stop");
dispatch("end");
playing = false;
});
@ -207,7 +217,7 @@
{/if}
{#if micWaveform && !recordedAudio}
<WaveformRecordControls bind:record {i18n} {dispatch} />
<WaveformRecordControls bind:record {i18n} />
{/if}
{#if recordingWaveform && recordedAudio}

@ -1,12 +1,11 @@
<script lang="ts">
import { onMount } from "svelte";
import { Pause } from "@gradio/icons";
import type { I18nFormatter } from "@gradio/utils";
import RecordPlugin from "wavesurfer.js/dist/plugins/record.js";
import { createEventDispatcher } from "svelte";
export let record: RecordPlugin;
export let i18n: I18nFormatter;
export let dispatch: (event: string, detail?: any) => void;
let micDevices: MediaDeviceInfo[] = [];
let recordButton: HTMLButtonElement;
@ -15,6 +14,10 @@
let stopButton: HTMLButtonElement;
let stopButtonPaused: HTMLButtonElement;
const dispatch = createEventDispatcher<{
error: string;
}>();
$: try {
let tempDevices: MediaDeviceInfo[] = [];
RecordPlugin.getAvailableAudioDevices().then(

@ -66,9 +66,11 @@
{value}
{label}
{i18n}
{dispatch}
{waveform_settings}
{waveform_options}
on:pause
on:play
on:stop
/>
{:else}
<Empty size="small">