diff --git a/backend/gradio_webrtc/__init__.py b/backend/gradio_webrtc/__init__.py index 306a6e5..2903fed 100644 --- a/backend/gradio_webrtc/__init__.py +++ b/backend/gradio_webrtc/__init__.py @@ -1,3 +1,3 @@ -from .webrtc import WebRTC +from .webrtc import WebRTC, StreamHandler -__all__ = ["WebRTC"] +__all__ = ["StreamHandler", "WebRTC"] diff --git a/backend/gradio_webrtc/utils.py b/backend/gradio_webrtc/utils.py index d08e9e9..d7f6d4f 100644 --- a/backend/gradio_webrtc/utils.py +++ b/backend/gradio_webrtc/utils.py @@ -15,8 +15,7 @@ AUDIO_PTIME = 0.020 def player_worker_decode( loop, - callable: Callable, - stream, + next: Callable, queue: asyncio.Queue, throttle_playback: bool, thread_quit: threading.Event, @@ -33,22 +32,10 @@ def player_worker_decode( frame_time = None start_time = time.time() - generator = None while not thread_quit.is_set(): - if stream.latest_args == "not_set": - continue - if generator is None: - generator = callable(*stream.latest_args) - try: - frame = next(generator) - except Exception as exc: - if isinstance(exc, StopIteration): - logger.debug("Stopping audio stream") - asyncio.run_coroutine_threadsafe(queue.put(None), loop) - thread_quit.set() - break - + frame = next() + logger.debug("emitted %s", frame) # read up to 1 second ahead if throttle_playback: elapsed_time = time.time() - start_time @@ -56,7 +43,7 @@ def player_worker_decode( time.sleep(0.1) sample_rate, audio_array = frame format = "s16" if audio_array.dtype == "int16" else "fltp" - frame = av.AudioFrame.from_ndarray(audio_array, format=format, layout="mono") + frame = av.AudioFrame.from_ndarray(audio_array, format=format, layout="stereo") frame.sample_rate = sample_rate for frame in audio_resampler.resample(frame): # fix timestamps diff --git a/backend/gradio_webrtc/webrtc.py b/backend/gradio_webrtc/webrtc.py index a18edbd..955a541 100644 --- a/backend/gradio_webrtc/webrtc.py +++ b/backend/gradio_webrtc/webrtc.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio +from abc import ABC, abstractmethod import logging import threading import time @@ -10,14 +11,16 @@ import traceback from collections.abc import Callable from typing import TYPE_CHECKING, Any, Generator, Literal, Sequence, cast +import anyio.to_thread import numpy as np from aiortc import ( AudioStreamTrack, RTCPeerConnection, RTCSessionDescription, VideoStreamTrack, + MediaStreamTrack, ) -from aiortc.contrib.media import MediaRelay, VideoFrame # type: ignore +from aiortc.contrib.media import MediaRelay, AudioFrame, VideoFrame # type: ignore from aiortc.mediastreams import MediaStreamError from gradio import wasm_utils from gradio.components.base import Component, server @@ -47,7 +50,7 @@ class VideoCallback(VideoStreamTrack): def __init__( self, - track, + track: MediaStreamTrack, event_handler: Callable, ) -> None: super().__init__() # don't forget this! @@ -72,7 +75,7 @@ class VideoCallback(VideoStreamTrack): async def recv(self): try: try: - frame = await self.track.recv() + frame = cast(VideoFrame, await self.track.recv()) except MediaStreamError: return frame_array = frame.to_ndarray(format="bgr24") @@ -100,6 +103,100 @@ class VideoCallback(VideoStreamTrack): logger.debug(exec) +class StreamHandler(ABC): + @abstractmethod + def receive(self, frame: tuple[int, np.ndarray] | np.ndarray) -> None: + pass + + @abstractmethod + def emit(self) -> None: + pass + + +class AudioCallback(AudioStreamTrack): + kind = "audio" + + def __init__( + self, + track: MediaStreamTrack, + event_handler: StreamHandler, + ) -> None: + self.track = track + self.event_handler = event_handler + self.current_timestamp = 0 + self.latest_args = "not_set" + self.queue = asyncio.Queue() + self.thread_quit = threading.Event() + self.__thread = None + self._start: float | None = None + self.has_started = False + super().__init__() + + async def process_input_frames(self) -> None: + while not self.thread_quit.is_set(): + try: + frame = cast(AudioFrame, await self.track.recv()) + numpy_array = frame.to_ndarray() + logger.debug("numpy array shape %s", numpy_array.shape) + await anyio.to_thread.run_sync( + self.event_handler.receive, (frame.sample_rate, numpy_array) + ) + except MediaStreamError: + break + + def start(self): + if not self.has_started: + asyncio.create_task(self.process_input_frames()) + self.__thread = threading.Thread( + name="audio-output-decoders", + target=player_worker_decode, + args=( + asyncio.get_event_loop(), + self.event_handler.emit, + self.queue, + True, + self.thread_quit, + ), + ) + self.__thread.start() + self.has_started = True + + async def recv(self): + try: + if self.readyState != "live": + raise MediaStreamError + + self.start() + data = await self.queue.get() + logger.debug("data %s", data) + if data is None: + self.stop() + return + + data_time = data.time + + # control playback rate + if data_time is not None: + if self._start is None: + self._start = time.time() - data_time + else: + wait = self._start + data_time - time.time() + await asyncio.sleep(wait) + + return data + except Exception as e: + logger.debug(e) + exec = traceback.format_exc() + logger.debug(exec) + + def stop(self): + self.thread_quit.set() + if self.__thread is not None: + self.__thread.join() + self.__thread = None + super().stop() + + class ServerToClientVideo(VideoStreamTrack): """ This works for streaming input and output @@ -116,17 +213,6 @@ class ServerToClientVideo(VideoStreamTrack): self.latest_args: str | list[Any] = "not_set" self.generator: Generator[Any, None, Any] | None = None - def add_frame_to_payload( - self, args: list[Any], frame: np.ndarray | None - ) -> list[Any]: - new_args = [] - for val in args: - if isinstance(val, str) and val == "__webrtc_value__": - new_args.append(frame) - else: - new_args.append(val) - return new_args - def array_to_frame(self, array: np.ndarray) -> VideoFrame: return VideoFrame.from_ndarray(array, format="bgr24") @@ -176,6 +262,25 @@ class ServerToClientAudio(AudioStreamTrack): self._start: float | None = None super().__init__() + def next(self) -> tuple[int, np.ndarray] | None: + import anyio + + if self.latest_args == "not_set": + return + if self.generator is None: + self.generator = self.event_handler(*self.latest_args) + if self.generator is not None: + try: + frame = next(self.generator) + return frame + except Exception as exc: + if isinstance(exc, StopIteration): + logger.debug("Stopping audio stream") + asyncio.run_coroutine_threadsafe( + self.queue.put(None), asyncio.get_event_loop() + ) + self.thread_quit.set() + def start(self): if self.__thread is None: self.__thread = threading.Thread( @@ -183,8 +288,7 @@ class ServerToClientAudio(AudioStreamTrack): target=player_worker_decode, args=( asyncio.get_event_loop(), - self.event_handler, - self, + self.next, self.queue, False, self.thread_quit, @@ -241,7 +345,7 @@ class WebRTC(Component): pcs: set[RTCPeerConnection] = set([]) relay = MediaRelay() connections: dict[ - str, VideoCallback | ServerToClientVideo | ServerToClientAudio + str, VideoCallback | ServerToClientVideo | ServerToClientAudio | AudioCallback ] = {} EVENTS = ["tick"] @@ -300,9 +404,6 @@ class WebRTC(Component): streaming: when used set as an output, takes video chunks yielded from the backend and combines them into one streaming video output. Each chunk should be a video file with a .ts extension using an h.264 encoding. Mp4 files are also accepted but they will be converted to h.264 encoding. watermark: an image file to be included as a watermark on the video. The image is not scaled and is displayed on the bottom right of the video. Valid formats for the image are: jpeg, png. """ - if modality == "audio" and mode == "send-receive": - raise ValueError("Audio modality is not supported in send-receive mode") - self.time_limit = time_limit self.height = height self.width = width @@ -358,7 +459,7 @@ class WebRTC(Component): def stream( self, - fn: Callable[..., Any] | None = None, + fn: Callable[..., Any] | StreamHandler | None = None, inputs: Block | Sequence[Block] | set[Block] | None = None, outputs: Block | Sequence[Block] | set[Block] | None = None, js: str | None = None, @@ -384,6 +485,15 @@ class WebRTC(Component): self.event_handler = fn self.time_limit = time_limit + if ( + self.mode == "send-receive" + and self.modality == "audio" + and not isinstance(self.event_handler, StreamHandler) + ): + raise ValueError( + "In the send-receive mode for audio, the event handler must be an instance of StreamHandler." + ) + if self.mode == "send-receive": if cast(list[Block], inputs)[0] != self: raise ValueError( @@ -439,7 +549,7 @@ class WebRTC(Component): @server async def offer(self, body): logger.debug("Starting to handle offer") - logger.debug("Offer body", body) + logger.debug("Offer body %s", body) if len(self.connections) >= cast(int, self.concurrency_limit): return {"status": "failed"} @@ -450,7 +560,7 @@ class WebRTC(Component): @pc.on("iceconnectionstatechange") async def on_iceconnectionstatechange(): - logger.debug("ICE connection state change", pc.iceConnectionState) + logger.debug("ICE connection state change %s", pc.iceConnectionState) if pc.iceConnectionState == "failed": await pc.close() self.connections.pop(body["webrtc_id"], None) @@ -468,12 +578,19 @@ class WebRTC(Component): @pc.on("track") def on_track(track): - cb = VideoCallback( - self.relay.subscribe(track), - event_handler=cast(Callable, self.event_handler), - ) + relay = MediaRelay() + if self.modality == "video": + cb = VideoCallback( + relay.subscribe(track), + event_handler=cast(Callable, self.event_handler), + ) + elif self.modality == "audio": + cb = AudioCallback( + relay.subscribe(track), + event_handler=cast(StreamHandler, self.event_handler), + ) self.connections[body["webrtc_id"]] = cb - logger.debug("Adding track to peer connection", cb) + logger.debug("Adding track to peer connection %s", cb) pc.addTrack(cb) if self.mode == "receive": @@ -482,7 +599,7 @@ class WebRTC(Component): elif self.modality == "audio": cb = ServerToClientAudio(cast(Callable, self.event_handler)) - logger.debug("Adding track to peer connection", cb) + logger.debug("Adding track to peer connection %s", cb) pc.addTrack(cb) self.connections[body["webrtc_id"]] = cb cb.on("ended", lambda: self.connections.pop(body["webrtc_id"], None)) diff --git a/demo/app.py b/demo/app.py index 3489fab..12e3204 100644 --- a/demo/app.py +++ b/demo/app.py @@ -1,72 +1,63 @@ +import logging + +# Configure the root logger to WARNING to suppress debug messages from other libraries +logging.basicConfig(level=logging.WARNING) + +# Create a console handler +console_handler = logging.StreamHandler() +console_handler.setLevel(logging.DEBUG) + +# Create a formatter +formatter = logging.Formatter("%(name)s - %(levelname)s - %(message)s") +console_handler.setFormatter(formatter) + +# Configure the logger for your specific library +logger = logging.getLogger("gradio_webrtc") +logger.setLevel(logging.DEBUG) +logger.addHandler(console_handler) + + import gradio as gr -import cv2 -from huggingface_hub import hf_hub_download -from gradio_webrtc import WebRTC -from twilio.rest import Client -import os -from inference import YOLOv10 - -model_file = hf_hub_download( - repo_id="onnx-community/yolov10n", filename="onnx/model.onnx" -) - -model = YOLOv10(model_file) - -account_sid = os.environ.get("TWILIO_ACCOUNT_SID") -auth_token = os.environ.get("TWILIO_AUTH_TOKEN") - -if account_sid and auth_token: - client = Client(account_sid, auth_token) - - token = client.tokens.create() - - rtc_configuration = { - "iceServers": token.ice_servers, - "iceTransportPolicy": "relay", - } -else: - rtc_configuration = None +import numpy as np +from gradio_webrtc import WebRTC, StreamHandler +from queue import Queue +import time -def detection(image, conf_threshold=0.3): - image = cv2.resize(image, (model.input_width, model.input_height)) - new_image = model.detect_objects(image, conf_threshold) - return cv2.resize(new_image, (500, 500)) +class EchoHandler(StreamHandler): + def __init__(self) -> None: + self.queue = Queue() + + def receive(self, frame: tuple[int, np.ndarray] | np.ndarray) -> None: + self.queue.put(frame) + + def emit(self) -> None: + return self.queue.get() css = """.my-group {max-width: 600px !important; max-height: 600 !important;} .my-column {display: flex !important; justify-content: center !important; align-items: center !important};""" -with gr.Blocks(css=css) as demo: +with gr.Blocks() as demo: gr.HTML( """

- YOLOv10 Webcam Stream (Powered by WebRTC ⚡️) + Audio Streaming (Powered by WebRTC ⚡️)

""" ) - gr.HTML( - """ -

- arXiv | github -

- """ - ) with gr.Column(elem_classes=["my-column"]): with gr.Group(elem_classes=["my-group"]): - image = WebRTC(label="Stream", rtc_configuration=rtc_configuration) - conf_threshold = gr.Slider( - label="Confidence Threshold", - minimum=0.0, - maximum=1.0, - step=0.05, - value=0.30, + audio = WebRTC( + label="Stream", + rtc_configuration=None, + mode="send-receive", + modality="audio", ) - image.stream( - fn=detection, inputs=[image, conf_threshold], outputs=[image], time_limit=10 - ) + audio.stream(fn=EchoHandler(), inputs=[audio], outputs=[audio], time_limit=15) + if __name__ == "__main__": demo.launch() diff --git a/demo/audio_out.py b/demo/audio_out.py index a66d41c..b2da4a8 100644 --- a/demo/audio_out.py +++ b/demo/audio_out.py @@ -6,7 +6,6 @@ import os from pydub import AudioSegment - account_sid = os.environ.get("TWILIO_ACCOUNT_SID") auth_token = os.environ.get("TWILIO_AUTH_TOKEN") @@ -24,10 +23,16 @@ else: import time + def generation(num_steps): for _ in range(num_steps): - segment = AudioSegment.from_file("/Users/freddy/sources/gradio/demo/audio_debugger/cantina.wav") - yield (segment.frame_rate, np.array(segment.get_array_of_samples()).reshape(1, -1)) + segment = AudioSegment.from_file( + "/Users/freddy/sources/gradio/demo/audio_debugger/cantina.wav" + ) + yield ( + segment.frame_rate, + np.array(segment.get_array_of_samples()).reshape(1, -1), + ) time.sleep(3.5) @@ -45,8 +50,12 @@ with gr.Blocks() as demo: ) with gr.Column(elem_classes=["my-column"]): with gr.Group(elem_classes=["my-group"]): - audio = WebRTC(label="Stream", rtc_configuration=rtc_configuration, - mode="receive", modality="audio") + audio = WebRTC( + label="Stream", + rtc_configuration=rtc_configuration, + mode="receive", + modality="audio", + ) num_steps = gr.Slider( label="Number of Steps", minimum=1, @@ -57,8 +66,7 @@ with gr.Blocks() as demo: button = gr.Button("Generate") audio.stream( - fn=generation, inputs=[num_steps], outputs=[audio], - trigger=button.click + fn=generation, inputs=[num_steps], outputs=[audio], trigger=button.click ) diff --git a/demo/audio_out_2.py b/demo/audio_out_2.py index ef43b6b..ec885b3 100644 --- a/demo/audio_out_2.py +++ b/demo/audio_out_2.py @@ -6,7 +6,6 @@ import os from pydub import AudioSegment - account_sid = os.environ.get("TWILIO_ACCOUNT_SID") auth_token = os.environ.get("TWILIO_AUTH_TOKEN") @@ -24,10 +23,16 @@ else: import time + def generation(num_steps): for _ in range(num_steps): - segment = AudioSegment.from_file("/Users/freddy/sources/gradio/demo/audio_debugger/cantina.wav") - yield (segment.frame_rate, np.array(segment.get_array_of_samples()).reshape(1, -1)) + segment = AudioSegment.from_file( + "/Users/freddy/sources/gradio/demo/audio_debugger/cantina.wav" + ) + yield ( + segment.frame_rate, + np.array(segment.get_array_of_samples()).reshape(1, -1), + ) time.sleep(3.5) @@ -48,9 +53,12 @@ with gr.Blocks() as demo: gr.Slider() with gr.Column(): # audio = gr.Audio(interactive=False) - audio = WebRTC(label="Stream", rtc_configuration=rtc_configuration, - mode="receive", modality="audio") - + audio = WebRTC( + label="Stream", + rtc_configuration=rtc_configuration, + mode="receive", + modality="audio", + ) if __name__ == "__main__": diff --git a/demo/space.py b/demo/space.py index a0a85f2..36a54de 100644 --- a/demo/space.py +++ b/demo/space.py @@ -1,26 +1,91 @@ - import gradio as gr import os -_docs = {'WebRTC': - {'description': 'Stream audio/video with WebRTC', - 'members': {'__init__': - { - 'rtc_configuration': {'type': 'dict[str, Any] | None', 'default': 'None', 'description': "The configration dictionary to pass to the RTCPeerConnection constructor. If None, the default configuration is used."}, - 'height': {'type': 'int | str | None', 'default': 'None', 'description': 'The height of the component, specified in pixels if a number is passed, or in CSS units if a string is passed. This has no effect on the preprocessed video file, but will affect the displayed video.'}, - 'width': {'type': 'int | str | None', 'default': 'None', 'description': 'The width of the component, specified in pixels if a number is passed, or in CSS units if a string is passed. This has no effect on the preprocessed video file, but will affect the displayed video.'}, - 'label': {'type': 'str | None', 'default': 'None', 'description': 'the label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.'}, - 'show_label': {'type': 'bool | None', 'default': 'None', 'description': 'if True, will display label.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'if True, will place the component in a container - providing some extra padding around the border.'}, - 'scale': {'type': 'int | None', 'default': 'None', 'description': 'relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.'}, - 'min_width': {'type': 'int', 'default': '160', 'description': 'minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.'}, - 'interactive': {'type': 'bool | None', 'default': 'None', 'description': 'if True, will allow users to upload a video; if False, can only be used to display videos. If not provided, this is inferred based on whether the component is used as an input or output.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'if False, component will be hidden.'}, - 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'an optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.'}, - 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'an optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.'}, - 'render': {'type': 'bool', 'default': 'True', 'description': 'if False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.'}, - 'key': {'type': 'int | str | None', 'default': 'None', 'description': 'if assigned, will be used to assume identity across a re-render. Components that have the same key across a re-render will have their value preserved.'}, - 'mirror_webcam': {'type': 'bool', 'default': 'True', 'description': 'if True webcam will be mirrored. Default is True.'}, - }, - 'events': {'tick': {'type': None, 'default': None, 'description': ''}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'WebRTC': []}}} +_docs = { + "WebRTC": { + "description": "Stream audio/video with WebRTC", + "members": { + "__init__": { + "rtc_configuration": { + "type": "dict[str, Any] | None", + "default": "None", + "description": "The configration dictionary to pass to the RTCPeerConnection constructor. If None, the default configuration is used.", + }, + "height": { + "type": "int | str | None", + "default": "None", + "description": "The height of the component, specified in pixels if a number is passed, or in CSS units if a string is passed. This has no effect on the preprocessed video file, but will affect the displayed video.", + }, + "width": { + "type": "int | str | None", + "default": "None", + "description": "The width of the component, specified in pixels if a number is passed, or in CSS units if a string is passed. This has no effect on the preprocessed video file, but will affect the displayed video.", + }, + "label": { + "type": "str | None", + "default": "None", + "description": "the label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.", + }, + "show_label": { + "type": "bool | None", + "default": "None", + "description": "if True, will display label.", + }, + "container": { + "type": "bool", + "default": "True", + "description": "if True, will place the component in a container - providing some extra padding around the border.", + }, + "scale": { + "type": "int | None", + "default": "None", + "description": "relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.", + }, + "min_width": { + "type": "int", + "default": "160", + "description": "minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.", + }, + "interactive": { + "type": "bool | None", + "default": "None", + "description": "if True, will allow users to upload a video; if False, can only be used to display videos. If not provided, this is inferred based on whether the component is used as an input or output.", + }, + "visible": { + "type": "bool", + "default": "True", + "description": "if False, component will be hidden.", + }, + "elem_id": { + "type": "str | None", + "default": "None", + "description": "an optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.", + }, + "elem_classes": { + "type": "list[str] | str | None", + "default": "None", + "description": "an optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.", + }, + "render": { + "type": "bool", + "default": "True", + "description": "if False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.", + }, + "key": { + "type": "int | str | None", + "default": "None", + "description": "if assigned, will be used to assume identity across a re-render. Components that have the same key across a re-render will have their value preserved.", + }, + "mirror_webcam": { + "type": "bool", + "default": "True", + "description": "if True webcam will be mirrored. Default is True.", + }, + }, + "events": {"tick": {"type": None, "default": None, "description": ""}}, + }, + "__meta__": {"additional_interfaces": {}, "user_fn_refs": {"WebRTC": []}}, + } } @@ -36,16 +101,19 @@ with gr.Blocks( ), ) as demo: gr.Markdown( -""" + """

Gradio WebRTC ⚡️

Static Badge Static Badge
-""", elem_classes=["md-custom"], header_links=True) +""", + elem_classes=["md-custom"], + header_links=True, + ) gr.Markdown( -""" + """ ## Installation ```bash @@ -195,17 +263,24 @@ with gr.Blocks() as demo: rtc = WebRTC(rtc_configuration=rtc_configuration, ...) ... ``` -""", elem_classes=["md-custom"], header_links=True) +""", + elem_classes=["md-custom"], + header_links=True, + ) - - gr.Markdown(""" + gr.Markdown( + """ ## -""", elem_classes=["md-custom"], header_links=True) +""", + elem_classes=["md-custom"], + header_links=True, + ) gr.ParamViewer(value=_docs["WebRTC"]["members"]["__init__"], linkify=[]) - - demo.load(None, js=r"""function() { + demo.load( + None, + js=r"""function() { const refs = {}; const user_fn_refs = { WebRTC: [], }; @@ -239,6 +314,7 @@ with gr.Blocks() as demo: }) } -""") +""", + ) demo.launch() diff --git a/demo/video_out.py b/demo/video_out.py index 082e193..298614d 100644 --- a/demo/video_out.py +++ b/demo/video_out.py @@ -24,7 +24,6 @@ else: def generation(input_video): cap = cv2.VideoCapture(input_video) - iterating = True while iterating: @@ -35,6 +34,7 @@ def generation(input_video): display_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) yield display_frame + with gr.Blocks() as demo: gr.HTML( """ @@ -47,11 +47,17 @@ with gr.Blocks() as demo: with gr.Column(): input_video = gr.Video(sources="upload") with gr.Column(): - output_video = WebRTC(label="Video Stream", rtc_configuration=rtc_configuration, - mode="receive", modality="video") + output_video = WebRTC( + label="Video Stream", + rtc_configuration=rtc_configuration, + mode="receive", + modality="video", + ) output_video.stream( - fn=generation, inputs=[input_video], outputs=[output_video], - trigger=input_video.upload + fn=generation, + inputs=[input_video], + outputs=[output_video], + trigger=input_video.upload, ) diff --git a/demo/video_out_stream.py b/demo/video_out_stream.py index 1aeb4d6..49461ed 100644 --- a/demo/video_out_stream.py +++ b/demo/video_out_stream.py @@ -30,7 +30,6 @@ def generation(): yield frame - with gr.Blocks() as demo: gr.HTML( """ @@ -39,12 +38,15 @@ with gr.Blocks() as demo: """ ) - output_video = WebRTC(label="Video Stream", rtc_configuration=rtc_configuration, - mode="receive", modality="video") + output_video = WebRTC( + label="Video Stream", + rtc_configuration=rtc_configuration, + mode="receive", + modality="video", + ) button = gr.Button("Start", variant="primary") output_video.stream( - fn=generation, inputs=None, outputs=[output_video], - trigger=button.click + fn=generation, inputs=None, outputs=[output_video], trigger=button.click ) diff --git a/frontend/Index.svelte b/frontend/Index.svelte index 4d14ea8..b3ba5db 100644 --- a/frontend/Index.svelte +++ b/frontend/Index.svelte @@ -7,6 +7,7 @@ import type { LoadingStatus } from "@gradio/statustracker"; import StaticVideo from "./shared/StaticVideo.svelte"; import StaticAudio from "./shared/StaticAudio.svelte"; + import InteractiveAudio from "./shared/InteractiveAudio.svelte"; export let elem_id = ""; export let elem_classes: string[] = []; @@ -37,8 +38,7 @@ $: console.log("value", value); -{#if mode == "receive" && modality === "video"} - gradio.dispatch("clear_status", loading_status)} /> + {#if mode == "receive" && modality === "video"} gradio.dispatch("tick")} on:error={({ detail }) => gradio.dispatch("error", detail)} /> - - -{:else if mode == "receive" && modality === "audio"} - - gradio.dispatch("clear_status", loading_status)} - /> + {:else if mode == "receive" && modality === "audio"} gradio.dispatch("tick")} on:error={({ detail }) => gradio.dispatch("error", detail)} /> - -{:else if mode === "send-receive" && modality === "video"} - - gradio.dispatch("clear_status", loading_status)} - /> + {:else if mode === "send-receive" && modality === "video"} - -{/if} + {:else if mode === "send-receive" && modality === "audio"} + gradio.dispatch("tick")} + on:error={({ detail }) => gradio.dispatch("error", detail)} + /> + {/if} + diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 6e7e181..bd606ac 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,15 +11,15 @@ "dependencies": { "@ffmpeg/ffmpeg": "^0.12.10", "@ffmpeg/util": "^0.12.1", - "@gradio/atoms": "0.9.0", - "@gradio/client": "1.6.0", + "@gradio/atoms": "0.9.2", + "@gradio/client": "1.7.0", "@gradio/icons": "0.8.0", - "@gradio/image": "0.16.0", - "@gradio/markdown": "^0.10.0", - "@gradio/statustracker": "0.8.0", - "@gradio/upload": "0.13.0", + "@gradio/image": "0.16.4", + "@gradio/markdown": "^0.10.3", + "@gradio/statustracker": "0.9.1", + "@gradio/upload": "0.13.3", "@gradio/utils": "0.7.0", - "@gradio/wasm": "0.14.0", + "@gradio/wasm": "0.14.2", "hls.js": "^1.5.16", "mrmime": "^2.0.0" }, @@ -49,30 +49,30 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", + "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", "dev": true, "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.25.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -82,13 +82,13 @@ } }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", + "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -120,6 +120,20 @@ "tough-cookie": "^4.1.4" } }, + "node_modules/@bundled-es-modules/tough-cookie/node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", @@ -538,11 +552,12 @@ } }, "node_modules/@gradio/atoms": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@gradio/atoms/-/atoms-0.9.0.tgz", - "integrity": "sha512-dIrMl4py7+1s1on52MwCeFq1p07IjbJWg3Y2vR+5FlwjQtQ3hPhP/KH+PrL94WchsUnF6aE2DV7LpjbnZvGtrQ==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@gradio/atoms/-/atoms-0.9.2.tgz", + "integrity": "sha512-P4+XXBl7S3JfmggMaFc/Ni9si9GtKMRE74HkG6C76HKJfszhnAV2/u/sS87+fe5NffU8CgS0R47FwxUSKMsm5g==", "dependencies": { "@gradio/icons": "^0.8.0", + "@gradio/markdown": "^0.10.3", "@gradio/utils": "^0.7.0" }, "peerDependencies": { @@ -550,9 +565,9 @@ } }, "node_modules/@gradio/client": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@gradio/client/-/client-1.6.0.tgz", - "integrity": "sha512-1258LcF45FFjGCjcn37zDZD1dRrsApTogc7fD9jlSBN8x61s0MPzz6LRCefD2DZ1Is3G+pRu7M6w6XrBNyVVmA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@gradio/client/-/client-1.7.0.tgz", + "integrity": "sha512-yRo7qU4zz8ZT61L1LFy+dSU5M0L6UzpMYWIdryHskvd4DbnhpXOj0LMYH/r1Snb61YBUJYIPOSzAJV1YP1Tkug==", "dependencies": { "@types/eventsource": "^1.1.15", "bufferutil": "^4.0.7", @@ -577,17 +592,17 @@ } }, "node_modules/@gradio/image": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@gradio/image/-/image-0.16.0.tgz", - "integrity": "sha512-FONnsxAvJPDGJ8DMFhMrdCiQkCP9m+9NoO3nh5I5mE26Q5bioN+Wdwu/IgQkJVbxo3iok8vu+R2J1jqqB0WM8A==", + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@gradio/image/-/image-0.16.4.tgz", + "integrity": "sha512-BKH3FHe/N/nyRww4/Gm9uSYfkFjmVQSQAZDq5ONpFNHAoOOA6+SjjWJq6yY1vM9SaAMkMQreLN0eugbOiQwwxw==", "dependencies": { - "@gradio/atoms": "^0.9.0", - "@gradio/client": "^1.6.0", + "@gradio/atoms": "^0.9.2", + "@gradio/client": "^1.7.0", "@gradio/icons": "^0.8.0", - "@gradio/statustracker": "^0.8.0", - "@gradio/upload": "^0.13.0", + "@gradio/statustracker": "^0.9.1", + "@gradio/upload": "^0.13.3", "@gradio/utils": "^0.7.0", - "@gradio/wasm": "^0.14.0", + "@gradio/wasm": "^0.14.2", "cropperjs": "^1.5.12", "lazy-brush": "^1.0.1", "resize-observer-polyfill": "^1.5.1" @@ -597,18 +612,18 @@ } }, "node_modules/@gradio/markdown": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@gradio/markdown/-/markdown-0.10.0.tgz", - "integrity": "sha512-ge2aoFWI+Fw/qQfwm1z9OwCBRBmHbOVdK9GSD/1EMURdMpTiYd9SiyaUk7OzJXFSpBxjRQEwejQQL+AjJ7X9KQ==", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@gradio/markdown/-/markdown-0.10.3.tgz", + "integrity": "sha512-qSywsn/tpnSL1kWPX3+SyeDoYke3y19mU9dxny7ZHn8gT3qdiYOY5Xgs1qcHXd7JEkJKsMkRdEMedziaFhwp1w==", "dependencies": { - "@gradio/atoms": "^0.9.0", + "@gradio/atoms": "^0.9.2", "@gradio/icons": "^0.8.0", - "@gradio/statustracker": "^0.8.0", + "@gradio/sanitize": "^0.1.1", + "@gradio/statustracker": "^0.9.1", "@gradio/utils": "^0.7.0", "@types/dompurify": "^3.0.2", "@types/katex": "^0.16.0", "@types/prismjs": "1.26.4", - "amuchina": "^1.0.12", "dom-parser": "^1.1.5", "github-slugger": "^2.0.0", "isomorphic-dompurify": "^2.14.0", @@ -616,8 +631,7 @@ "marked": "^12.0.0", "marked-gfm-heading-id": "^3.1.2", "marked-highlight": "^2.0.1", - "prismjs": "1.29.0", - "sanitize-html": "^2.13.0" + "prismjs": "1.29.0" }, "peerDependencies": { "svelte": "^4.0.0" @@ -679,12 +693,21 @@ "url": "https://opencollective.com/stylus" } }, - "node_modules/@gradio/statustracker": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@gradio/statustracker/-/statustracker-0.8.0.tgz", - "integrity": "sha512-qQqK03OWOiISJOOR8GTB+t3Ls/LonrtBiZWcTzH0FhmXlJUYGN/vRhgg0oc9ZpLuXutTbCvNcKEu+3PPKFIolA==", + "node_modules/@gradio/sanitize": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@gradio/sanitize/-/sanitize-0.1.1.tgz", + "integrity": "sha512-7OpCtsFSlAcpEQwRLrWvJVWJrvjrEL/eE4JzBc0PATm2rV5hbKbEHq42QqNubOyrvJTQN41u0B+nxQMrrGruLA==", "dependencies": { - "@gradio/atoms": "^0.9.0", + "amuchina": "^1.0.12", + "sanitize-html": "^2.13.0" + } + }, + "node_modules/@gradio/statustracker": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@gradio/statustracker/-/statustracker-0.9.1.tgz", + "integrity": "sha512-Iz36z1MrA22oCDgxHdUQFT8U+jkPYdGM1kbq+jaCMTbnSg9Y/+oppyBcUV7vBFUGcBgi6WV7KqxmMCK+whTfbw==", + "dependencies": { + "@gradio/atoms": "^0.9.2", "@gradio/icons": "^0.8.0", "@gradio/utils": "^0.7.0", "@types/dompurify": "^3.0.2", @@ -703,15 +726,15 @@ } }, "node_modules/@gradio/upload": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@gradio/upload/-/upload-0.13.0.tgz", - "integrity": "sha512-BMBlCWDxTrZ0rNYr2Gxolvlz1Zp+cEbAP1SVhL87g0y5/5A1dO1ZporBdPRcoST57P2ApvqZPpR1HyDAy+iKvA==", + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/@gradio/upload/-/upload-0.13.3.tgz", + "integrity": "sha512-ObL0vxWTghT07yWs2U1SQ5uILAKm9riZ5ys5dhn3kJZUsA7Pi55IUxcLA8NOIn2CnGHRKhHmyy8xe0UuTJ0qMw==", "dependencies": { - "@gradio/atoms": "^0.9.0", - "@gradio/client": "^1.6.0", + "@gradio/atoms": "^0.9.2", + "@gradio/client": "^1.7.0", "@gradio/icons": "^0.8.0", "@gradio/utils": "^0.7.0", - "@gradio/wasm": "^0.14.0" + "@gradio/wasm": "^0.14.2" }, "peerDependencies": { "svelte": "^4.0.0" @@ -727,9 +750,9 @@ } }, "node_modules/@gradio/wasm": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@gradio/wasm/-/wasm-0.14.0.tgz", - "integrity": "sha512-7APLdin+K5iriVnG79pfdl5wVb9whoVoe8i/Nio8d/zczKae+aN/HPkAqSEAgb2pJl7BqhfaQ4BzHkzr74F4NA==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@gradio/wasm/-/wasm-0.14.2.tgz", + "integrity": "sha512-oaGYQFvD5QFizoJbD/OJzURqBhWXGo/3QTXjh53cL6hlzxee4r2nREw8qHFCJ8kKAKfvuF/9cdBrJkEm9XqLeg==", "dependencies": { "@types/path-browserify": "^1.0.0", "path-browserify": "^1.0.1", @@ -785,9 +808,9 @@ } }, "node_modules/@inquirer/figures": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.6.tgz", - "integrity": "sha512-yfZzps3Cso2UbM7WlxKwZQh2Hs6plrbjs1QnzQDZhK2DgyCo6D8AaHps9olkNcUFlcYERMqU3uJSp1gmy3s/qQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.7.tgz", + "integrity": "sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw==", "engines": { "node": ">=18" } @@ -943,9 +966,9 @@ } }, "node_modules/@mswjs/interceptors": { - "version": "0.35.8", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.35.8.tgz", - "integrity": "sha512-PFfqpHplKa7KMdoQdj5td03uG05VK2Ng1dG0sP4pT9h0dGSX2v9txYt/AnrzPb/vAmfyBBC0NQV7VaBEX+efgQ==", + "version": "0.35.9", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.35.9.tgz", + "integrity": "sha512-SSnyl/4ni/2ViHKkiZb8eajA/eN1DNFaHjhGiLUdZvDz6PKF4COSf/17xqSz64nOo2Ia29SA6B2KNCsyCbVmaQ==", "dependencies": { "@open-draft/deferred-promise": "^2.2.0", "@open-draft/logger": "^0.3.0", @@ -986,6 +1009,279 @@ "esbuild": "^0.14.14" } }, + "node_modules/@parcel/watcher": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", + "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.4.1", + "@parcel/watcher-darwin-arm64": "2.4.1", + "@parcel/watcher-darwin-x64": "2.4.1", + "@parcel/watcher-freebsd-x64": "2.4.1", + "@parcel/watcher-linux-arm-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-musl": "2.4.1", + "@parcel/watcher-linux-x64-glibc": "2.4.1", + "@parcel/watcher-linux-x64-musl": "2.4.1", + "@parcel/watcher-win32-arm64": "2.4.1", + "@parcel/watcher-win32-ia32": "2.4.1", + "@parcel/watcher-win32-x64": "2.4.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", + "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", + "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", + "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", + "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", + "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", + "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", + "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", + "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", + "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", + "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", + "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz", + "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1040,9 +1336,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", "cpu": [ "arm" ], @@ -1053,9 +1349,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", "cpu": [ "arm64" ], @@ -1066,9 +1362,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", "cpu": [ "arm64" ], @@ -1079,9 +1375,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", "cpu": [ "x64" ], @@ -1092,9 +1388,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", "cpu": [ "arm" ], @@ -1105,9 +1401,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", "cpu": [ "arm" ], @@ -1118,9 +1414,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", "cpu": [ "arm64" ], @@ -1131,9 +1427,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", "cpu": [ "arm64" ], @@ -1144,9 +1440,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", "cpu": [ "ppc64" ], @@ -1157,9 +1453,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", "cpu": [ "riscv64" ], @@ -1170,9 +1466,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", "cpu": [ "s390x" ], @@ -1183,9 +1479,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", "cpu": [ "x64" ], @@ -1196,9 +1492,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", "cpu": [ "x64" ], @@ -1209,9 +1505,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", "cpu": [ "arm64" ], @@ -1222,9 +1518,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", "cpu": [ "ia32" ], @@ -1235,9 +1531,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", "cpu": [ "x64" ], @@ -1323,9 +1619,9 @@ } }, "node_modules/@types/node": { - "version": "22.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", - "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", + "version": "22.7.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz", + "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==", "dependencies": { "undici-types": "~6.19.2" } @@ -1528,6 +1824,18 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/buffer-crc32": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", @@ -1672,9 +1980,9 @@ } }, "node_modules/code-red/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "bin": { "acorn": "bin/acorn" }, @@ -1731,12 +2039,11 @@ } }, "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "engines": { - "node": ">= 6" + "node": ">= 12" } }, "node_modules/concat-map": { @@ -2548,6 +2855,18 @@ "resolved": "https://registry.npmjs.org/fetch-event-stream/-/fetch-event-stream-0.1.5.tgz", "integrity": "sha512-V1PWovkspxQfssq/NnxoEyQo1DV+MRK/laPuPblIZmSjMN8P5u46OhlFQznSr9p/t0Sp8Uc6SbM3yCMfr0KU8g==" }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -2565,9 +2884,9 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -2899,6 +3218,15 @@ "object-assign": "^4.1.1" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2907,11 +3235,32 @@ "node": ">=8" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-node-process": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==" }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -3036,17 +3385,6 @@ } } }, - "node_modules/jsdom/node_modules/tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/jstransformer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", @@ -3072,14 +3410,6 @@ "katex": "cli.js" } }, - "node_modules/katex/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "engines": { - "node": ">= 12" - } - }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -3348,9 +3678,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } @@ -3378,9 +3708,9 @@ } }, "node_modules/marked-highlight": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/marked-highlight/-/marked-highlight-2.1.4.tgz", - "integrity": "sha512-D1GOkcdzP+1dzjoColL7umojefFrASDuLeyaHS0Zr/Uo9jkr1V6vpLRCzfi1djmEaWyK0SYMFtHnpkZ+cwFT1w==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/marked-highlight/-/marked-highlight-2.2.0.tgz", + "integrity": "sha512-36LzwtVf7HEbbMITKU4j+iZuyWKgdXJfgYr4F5j27vs79oRPyApuBF3WkS5OsqO1+1lypWxztad7zNRM4qgXFw==", "peerDependencies": { "marked": ">=4 <15" } @@ -3408,6 +3738,19 @@ "node": ">=0.12" } }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -3500,9 +3843,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/msw": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.4.9.tgz", - "integrity": "sha512-1m8xccT6ipN4PTqLinPwmzhxQREuxaEJYdx4nIbggxP8aM7r1e71vE7RtOUSQoAm1LydjGfZKy7370XD/tsuYg==", + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.4.11.tgz", + "integrity": "sha512-TVEw9NOPTc6ufOQLJ53234S9NBRxQbu7xFMxs+OCP43JQcNEIOKiZHxEm2nDzYIrwccoIhUxUf8wr99SukD76A==", "hasInstallScript": true, "dependencies": { "@bundled-es-modules/cookie": "^2.0.0", @@ -3517,10 +3860,10 @@ "graphql": "^16.8.1", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", - "outvariant": "^1.4.2", + "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "strict-event-emitter": "^0.5.1", - "type-fest": "^4.9.0", + "type-fest": "^4.26.1", "yargs": "^17.7.2" }, "bin": { @@ -3582,6 +3925,12 @@ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true + }, "node_modules/node-gyp-build": { "version": "4.8.2", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", @@ -3621,9 +3970,9 @@ "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==" }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, "node_modules/parse-srcset": { @@ -3632,11 +3981,11 @@ "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==" }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", "dependencies": { - "entities": "^4.4.0" + "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -3711,9 +4060,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -3934,9 +4283,9 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "node_modules/readdirp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", - "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, "engines": { "node": ">= 14.16.0" @@ -3995,12 +4344,12 @@ } }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", "dev": true, "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -4010,31 +4359,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", @@ -4082,11 +4425,12 @@ } }, "node_modules/sass": { - "version": "1.79.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.3.tgz", - "integrity": "sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==", + "version": "1.80.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.1.tgz", + "integrity": "sha512-9lBwDZ7j3y/1DKj5Ec249EVGo5CVpwnzIyIj+cqlCjKkApLnzsJ/l9SnV4YnORvW9dQwQN+gQvh/mFZ8CnDs7Q==", "dev": true, "dependencies": { + "@parcel/watcher": "^2.4.1", "chokidar": "^4.0.0", "immutable": "^4.0.0", "source-map-js": ">=0.6.2 <2.0.0" @@ -4395,6 +4739,15 @@ "balanced-match": "^1.0.0" } }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/sucrase/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -4643,9 +4996,9 @@ } }, "node_modules/svelte/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "bin": { "acorn": "bin/acorn" }, @@ -4714,20 +5067,20 @@ } }, "node_modules/tldts": { - "version": "6.1.50", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", - "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", + "version": "6.1.52", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.52.tgz", + "integrity": "sha512-fgrDJXDjbAverY6XnIt0lNfv8A0cf7maTEaZxNykLGsLG7XP+5xhjBTrt/ieAsFjAlZ+G5nmXomLcZDkxXnDzw==", "dependencies": { - "tldts-core": "^6.1.50" + "tldts-core": "^6.1.52" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.50", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", - "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==" + "version": "6.1.52", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.52.tgz", + "integrity": "sha512-j4OxQI5rc1Ve/4m/9o2WhWSC4jGc4uVbCINdOEJRAraCi0YqTqgMcxUx7DbmuP0G3PCixoof/RZB0Q5Kh9tagw==" }, "node_modules/to-fast-properties": { "version": "2.0.0", @@ -4738,6 +5091,18 @@ "node": ">=4" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/token-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", @@ -4745,17 +5110,14 @@ "dev": true }, "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^6.1.32" }, "engines": { - "node": ">=6" + "node": ">=16" } }, "node_modules/tr46": { @@ -4776,9 +5138,9 @@ "dev": true }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==" }, "node_modules/type": { "version": "2.7.3", @@ -4797,9 +5159,9 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4831,9 +5193,9 @@ } }, "node_modules/vite": { - "version": "5.4.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", - "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==", + "version": "5.4.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz", + "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", "dev": true, "dependencies": { "esbuild": "^0.21.3", diff --git a/frontend/package.json b/frontend/package.json index bde834b..ea8bc24 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,15 +9,15 @@ "dependencies": { "@ffmpeg/ffmpeg": "^0.12.10", "@ffmpeg/util": "^0.12.1", - "@gradio/atoms": "0.9.0", - "@gradio/client": "1.6.0", + "@gradio/atoms": "0.9.2", + "@gradio/client": "1.7.0", "@gradio/icons": "0.8.0", - "@gradio/image": "0.16.0", - "@gradio/markdown": "^0.10.0", - "@gradio/statustracker": "0.8.0", - "@gradio/upload": "0.13.0", + "@gradio/image": "0.16.4", + "@gradio/markdown": "^0.10.3", + "@gradio/statustracker": "0.9.1", + "@gradio/upload": "0.13.3", "@gradio/utils": "0.7.0", - "@gradio/wasm": "0.14.0", + "@gradio/wasm": "0.14.2", "hls.js": "^1.5.16", "mrmime": "^2.0.0" }, diff --git a/frontend/shared/AudioWave.svelte b/frontend/shared/AudioWave.svelte index 4e94f98..8d8c19e 100644 --- a/frontend/shared/AudioWave.svelte +++ b/frontend/shared/AudioWave.svelte @@ -2,7 +2,7 @@ import { onMount, onDestroy } from 'svelte'; export let numBars = 16; - export let stream_state: "open" | "closed" = "closed"; + export let stream_state: "open" | "closed" | "waiting" = "closed"; export let audio_source: HTMLAudioElement; let audioContext: AudioContext; @@ -69,17 +69,12 @@
{/each} - \ No newline at end of file diff --git a/frontend/shared/InteractiveAudio.svelte b/frontend/shared/InteractiveAudio.svelte new file mode 100644 index 0000000..6f7f043 --- /dev/null +++ b/frontend/shared/InteractiveAudio.svelte @@ -0,0 +1,244 @@ + + + +
+
+ + \ No newline at end of file diff --git a/frontend/shared/InteractiveVideo.svelte b/frontend/shared/InteractiveVideo.svelte index d74480b..9239a7c 100644 --- a/frontend/shared/InteractiveVideo.svelte +++ b/frontend/shared/InteractiveVideo.svelte @@ -62,22 +62,6 @@