Set border radius (#84)

Co-authored-by: Freddy Boulton <freddyboulton@hf-freddy.local>
This commit is contained in:
Freddy Boulton
2025-02-26 11:53:25 -05:00
committed by GitHub
parent c6769fe33f
commit da872627b9
13 changed files with 51 additions and 17 deletions

3
.gitignore vendored
View File

@@ -17,4 +17,5 @@ demo/scratch
.vscode
.DS_Store
test/
.venv*
.venv*
.env

View File

@@ -42,6 +42,8 @@ class UIArgs(TypedDict):
"""Color of the icon button. Default is var(--color-accent) of the demo theme."""
pulse_color: NotRequired[str]
"""Color of the pulse animation. Default is var(--color-accent) of the demo theme."""
icon_radius: NotRequired[int]
"""Border radius of the icon button expressed as a percentage of the button size. Default is 50%."""
class Stream(WebRTCConnectionMixin):
@@ -322,6 +324,7 @@ class Stream(WebRTCConnectionMixin):
icon=ui_args.get("icon"),
icon_button_color=ui_args.get("icon_button_color"),
pulse_color=ui_args.get("pulse_color"),
icon_radius=ui_args.get("icon_radius"),
)
for component in additional_output_components:
if component not in same_components:
@@ -358,6 +361,10 @@ class Stream(WebRTCConnectionMixin):
rtc_configuration=self.rtc_configuration,
mode="send-receive",
modality="audio",
icon=ui_args.get("icon"),
icon_button_color=ui_args.get("icon_button_color"),
pulse_color=ui_args.get("pulse_color"),
icon_radius=ui_args.get("icon_radius"),
)
for component in additional_input_components:
if component not in same_components:
@@ -400,6 +407,7 @@ class Stream(WebRTCConnectionMixin):
icon=ui_args.get("icon"),
icon_button_color=ui_args.get("icon_button_color"),
pulse_color=ui_args.get("pulse_color"),
icon_radius=ui_args.get("icon_radius"),
)
for component in additional_input_components:
if component not in same_components:
@@ -443,6 +451,7 @@ class Stream(WebRTCConnectionMixin):
icon=ui_args.get("icon"),
icon_button_color=ui_args.get("icon_button_color"),
pulse_color=ui_args.get("pulse_color"),
icon_radius=ui_args.get("icon_radius"),
)
for component in additional_input_components:
if component not in same_components:
@@ -552,6 +561,7 @@ class Stream(WebRTCConnectionMixin):
port: int = 8000,
**kwargs,
):
import atexit
import secrets
import threading
import time
@@ -563,7 +573,6 @@ class Stream(WebRTCConnectionMixin):
from gradio.networking import setup_tunnel
from gradio.tunneling import CURRENT_TUNNELS
from huggingface_hub import get_token
import atexit
app = FastAPI()

View File

@@ -1,14 +1,15 @@
import asyncio
import fractions
import functools
import inspect
import io
import json
import logging
import tempfile
import traceback
from contextvars import ContextVar
from typing import Any, Callable, Literal, Protocol, TypedDict, cast
import functools
import traceback
import inspect
import av
import numpy as np
from numpy.typing import NDArray

View File

@@ -87,6 +87,7 @@ class WebRTC(Component, WebRTCConnectionMixin):
icon: str | None = None,
icon_button_color: str | None = None,
pulse_color: str | None = None,
icon_radius: int | None = None,
button_labels: dict | None = None,
):
"""
@@ -119,6 +120,7 @@ class WebRTC(Component, WebRTCConnectionMixin):
icon_button_color: Color of the icon button. Default is var(--color-accent) of the demo theme.
pulse_color: Color of the pulse animation. Default is var(--color-accent) of the demo theme.
button_labels: Text to display on the audio or video start, stop, waiting buttons. Dict with keys "start", "stop", "waiting" mapping to the text to display on the buttons.
icon_radius: Border radius of the icon button expressed as a percentage of the button size. Default is 50%
"""
self.time_limit = time_limit
self.height = height
@@ -129,6 +131,7 @@ class WebRTC(Component, WebRTCConnectionMixin):
self.mode = mode
self.modality = modality
self.icon_button_color = icon_button_color
self.icon_radius = icon_radius
self.pulse_color = pulse_color
self.rtp_params = rtp_params or {}
self.button_labels = {

View File

@@ -149,14 +149,14 @@ class WebRTCConnectionMixin:
if isinstance(self.event_handler, StreamHandlerBase):
handler = self.event_handler.copy()
handler.emit = webrtc_error_handler(handler.emit)
handler.receive = webrtc_error_handler(handler.receive)
handler.start_up = webrtc_error_handler(handler.start_up)
handler.shutdown = webrtc_error_handler(handler.shutdown)
handler.emit = webrtc_error_handler(handler.emit) # type: ignore
handler.receive = webrtc_error_handler(handler.receive) # type: ignore
handler.start_up = webrtc_error_handler(handler.start_up) # type: ignore
handler.shutdown = webrtc_error_handler(handler.shutdown) # type: ignore
if hasattr(handler, "video_receive"):
handler.video_receive = webrtc_error_handler(handler.video_receive)
handler.video_receive = webrtc_error_handler(handler.video_receive) # type: ignore
if hasattr(handler, "video_emit"):
handler.video_emit = webrtc_error_handler(handler.video_emit)
handler.video_emit = webrtc_error_handler(handler.video_emit) # type: ignore
else:
handler = webrtc_error_handler(cast(Callable, self.event_handler))

View File

@@ -5,16 +5,16 @@ import time
from io import BytesIO
import gradio as gr
from gradio.utils import get_space
import numpy as np
from google import genai
from dotenv import load_dotenv
from fastrtc import (
AsyncAudioVideoStreamHandler,
Stream,
get_twilio_turn_credentials,
WebRTC,
get_twilio_turn_credentials,
)
from google import genai
from gradio.utils import get_space
from PIL import Image
load_dotenv()

View File

@@ -38,6 +38,7 @@
export let icon: string | undefined = undefined;
export let icon_button_color: string = "var(--color-accent)";
export let pulse_color: string = "var(--color-accent)";
export let icon_radius: number = 50;
const on_change_cb = (msg: "change" | "tick" | any) => {
if (
@@ -124,6 +125,7 @@
{icon}
{icon_button_color}
{pulse_color}
{icon_radius}
i18n={gradio.i18n}
on:tick={() => gradio.dispatch("tick")}
on:error={({ detail }) => gradio.dispatch("error", detail)}
@@ -178,6 +180,7 @@
{icon}
{reject_cb}
{icon_button_color}
{icon_radius}
{pulse_color}
{button_labels}
on:tick={() => gradio.dispatch("tick")}

View File

@@ -11,6 +11,7 @@
export let icon_button_color: string = "var(--color-accent)";
export let pulse_color: string = "var(--color-accent)";
export let pending: boolean = false;
export let icon_radius: number = 50;
let audioContext: AudioContext;
let analyser: AnalyserNode;
@@ -34,6 +35,7 @@
});
function setupAudioContext() {
// @ts-ignore
audioContext = new (window.AudioContext || window.webkitAudioContext)();
analyser = audioContext.createAnalyser();
const source = audioContext.createMediaStreamSource(
@@ -58,6 +60,7 @@
);
for (let i = 0; i < bars.length; i++) {
const barHeight = (dataArray[i] / 255) * 2;
// @ts-ignore
bars[i].style.transform = `scaleY(${Math.max(0.1, barHeight)})`;
}
@@ -78,6 +81,7 @@
{pulse_color}
{icon}
{icon_button_color}
{icon_radius}
{audio_source_callback}
/>
</div>

View File

@@ -33,6 +33,7 @@
export let icon: string | undefined = undefined;
export let icon_button_color: string = "var(--color-accent)";
export let pulse_color: string = "var(--color-accent)";
export let icon_radius: number = 50;
export let button_labels: { start: string; stop: string; waiting: string };
let pending = false;
@@ -291,6 +292,7 @@
{icon_button_color}
{pulse_color}
{pending}
{icon_radius}
/>
<StreamingBar time_limit={_time_limit} />
<div class="button-wrap" class:pulse={stopword_recognized}>

View File

@@ -63,6 +63,7 @@
{icon_button_color}
{pulse_color}
{button_labels}
{icon_radius}
on:error
on:start_recording
on:stop_recording

View File

@@ -7,6 +7,7 @@
export let icon: string | ComponentType = undefined;
export let icon_button_color: string = "var(--color-accent)";
export let pulse_color: string = "var(--color-accent)";
export let icon_radius: number = 50;
let audioContext: AudioContext;
let analyser: AnalyserNode;
@@ -27,6 +28,7 @@
});
function setupAudioContext() {
// @ts-ignore
audioContext = new (window.AudioContext || window.webkitAudioContext)();
analyser = audioContext.createAnalyser();
const source = audioContext.createMediaStreamSource(
@@ -77,7 +79,12 @@
style:background={icon_button_color}
>
{#if typeof icon === "string"}
<img src={icon} alt="Audio visualization icon" class="icon-image" />
<img
src={icon}
alt="Audio visualization icon"
class="icon-image"
style:border-radius={`${icon_radius}%`}
/>
{:else if icon === undefined}
<div></div>
{:else}
@@ -123,7 +130,6 @@
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 50%;
}
.pulse-ring {

View File

@@ -18,6 +18,7 @@
export let icon: string | undefined = undefined;
export let icon_button_color: string = "var(--color-accent)";
export let pulse_color: string = "var(--color-accent)";
export let icon_radius: number = 50;
export let server: {
offer: (body: any) => Promise<any>;
@@ -65,6 +66,7 @@
});
let stream = null;
const timeoutId = setTimeout(() => {
// @ts-ignore
on_change_cb({ type: "connection_timeout" });
}, 5000);
@@ -120,6 +122,7 @@
{icon}
{icon_button_color}
{pulse_color}
{icon_radius}
/>
</div>
{/if}

View File

@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
[project]
name = "fastrtc"
version = "0.0.5.post2"
version = "0.0.6"
description = "The realtime communication library for Python"
readme = "README.md"
license = "apache-2.0"
@@ -83,3 +83,4 @@ packages = ["/backend/fastrtc"]
[tool.ruff]
target-version = "py310"
extend-exclude = ["demo/phonic_chat"]