gradio / js /audio /streaming /StreamAudio.svelte
mindmime's picture
Upload folder using huggingface_hub
a03b3ba verified
<script lang="ts">
import { onMount } from "svelte";
import type { I18nFormatter } from "@gradio/utils";
import WaveSurfer from "wavesurfer.js";
import RecordPlugin from "wavesurfer.js/dist/plugins/record.js";
import type { WaveformOptions } from "../shared/types";
import DeviceSelect from "../shared/DeviceSelect.svelte";
export let recording = false;
export let paused_recording = false;
export let stop: () => void;
export let record: () => void;
export let i18n: I18nFormatter;
export let waveform_settings: Record<string, any>;
export let waveform_options: WaveformOptions = {
show_recording_waveform: true
};
let micWaveform: WaveSurfer;
let waveformRecord: RecordPlugin;
let microphoneContainer: HTMLDivElement;
let micDevices: MediaDeviceInfo[] = [];
onMount(() => {
create_mic_waveform();
});
const create_mic_waveform = (): void => {
if (micWaveform !== undefined) micWaveform.destroy();
if (!microphoneContainer) return;
micWaveform = WaveSurfer.create({
...waveform_settings,
height: 100,
container: microphoneContainer
});
waveformRecord = micWaveform.registerPlugin(RecordPlugin.create());
};
</script>
<div class="mic-wrap">
{#if waveform_options.show_recording_waveform}
<div
bind:this={microphoneContainer}
style:display={recording ? "block" : "none"}
/>
{/if}
<div class="controls">
{#if recording}
<button
class={paused_recording ? "stop-button-paused" : "stop-button"}
on:click={() => {
waveformRecord?.stopMic();
stop();
}}
>
<span class="record-icon">
<span class="pinger" />
<span class="dot" />
</span>
{paused_recording ? i18n("audio.pause") : i18n("audio.stop")}
</button>
{:else}
<button
class="record-button"
on:click={() => {
waveformRecord?.startMic();
record();
}}
>
<span class="record-icon">
<span class="dot" />
</span>
{i18n("audio.record")}
</button>
{/if}
<DeviceSelect bind:micDevices {i18n} />
</div>
</div>
<style>
.controls {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
}
.mic-wrap {
display: block;
align-items: center;
margin: var(--spacing-xl);
}
.stop-button-paused {
display: none;
height: var(--size-8);
width: var(--size-20);
background-color: var(--block-background-fill);
border-radius: var(--radius-3xl);
align-items: center;
border: 1px solid var(--neutral-400);
margin-right: 5px;
}
.stop-button-paused::before {
content: "";
height: var(--size-4);
width: var(--size-4);
border-radius: var(--radius-full);
background: var(--primary-600);
margin: 0 var(--spacing-xl);
}
.stop-button::before {
content: "";
height: var(--size-4);
width: var(--size-4);
border-radius: var(--radius-full);
background: var(--primary-600);
margin: 0 var(--spacing-xl);
animation: scaling 1800ms infinite;
}
.stop-button {
height: var(--size-8);
width: var(--size-20);
background-color: var(--block-background-fill);
border-radius: var(--radius-3xl);
align-items: center;
border: 1px solid var(--primary-600);
margin-right: 5px;
display: flex;
}
.record-button::before {
content: "";
height: var(--size-4);
width: var(--size-4);
border-radius: var(--radius-full);
background: var(--primary-600);
margin: 0 var(--spacing-xl);
}
.record-button {
height: var(--size-8);
width: var(--size-24);
background-color: var(--block-background-fill);
border-radius: var(--radius-3xl);
display: flex;
align-items: center;
border: 1px solid var(--neutral-400);
}
@keyframes scaling {
0% {
background-color: var(--primary-600);
scale: 1;
}
50% {
background-color: var(--primary-600);
scale: 1.2;
}
100% {
background-color: var(--primary-600);
scale: 1;
}
}
</style>