File size: 3,903 Bytes
9dfbb06 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
<script lang="ts">
import { onMount, onDestroy, createEventDispatcher } from "svelte";
import { Upload, ModifyUpload } from "@gradio/upload";
import { upload, prepare_files, type FileData } from "@gradio/client";
import AudioPlayer from "../player/AudioPlayer.svelte";
import { _ } from "svelte-i18n";
import type { IBlobEvent, IMediaRecorder } from "extendable-media-recorder";
import type { I18nFormatter } from "js/app/src/gradio_helper";
import AudioRecorder from "../recorder/AudioRecorder.svelte";
import StreamAudio from "../streaming/StreamAudio.svelte";
import { SelectSource } from "@gradio/atoms";
export let value: null | FileData = null;
export let label: string;
export let root: string;
export let show_label = true;
export let sources:
| ["microphone"]
| ["upload"]
| ["microphone", "upload"]
| ["upload", "microphone"] = ["microphone", "upload"];
export let pending = false;
export let streaming = false;
export let i18n: I18nFormatter;
export let waveform_settings = {};
export let dragging: boolean;
export let active_source: "microphone" | "upload";
export let handle_reset_value: () => void = () => {};
$: dispatch("drag", dragging);
// TODO: make use of this
// export let type: "normal" | "numpy" = "normal";
let recording = false;
let recorder: IMediaRecorder;
let mode = "";
let header: Uint8Array | undefined = undefined;
let pending_stream: Uint8Array[] = [];
let submit_pending_stream_on_pending_end = false;
let inited = false;
const STREAM_TIMESLICE = 500;
const NUM_HEADER_BYTES = 44;
let audio_chunks: Blob[] = [];
let module_promises: [
Promise<typeof import("extendable-media-recorder")>,
Promise<typeof import("extendable-media-recorder-wav-encoder")>
];
function get_modules(): void {
module_promises = [
import("extendable-media-recorder"),
import("extendable-media-recorder-wav-encoder")
];
}
if (streaming) {
get_modules();
}
const dispatch = createEventDispatcher<{
change: FileData | null;
stream: FileData;
edit: never;
play: never;
pause: never;
stop: never;
end: never;
drag: boolean;
error: string;
upload: FileData;
clear: undefined;
start_recording: undefined;
pause_recording: undefined;
stop_recording: FileData | null;
}>();
const dispatch_blob = async (
blobs: Uint8Array[] | Blob[],
event: "stream" | "change" | "stop_recording"
): Promise<void> => {
let _audio_blob = new File(blobs, "audio.wav");
const val = await prepare_files([_audio_blob], event === "stream");
value = ((await upload(val, root))?.filter(Boolean) as FileData[])[0];
dispatch(event, value);
};
onDestroy(() => {
if (streaming && recorder && recorder.state !== "inactive") {
recorder.stop();
}
});
async function handle_chunk(event: IBlobEvent): Promise<void> {
let buffer = await event.data.arrayBuffer();
let payload = new Uint8Array(buffer);
if (!header) {
header = new Uint8Array(buffer.slice(0, NUM_HEADER_BYTES));
payload = new Uint8Array(buffer.slice(NUM_HEADER_BYTES));
}
if (pending) {
pending_stream.push(payload);
} else {
let blobParts = [header].concat(pending_stream, [payload]);
dispatch_blob(blobParts, "stream");
pending_stream = [];
}
}
$: if (submit_pending_stream_on_pending_end && pending === false) {
submit_pending_stream_on_pending_end = false;
if (header && pending_stream) {
let blobParts: Uint8Array[] = [header].concat(pending_stream);
pending_stream = [];
dispatch_blob(blobParts, "stream");
}
}
function clear(): void {
dispatch("change", null);
dispatch("clear");
mode = "";
value = null;
}
function handle_load({ detail }: { detail: FileData }): void {
value = detail;
dispatch("change", detail);
dispatch("upload", detail);
}
</script>
<AudioRecorder
bind:mode
{i18n}
{dispatch}
{dispatch_blob}
{waveform_settings}
{handle_reset_value}
/>
|