Skip to content

Commit

Permalink
Ensure Audio ouput events are dispatched (#6454)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
hannahblair and gradio-pr-bot committed Nov 16, 2023
1 parent a1e3c61 commit 2777f32
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 28 deletions.
6 changes: 6 additions & 0 deletions .changeset/honest-goats-rush.md
@@ -0,0 +1,6 @@
---
"@gradio/audio": patch
"gradio": patch
---

fix:Ensure Audio ouput events are dispatched
2 changes: 1 addition & 1 deletion demo/audio_component_events/run.ipynb
@@ -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}
32 changes: 23 additions & 9 deletions demo/audio_component_events/run.py
Expand Up @@ -6,16 +6,30 @@
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():
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():
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)
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()
36 changes: 29 additions & 7 deletions js/app/test/audio_component_events.spec.ts
Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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 ({
Expand All @@ -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");
});
4 changes: 3 additions & 1 deletion js/audio/Index.svelte
Expand Up @@ -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}
Expand Down Expand Up @@ -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)}
Expand Down
6 changes: 4 additions & 2 deletions js/audio/interactive/InteractiveAudio.svelte
Expand Up @@ -215,7 +215,6 @@
<AudioRecorder
bind:mode
{i18n}
{dispatch}
{dispatch_blob}
{waveform_settings}
{waveform_options}
Expand Down Expand Up @@ -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}

Expand Down
11 changes: 9 additions & 2 deletions js/audio/player/AudioPlayer.svelte
Expand Up @@ -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"
Expand All @@ -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;
Expand Down Expand Up @@ -78,7 +86,6 @@
$: waveform?.on("finish", () => {
playing = false;
dispatch("stop");
dispatch("end");
});
$: waveform?.on("pause", () => {
playing = false;
Expand Down
16 changes: 13 additions & 3 deletions js/audio/recorder/AudioRecorder.svelte
@@ -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";
Expand All @@ -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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -109,7 +120,6 @@
$: recordingWaveform?.on("finish", () => {
dispatch("stop");
dispatch("end");
playing = false;
});
Expand Down Expand Up @@ -207,7 +217,7 @@
{/if}

{#if micWaveform && !recordedAudio}
<WaveformRecordControls bind:record {i18n} {dispatch} />
<WaveformRecordControls bind:record {i18n} />
{/if}

{#if recordingWaveform && recordedAudio}
Expand Down
7 changes: 5 additions & 2 deletions js/audio/shared/WaveformRecordControls.svelte
@@ -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;
Expand All @@ -15,6 +14,10 @@
let stopButton: HTMLButtonElement;
let stopButtonPaused: HTMLButtonElement;
const dispatch = createEventDispatcher<{
error: string;
}>();
$: try {
let tempDevices: MediaDeviceInfo[] = [];
RecordPlugin.getAvailableAudioDevices().then(
Expand Down
4 changes: 3 additions & 1 deletion js/audio/static/StaticAudio.svelte
Expand Up @@ -66,9 +66,11 @@
{value}
{label}
{i18n}
{dispatch}
{waveform_settings}
{waveform_options}
on:pause
on:play
on:stop
/>
{:else}
<Empty size="small">
Expand Down

0 comments on commit 2777f32

Please sign in to comment.