Stream works now (#2351)

* changes

* changes

* lazy load streaming deps

* lazy load streaming deps

* cleanup

* fix last chunks of streaming

* add changelog

* add changelog

* add changelog

* add changelog

* updated streaming demo

* renamed sst

* changes

Co-authored-by: pngwn <hello@pngwn.io>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
This commit is contained in:
aliabid94 2022-10-05 16:11:47 -05:00 committed by GitHub
parent b59c45160d
commit ac378d0875
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 324 additions and 97 deletions

View File

@ -15,6 +15,7 @@ You can now see gradio's release history directly on the website, and also keep
3. Catch the permission exception on the audio component by [@Ian-GL](https://github.com/Ian-GL) in [PR 2330](https://github.com/gradio-app/gradio/pull/2330)
4. Fix image_classifier_interface_load demo by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2365](https://github.com/gradio-app/gradio/pull/2365)
5. Fix combining adjacent components without gaps by introducing `gr.Row(variant="compact")` by [@aliabid94](https://github.com/aliabid94) in [PR 2291](https://github.com/gradio-app/gradio/pull/2291) This comes with deprecation of the following arguments for `Component.style`: `round`, `margin`, `border`.
6. Fix audio streaming, which was previously choppy in [PR 2351](https://github.com/gradio-app/gradio/pull/2351). Big thanks to [@yannickfunk](https://github.com/yannickfunk) for the proposed solution.
## Documentation Changes:

View File

@ -1,20 +1,27 @@
import gradio as gr
import numpy as np
import time
def add_to_stream(audio, instream):
time.sleep(1)
if audio is None:
return gr.update(), instream
if instream is None:
ret = audio
else:
ret = (audio[0], np.concatenate((instream[1], audio[1])))
return ret, ret
with gr.Blocks() as demo:
inp = gr.Audio(source="microphone")
out = gr.Audio()
stream = gr.State()
clear = gr.Button("Clear")
def add_to_stream(audio, instream):
if audio is None:
return gr.update(), instream
if instream is None:
ret = audio
else:
ret = (audio[0], np.concatenate((instream[1], audio[1])))
return ret, ret
inp.stream(add_to_stream, [inp, stream], [out, stream])
clear.click(lambda: [None, None, None], None, [inp, out, stream])
if __name__ == "__main__":
demo.launch()

View File

@ -1 +1,2 @@
deepspeech==0.8.2
torch
transformers

View File

@ -1,47 +1,27 @@
from deepspeech import Model
from transformers import pipeline
import gradio as gr
import scipy.io.wavfile
import numpy as np
import time
model_file_path = "deepspeech-0.8.2-models.pbmm"
lm_file_path = "deepspeech-0.8.2-models.scorer"
beam_width = 100
lm_alpha = 0.93
lm_beta = 1.18
p = pipeline("automatic-speech-recognition")
model = Model(model_file_path)
model.enableExternalScorer(lm_file_path)
model.setScorerAlphaBeta(lm_alpha, lm_beta)
model.setBeamWidth(beam_width)
def transcribe(audio, state=""):
time.sleep(2)
text = p(audio)["text"]
state += text + " "
return state, state
def reformat_freq(sr, y):
if sr not in (
48000,
16000,
): # Deepspeech only supports 16k, (we convert 48k -> 16k)
raise ValueError("Unsupported rate", sr)
if sr == 48000:
y = (
((y / max(np.max(y), 1)) * 32767)
.reshape((-1, 3))
.mean(axis=1)
.astype("int16")
)
sr = 16000
return sr, y
def transcribe(speech, stream):
_, y = reformat_freq(*speech)
if stream is None:
stream = model.createStream()
stream.feedAudioContent(y)
text = stream.intermediateDecode()
return text, stream
demo = gr.Interface(transcribe, ["microphone", "state"], ["text", "state"], live=True)
demo = gr.Interface(
fn=transcribe,
inputs=[
gr.Audio(source="microphone", type="filepath", streaming=True),
"state"
],
outputs=[
"textbox",
"state"
],
live=True
)
if __name__ == "__main__":
demo.launch()

View File

@ -423,7 +423,7 @@ class Streamable(Block):
api_name: AnyStr = None,
status_tracker: Optional[StatusTracker] = None,
scroll_to_output: bool = False,
show_progress: bool = True,
show_progress: bool = False,
queue: Optional[bool] = None,
preprocess: bool = True,
postprocess: bool = True,

View File

@ -690,7 +690,7 @@ class TabbedInterface(Blocks):
"""
A TabbedInterface is created by providing a list of Interfaces, each of which gets
rendered in a separate tab.
Demos: sst_or_tts
Demos: stt_or_tts
"""
def __init__(

View File

@ -28,7 +28,7 @@ def copy_all_demos(source_dir: str, dest_dir: str):
"model3D",
"reset_components",
"reverse_audio",
"sst_or_tts",
"stt_or_tts",
"stream_audio",
"stream_frames",
"zip_files",

View File

@ -34,7 +34,7 @@ export default defineConfig(({ mode }) => {
build: {
target: "esnext",
minify: false,
minify: production,
outDir: `../../../gradio/templates/${is_cdn ? "cdn" : "frontend"}`
},
define: {

View File

@ -11,6 +11,8 @@
"@gradio/atoms": "workspace:^0.0.1",
"@gradio/icons": "workspace:^0.0.1",
"@gradio/upload": "workspace:^0.0.1",
"extendable-media-recorder": "^7.0.2",
"extendable-media-recorder-wav-encoder": "^7.0.76",
"svelte-range-slider-pips": "^2.0.1"
}
}

View File

@ -7,13 +7,15 @@
</script>
<script lang="ts">
import { onDestroy, createEventDispatcher } from "svelte";
import { onDestroy, createEventDispatcher, tick } from "svelte";
import { Upload, ModifyUpload } from "@gradio/upload";
import { BlockLabel } from "@gradio/atoms";
import { Music } from "@gradio/icons";
// @ts-ignore
import Range from "svelte-range-slider-pips";
import type { IBlobEvent, IMediaRecorder } from "extendable-media-recorder";
export let value: null | { name: string; data: string } = null;
export let label: string;
export let show_label: boolean;
@ -29,13 +31,34 @@
// export let type: "normal" | "numpy" = "normal";
let recording = false;
let recorder: MediaRecorder;
let recorder: IMediaRecorder;
let mode = "";
let audio_chunks: Array<Blob> = [];
let audio_blob;
let header: Uint8Array | undefined = undefined;
let pending_stream: Array<Uint8Array> = [];
let submit_pending_stream_on_pending_end: boolean = false;
let player;
let inited = false;
let crop_values = [0, 100];
const STREAM_TIMESLICE = 500;
const NUM_HEADER_BYTES = 44;
let audio_chunks: Array<Blob> = [];
let audio_blob;
let module_promises:
| [
Promise<typeof import("extendable-media-recorder")>,
Promise<typeof import("extendable-media-recorder-wav-encoder")>
];
function get_modules() {
module_promises = [
import("extendable-media-recorder"),
import("extendable-media-recorder-wav-encoder")
];
}
if (streaming) {
get_modules();
}
const dispatch = createEventDispatcher<{
change: AudioData;
@ -57,8 +80,21 @@
});
}
const dispatch_blob = async (
blobs: Array<Uint8Array> | Blob[],
event: "stream" | "change"
) => {
let audio_blob = new Blob(blobs, { type: "audio/wav" });
value = {
data: await blob_to_data_url(audio_blob),
name
};
dispatch(event, value);
};
async function prepare_audio() {
let stream: MediaStream | null;
try {
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
} catch (err) {
@ -73,38 +109,67 @@
}
}
if (stream === null) {
return;
if (stream == null) return;
if (streaming) {
const [{ MediaRecorder, register }, { connect }] = await Promise.all(
module_promises
);
await register(await connect());
recorder = new MediaRecorder(stream, { mimeType: "audio/wav" });
async function handle_chunk(event: IBlobEvent) {
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 = [];
}
}
recorder.addEventListener("dataavailable", handle_chunk);
} else {
recorder = new MediaRecorder(stream);
recorder.addEventListener("dataavailable", (event) => {
audio_chunks.push(event.data);
});
recorder.addEventListener("stop", async () => {
recording = false;
await dispatch_blob(audio_chunks, "change");
audio_chunks = [];
});
}
recorder = new MediaRecorder(stream);
recorder.addEventListener("dataavailable", (event) => {
audio_chunks.push(event.data);
});
recorder.addEventListener("stop", async () => {
if (!streaming) {
recording = false;
}
audio_blob = new Blob(audio_chunks, { type: "audio/wav" });
audio_chunks = [];
value = {
data: await blob_to_data_url(audio_blob),
name
};
dispatch(streaming ? "stream" : "change", value);
});
inited = true;
}
$: if (submit_pending_stream_on_pending_end && pending === false) {
submit_pending_stream_on_pending_end = false;
if (header && pending_stream) {
let blobParts: Array<Uint8Array> = [header].concat(pending_stream);
pending_stream = [];
dispatch_blob(blobParts, "stream");
}
}
async function record() {
recording = true;
if (!inited) await prepare_audio();
if (recorder) {
recording = true;
audio_chunks = [];
header = undefined;
if (streaming) {
recorder.start(STREAM_TIMESLICE);
} else {
recorder.start();
}
}
@ -115,10 +180,13 @@
}
});
const stop = () => {
const stop = async () => {
recorder.stop();
if (streaming) {
recording = false;
if (pending) {
submit_pending_stream_on_pending_end = true;
}
}
};
@ -177,20 +245,6 @@
export let dragging = false;
$: dispatch("drag", dragging);
if (streaming) {
window.setInterval(() => {
if (
recording &&
recorder &&
recorder.state === "recording" &&
pending === false
) {
stop();
record();
}
}, 500);
}
</script>
<BlockLabel {show_label} Icon={Music} label={label || "Audio"} />

182
ui/pnpm-lock.yaml generated
View File

@ -146,11 +146,15 @@ importers:
'@gradio/atoms': workspace:^0.0.1
'@gradio/icons': workspace:^0.0.1
'@gradio/upload': workspace:^0.0.1
extendable-media-recorder: ^7.0.2
extendable-media-recorder-wav-encoder: ^7.0.76
svelte-range-slider-pips: ^2.0.1
dependencies:
'@gradio/atoms': link:../atoms
'@gradio/icons': link:../icons
'@gradio/upload': link:../upload
extendable-media-recorder: 7.0.2
extendable-media-recorder-wav-encoder: 7.0.76
svelte-range-slider-pips: 2.0.2
packages/button:
@ -435,6 +439,13 @@ packages:
regenerator-runtime: 0.13.9
dev: false
/@babel/runtime/7.19.0:
resolution: {integrity: sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==}
engines: {node: '>=6.9.0'}
dependencies:
regenerator-runtime: 0.13.9
dev: false
/@cloudflare/workers-types/3.14.1:
resolution: {integrity: sha512-B1/plF62pt+H2IJHvApK8fdOJAVsvojvacuac8x8s+JIyqbropMyqNqHTKLm3YD8ZFLGwYeFTudU+PQ7vGvBdA==}
dev: true
@ -965,6 +976,14 @@ packages:
resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=}
dev: false
/automation-events/4.0.21:
resolution: {integrity: sha512-VJdSzclxoBVAqE4UAwmqPLHAM3EI2iYhZ2MADdQnjFlW/GE17B47aQ6y9JE9up2bf8f7I5RfqGhJM464jPMzww==}
engines: {node: '>=12.20.1'}
dependencies:
'@babel/runtime': 7.19.0
tslib: 2.4.0
dev: false
/autoprefixer/10.4.2_postcss@8.4.6:
resolution: {integrity: sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==}
engines: {node: ^10 || ^12 || >=14}
@ -1057,6 +1076,15 @@ packages:
dependencies:
fill-range: 7.0.1
/broker-factory/3.0.68:
resolution: {integrity: sha512-QrbDJ/7YwZ2+TuSreT8WMKrssIO3VjywMu5C5Jq+pJ+OkIVIXhUkxdBhNX2mmRXlzkU+jVXz8uMyRP+2uAgx8w==}
dependencies:
'@babel/runtime': 7.19.0
fast-unique-numbers: 6.0.21
tslib: 2.4.0
worker-factory: 6.0.69
dev: false
/browserslist/4.19.1:
resolution: {integrity: sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@ -1200,6 +1228,16 @@ packages:
engines: {node: '>= 10'}
dev: false
/compilerr/9.0.21:
resolution: {integrity: sha512-H6ZnGHPBiwVdWt8GbAPuQK4mmtRTJ5yucysgFFhGxmPoLCAmaMSxtvHNzhAAGNqBRZOTsGjkwT8clNw6CJcGgQ==}
engines: {node: '>=12.20.1'}
dependencies:
'@babel/runtime': 7.19.0
dashify: 2.0.0
indefinite-article: 0.0.2
tslib: 2.4.0
dev: false
/concat-map/0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
@ -1352,6 +1390,11 @@ packages:
d3-array: 3.1.1
dev: false
/dashify/2.0.0:
resolution: {integrity: sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==}
engines: {node: '>=4'}
dev: false
/debug/4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@ -1935,6 +1978,44 @@ packages:
/estree-walker/2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
/extendable-media-recorder-wav-encoder-broker/7.0.70:
resolution: {integrity: sha512-nnVAxiLBdf0PLDXP/8+bKYYRs2PmoJMoJzpcDGOra8GsHIPS+ytmS+85DUFSYGxaxohrhovgN0jVXSyjJ6hQSQ==}
dependencies:
'@babel/runtime': 7.19.0
broker-factory: 3.0.68
extendable-media-recorder-wav-encoder-worker: 8.0.69
tslib: 2.4.0
dev: false
/extendable-media-recorder-wav-encoder-worker/8.0.69:
resolution: {integrity: sha512-8RJgKYTTHkzDoCWrnPMMqX+TyJpwzP9lwqxQWDpa9J5J1DP0SybgoYWP8Dtty/R5xT344lU+NKo7g1661i7Ujg==}
dependencies:
'@babel/runtime': 7.19.0
tslib: 2.4.0
worker-factory: 6.0.69
dev: false
/extendable-media-recorder-wav-encoder/7.0.76:
resolution: {integrity: sha512-HLeyR9R0mUPOo7zG3d3GRWltNaSYUjyUZGQ8amRjuQVkZFXszmOIAAUVBq3fou0Z3V1mAEo+mXnCqbEfYtgZXQ==}
dependencies:
'@babel/runtime': 7.19.0
extendable-media-recorder-wav-encoder-broker: 7.0.70
extendable-media-recorder-wav-encoder-worker: 8.0.69
tslib: 2.4.0
dev: false
/extendable-media-recorder/7.0.2:
resolution: {integrity: sha512-rZAvRaAJgMyQUMWMrgSB1U1o9nNXaguVAwNVOnt396tRlfZtBbHxraygqjPQXNs6kb1H4XcG/RLTn+hfZJx2Xg==}
dependencies:
'@babel/runtime': 7.19.0
media-encoder-host: 8.0.78
multi-buffer-data-view: 3.0.21
recorder-audio-worklet: 5.1.29
standardized-audio-context: 25.3.32
subscribable-things: 2.1.7
tslib: 2.4.0
dev: false
/fast-glob/3.2.11:
resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==}
engines: {node: '>=8.6.0'}
@ -1945,6 +2026,14 @@ packages:
merge2: 1.4.1
micromatch: 4.0.4
/fast-unique-numbers/6.0.21:
resolution: {integrity: sha512-MW8UAAypyhNtbnMlSch9EiEAuiMo1y6O02WzI5mcHAzvirdIm/hXMVp4QH9ijWnU1xzW23GXk6Bf+5B1kv9hzw==}
engines: {node: '>=12.20.1'}
dependencies:
'@babel/runtime': 7.19.0
tslib: 2.4.0
dev: false
/fastq/1.13.0:
resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
dependencies:
@ -2174,6 +2263,10 @@ packages:
parent-module: 1.0.1
resolve-from: 4.0.0
/indefinite-article/0.0.2:
resolution: {integrity: sha512-Au/2XzRkvxq2J6w5uvSSbBKPZ5kzINx5F2wb0SF8xpRL8BP9Lav81TnRbfPp6p+SYjYxwaaLn4EUwI3/MmYKSw==}
dev: false
/inflight/1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
dependencies:
@ -2412,6 +2505,34 @@ packages:
semver: 6.3.0
dev: true
/media-encoder-host-broker/7.0.70:
resolution: {integrity: sha512-ixixE9auojgUHEIQHYvJ75vPxetkHreIfxK20SQ4ZoZSO/vRj4+up72rETMbj2e0UO7xnDJqADsx+sfkoV2eVA==}
dependencies:
'@babel/runtime': 7.19.0
broker-factory: 3.0.68
fast-unique-numbers: 6.0.21
media-encoder-host-worker: 9.0.70
tslib: 2.4.0
dev: false
/media-encoder-host-worker/9.0.70:
resolution: {integrity: sha512-ttZAvG0osaOTl6C1OMIzZzFQ/ZIBiRDHyrfcM0d+ZF65tAjLtA53vWoINcgwRBEwc4P62y9a12pbujB1ZdCU6Q==}
dependencies:
'@babel/runtime': 7.19.0
extendable-media-recorder-wav-encoder-broker: 7.0.70
tslib: 2.4.0
worker-factory: 6.0.69
dev: false
/media-encoder-host/8.0.78:
resolution: {integrity: sha512-kobfdkFcfp8w2SkPY8ISHzG6L7o8tgtIvXtK5/j1hfZGZxqf0sxxXEzU9WFm9jNKnlgko6RSZhPzD24w60I4zQ==}
dependencies:
'@babel/runtime': 7.19.0
media-encoder-host-broker: 7.0.70
media-encoder-host-worker: 9.0.70
tslib: 2.4.0
dev: false
/memorystream/0.3.1:
resolution: {integrity: sha1-htcJCzDORV1j+64S3aUaR93K+bI=}
engines: {node: '>= 0.10.0'}
@ -2499,6 +2620,14 @@ packages:
/ms/2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
/multi-buffer-data-view/3.0.21:
resolution: {integrity: sha512-K/v5mjWMbJEgiZzn6Pr7+jKoKuChY6GdQEeiKNWhIi0QILXzJmUvuho85z6AYYh38Ua2kGY/5E3qs2ceoZ8chA==}
engines: {node: '>=12.20.1'}
dependencies:
'@babel/runtime': 7.19.0
tslib: 2.4.0
dev: false
/nanoid/3.2.0:
resolution: {integrity: sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@ -2980,6 +3109,26 @@ packages:
dependencies:
picomatch: 2.3.1
/recorder-audio-worklet-processor/4.2.15:
resolution: {integrity: sha512-5QTJKukH8JcQR1f2FqZsQ1QD2aoc6/+tM0WPv8sqEI4THzbiMfH4VuWF3BfdL2F9mRjLo81nFC9OShCj87wMhg==}
dependencies:
'@babel/runtime': 7.19.0
tslib: 2.4.0
dev: false
/recorder-audio-worklet/5.1.29:
resolution: {integrity: sha512-HCuB5c50UdRSm8DubnRYIzfNo+eNPfdCAWlSO9jag3lt9vnAJpg6u4DBBb/psXOk7PsHaRsHkZTdg96RSybawA==}
dependencies:
'@babel/runtime': 7.19.0
broker-factory: 3.0.68
fast-unique-numbers: 6.0.21
recorder-audio-worklet-processor: 4.2.15
standardized-audio-context: 25.3.32
subscribable-things: 2.1.7
tslib: 2.4.0
worker-factory: 6.0.69
dev: false
/regenerator-runtime/0.13.9:
resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==}
dev: false
@ -3063,6 +3212,10 @@ packages:
resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
dev: false
/rxjs-interop/2.0.0:
resolution: {integrity: sha512-ASEq9atUw7lualXB+knvgtvwkCEvGWV2gDD/8qnASzBkzEARZck9JAyxmY8OS6Nc1pCPEgDTKNcx+YqqYfzArw==}
dev: false
/sade/1.8.1:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'}
@ -3210,6 +3363,14 @@ packages:
resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==}
dev: false
/standardized-audio-context/25.3.32:
resolution: {integrity: sha512-TtnRZGzHaTowIrEPo7w7WK74TrrY885NpplFpD79h85YuUAUBrUGifHlh8GK11oyZHfwDtCV29yFPfIHWotrXg==}
dependencies:
'@babel/runtime': 7.19.0
automation-events: 4.0.21
tslib: 2.4.0
dev: false
/string-width/4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@ -3265,6 +3426,14 @@ packages:
dependencies:
min-indent: 1.0.1
/subscribable-things/2.1.7:
resolution: {integrity: sha512-z8CMs8i0KSz69Lk83db40io5OEEq4TeuB/g6Z8tpSzmG20oNAL+C2Uys7XAOvcU4Iqrvvc/gcdFLRn6bi1Gb/w==}
dependencies:
'@babel/runtime': 7.19.0
rxjs-interop: 2.0.0
tslib: 2.4.0
dev: false
/supports-color/5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
@ -3633,6 +3802,10 @@ packages:
/tslib/2.3.1:
resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
/tslib/2.4.0:
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
dev: false
/type-detect/4.0.8:
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
engines: {node: '>=4'}
@ -3801,6 +3974,15 @@ packages:
string-width: 4.2.3
dev: true
/worker-factory/6.0.69:
resolution: {integrity: sha512-vut3DexCAyRicCuvfUAhOAlt7s4segcDutnqAH/ybxbpYzDu4qLfkmpEzfinbGCkPffTzXq64XulaSdqVG3Ncw==}
dependencies:
'@babel/runtime': 7.19.0
compilerr: 9.0.21
fast-unique-numbers: 6.0.21
tslib: 2.4.0
dev: false
/worktop/0.8.0-next.14:
resolution: {integrity: sha512-RZgqHu1w/JcUdWOE/BUEAzarrUUHh39eWkLdX8XpA6MfgLJF6X5Vl26CV7/wcm4O/UpZvHMGJUtB9eYTqDjc9g==}
engines: {node: '>=12'}