mirror of
https://github.com/HumanAIGC-Engineering/gradio-webrtc.git
synced 2026-02-04 17:39:23 +08:00
@@ -1,149 +1,146 @@
|
||||
<script lang="ts">
|
||||
import { Empty } from "@gradio/atoms";
|
||||
import { BlockLabel } from "@gradio/atoms";
|
||||
import { Music } from "@gradio/icons";
|
||||
import type { I18nFormatter } from "@gradio/utils";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { onMount } from "svelte";
|
||||
import { Empty } from "@gradio/atoms";
|
||||
import { BlockLabel } from "@gradio/atoms";
|
||||
import { Music } from "@gradio/icons";
|
||||
import type { I18nFormatter } from "@gradio/utils";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import { start, stop } from "./webrtc_utils";
|
||||
import AudioWave from "./AudioWave.svelte";
|
||||
import { start, stop } from "./webrtc_utils";
|
||||
import AudioWave from "./AudioWave.svelte";
|
||||
|
||||
export let value: string | null = null;
|
||||
export let label: string | undefined = undefined;
|
||||
export let show_label = true;
|
||||
export let rtc_configuration: Object | null = null;
|
||||
export let i18n: I18nFormatter;
|
||||
export let on_change_cb: (msg: "change" | "tick") => void;
|
||||
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 value: string | null = null;
|
||||
export let label: string | undefined = undefined;
|
||||
export let show_label = true;
|
||||
export let rtc_configuration: Object | null = null;
|
||||
export let i18n: I18nFormatter;
|
||||
export let on_change_cb: (msg: "change" | "tick") => void;
|
||||
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>;
|
||||
};
|
||||
export let server: {
|
||||
offer: (body: any) => Promise<any>;
|
||||
};
|
||||
|
||||
let stream_state: "open" | "closed" | "waiting" = "closed";
|
||||
let audio_player: HTMLAudioElement;
|
||||
let pc: RTCPeerConnection;
|
||||
let _webrtc_id = Math.random().toString(36).substring(2);
|
||||
let stream_state: "open" | "closed" | "waiting" = "closed";
|
||||
let audio_player: HTMLAudioElement;
|
||||
let pc: RTCPeerConnection;
|
||||
let _webrtc_id = Math.random().toString(36).substring(2);
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
tick: undefined;
|
||||
error: string;
|
||||
play: undefined;
|
||||
stop: undefined;
|
||||
}>();
|
||||
const dispatch = createEventDispatcher<{
|
||||
tick: undefined;
|
||||
error: string;
|
||||
play: undefined;
|
||||
stop: undefined;
|
||||
}>();
|
||||
|
||||
async function start_stream(value: string): Promise<string> {
|
||||
if (value === "start_webrtc_stream") {
|
||||
stream_state = "waiting";
|
||||
_webrtc_id = Math.random().toString(36).substring(2);
|
||||
value = _webrtc_id;
|
||||
pc = new RTCPeerConnection(rtc_configuration);
|
||||
pc.addEventListener("connectionstatechange", async (event) => {
|
||||
switch (pc.connectionState) {
|
||||
case "connected":
|
||||
console.info("connected");
|
||||
stream_state = "open";
|
||||
dispatch("tick");
|
||||
break;
|
||||
case "disconnected":
|
||||
console.info("closed");
|
||||
stop(pc);
|
||||
break;
|
||||
case "failed":
|
||||
stream_state = "closed";
|
||||
dispatch("error", "Connection failed!");
|
||||
stop(pc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
let stream = null;
|
||||
const timeoutId = setTimeout(() => {
|
||||
// @ts-ignore
|
||||
on_change_cb({ type: "connection_timeout" });
|
||||
}, 5000);
|
||||
|
||||
start(
|
||||
stream,
|
||||
pc,
|
||||
audio_player,
|
||||
server.offer,
|
||||
_webrtc_id,
|
||||
"audio",
|
||||
on_change_cb,
|
||||
)
|
||||
.then((connection) => {
|
||||
clearTimeout(timeoutId);
|
||||
pc = connection;
|
||||
})
|
||||
.catch(() => {
|
||||
clearTimeout(timeoutId);
|
||||
console.info("catching");
|
||||
dispatch(
|
||||
"error",
|
||||
"Too many concurrent users. Come back later!",
|
||||
);
|
||||
});
|
||||
async function start_stream(value: string): Promise<string> {
|
||||
if (value === "start_webrtc_stream") {
|
||||
stream_state = "waiting";
|
||||
_webrtc_id = Math.random().toString(36).substring(2);
|
||||
value = _webrtc_id;
|
||||
pc = new RTCPeerConnection(rtc_configuration);
|
||||
pc.addEventListener("connectionstatechange", async (event) => {
|
||||
switch (pc.connectionState) {
|
||||
case "connected":
|
||||
console.info("connected");
|
||||
stream_state = "open";
|
||||
dispatch("tick");
|
||||
break;
|
||||
case "disconnected":
|
||||
console.info("closed");
|
||||
stop(pc);
|
||||
break;
|
||||
case "failed":
|
||||
stream_state = "closed";
|
||||
dispatch("error", "Connection failed!");
|
||||
stop(pc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
});
|
||||
let stream = null;
|
||||
const timeoutId = setTimeout(() => {
|
||||
// @ts-ignore
|
||||
on_change_cb({ type: "connection_timeout" });
|
||||
}, 5000);
|
||||
|
||||
$: start_stream(value).then((val) => {
|
||||
value = val;
|
||||
});
|
||||
start(
|
||||
stream,
|
||||
pc,
|
||||
audio_player,
|
||||
server.offer,
|
||||
_webrtc_id,
|
||||
"audio",
|
||||
on_change_cb,
|
||||
)
|
||||
.then((connection) => {
|
||||
clearTimeout(timeoutId);
|
||||
pc = connection;
|
||||
})
|
||||
.catch(() => {
|
||||
clearTimeout(timeoutId);
|
||||
console.info("catching");
|
||||
dispatch("error", "Too many concurrent users. Come back later!");
|
||||
});
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
$: start_stream(value).then((val) => {
|
||||
value = val;
|
||||
});
|
||||
</script>
|
||||
|
||||
<BlockLabel
|
||||
{show_label}
|
||||
Icon={Music}
|
||||
float={false}
|
||||
label={label || i18n("audio.audio")}
|
||||
{show_label}
|
||||
Icon={Music}
|
||||
float={false}
|
||||
label={label || i18n("audio.audio")}
|
||||
/>
|
||||
<audio
|
||||
class="standard-player"
|
||||
class:hidden={true}
|
||||
on:load
|
||||
bind:this={audio_player}
|
||||
on:ended={() => dispatch("stop")}
|
||||
on:play={() => dispatch("play")}
|
||||
class="standard-player"
|
||||
class:hidden={true}
|
||||
on:load
|
||||
bind:this={audio_player}
|
||||
on:ended={() => dispatch("stop")}
|
||||
on:play={() => dispatch("play")}
|
||||
/>
|
||||
{#if value !== "__webrtc_value__"}
|
||||
<div class="audio-container">
|
||||
<AudioWave
|
||||
audio_source_callback={() => audio_player.srcObject}
|
||||
{stream_state}
|
||||
{icon}
|
||||
{icon_button_color}
|
||||
{pulse_color}
|
||||
{icon_radius}
|
||||
/>
|
||||
</div>
|
||||
<div class="audio-container">
|
||||
<AudioWave
|
||||
audio_source_callback={() => audio_player.srcObject}
|
||||
{stream_state}
|
||||
{icon}
|
||||
{icon_button_color}
|
||||
{pulse_color}
|
||||
{icon_radius}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{#if value === "__webrtc_value__"}
|
||||
<Empty size="small">
|
||||
<Music />
|
||||
</Empty>
|
||||
<Empty size="small">
|
||||
<Music />
|
||||
</Empty>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.audio-container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.audio-container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.standard-player {
|
||||
width: 100%;
|
||||
}
|
||||
.standard-player {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user