pyannote-speech-separation-pipeline
/
pyannote_viewer
/frontend
/shared
/WaveformRecordControls.svelte
<script lang="ts"> | |
import { Pause } from "@gradio/icons"; | |
import type { I18nFormatter } from "@gradio/utils"; | |
import RecordPlugin from "@gryannote/wavesurfer.js/dist/plugins/record.js"; | |
import DeviceSelect from "./DeviceSelect.svelte"; | |
export let record: RecordPlugin; | |
export let i18n: I18nFormatter; | |
let micDevices: MediaDeviceInfo[] = []; | |
let recordButton: HTMLButtonElement; | |
let pauseButton: HTMLButtonElement; | |
let resumeButton: HTMLButtonElement; | |
let stopButton: HTMLButtonElement; | |
let stopButtonPaused: HTMLButtonElement; | |
export let record_time: string; | |
export let show_recording_waveform: boolean | undefined; | |
export let timing = false; | |
$: record.on("record-start", () => { | |
record.startMic(); | |
recordButton.style.display = "none"; | |
stopButton.style.display = "flex"; | |
pauseButton.style.display = "block"; | |
}); | |
$: record.on("record-end", () => { | |
if (record.isPaused()) { | |
record.resumeRecording(); | |
record.stopRecording(); | |
} | |
record.stopMic(); | |
recordButton.style.display = "flex"; | |
stopButton.style.display = "none"; | |
pauseButton.style.display = "none"; | |
recordButton.disabled = false; | |
}); | |
$: record.on("record-pause", () => { | |
pauseButton.style.display = "none"; | |
resumeButton.style.display = "block"; | |
stopButton.style.display = "none"; | |
stopButtonPaused.style.display = "flex"; | |
}); | |
$: record.on("record-resume", () => { | |
pauseButton.style.display = "block"; | |
resumeButton.style.display = "none"; | |
recordButton.style.display = "none"; | |
stopButton.style.display = "flex"; | |
stopButtonPaused.style.display = "none"; | |
}); | |
</script> | |
<div class="controls"> | |
<div class="wrapper"> | |
<button | |
bind:this={recordButton} | |
class="record record-button" | |
on:click={() => record.startRecording()}>{i18n("audio.record")}</button | |
> | |
<button | |
bind:this={stopButton} | |
class="stop-button {record.isPaused() ? 'stop-button-paused' : ''}" | |
on:click={() => { | |
if (record.isPaused()) { | |
record.resumeRecording(); | |
record.stopRecording(); | |
} | |
record.stopRecording(); | |
}}>{i18n("audio.stop")}</button | |
> | |
<button | |
bind:this={stopButtonPaused} | |
id="stop-paused" | |
class="stop-button-paused" | |
on:click={() => { | |
if (record.isPaused()) { | |
record.resumeRecording(); | |
record.stopRecording(); | |
} | |
record.stopRecording(); | |
}}>{i18n("audio.stop")}</button | |
> | |
<button | |
aria-label="pause" | |
bind:this={pauseButton} | |
class="pause-button" | |
on:click={() => record.pauseRecording()}><Pause /></button | |
> | |
<button | |
bind:this={resumeButton} | |
class="resume-button" | |
on:click={() => record.resumeRecording()}>{i18n("audio.resume")}</button | |
> | |
{#if timing && !show_recording_waveform} | |
<time class="duration-button duration">{record_time}</time> | |
{/if} | |
</div> | |
<DeviceSelect bind:micDevices {i18n} /> | |
</div> | |
<style> | |
.controls { | |
display: flex; | |
align-items: center; | |
justify-content: space-between; | |
flex-wrap: wrap; | |
} | |
.wrapper { | |
display: flex; | |
align-items: center; | |
flex-wrap: wrap; | |
} | |
.record { | |
margin-right: var(--spacing-md); | |
} | |
.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: var(--size-1) var(--size-1) 0 0; | |
} | |
.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 { | |
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(--primary-600); | |
margin: var(--size-1) var(--size-1) 0 0; | |
} | |
.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); | |
} | |
.stop-button:disabled { | |
cursor: not-allowed; | |
} | |
.record-button:disabled { | |
cursor: not-allowed; | |
opacity: 0.5; | |
} | |
@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; | |
} | |
} | |
.pause-button { | |
display: none; | |
height: var(--size-8); | |
width: var(--size-20); | |
border: 1px solid var(--neutral-400); | |
border-radius: var(--radius-3xl); | |
padding: var(--spacing-md); | |
margin: var(--size-1) var(--size-1) 0 0; | |
} | |
.resume-button { | |
display: none; | |
height: var(--size-8); | |
width: var(--size-20); | |
border: 1px solid var(--neutral-400); | |
border-radius: var(--radius-3xl); | |
padding: var(--spacing-xl); | |
line-height: 1px; | |
font-size: var(--text-md); | |
margin: var(--size-1) var(--size-1) 0 0; | |
} | |
.duration { | |
display: flex; | |
height: var(--size-8); | |
width: var(--size-20); | |
border: 1px solid var(--neutral-400); | |
border-radius: var(--radius-3xl); | |
padding: var(--spacing-md); | |
align-items: center; | |
justify-content: center; | |
margin: var(--size-1) var(--size-1) 0 0; | |
} | |
:global(::part(region)) { | |
border-radius: var(--radius-md); | |
border: none; | |
background-color: unset; | |
} | |
:global(::part(region))::after { | |
content: ""; | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
opacity: 0.2; | |
border-radius: var(--radius-md); | |
} | |
:global(::part(region-handle)) { | |
width: 5px ; | |
border: none; | |
} | |
</style> | |