Skip to content

Commit a7e5216

Browse files
committed
avoid comms
1 parent d936de4 commit a7e5216

File tree

3 files changed

+31
-68
lines changed

3 files changed

+31
-68
lines changed

livekit-rtc/jupyter-html/src/App.tsx

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useState } from 'react';
22
import {
33
LiveKitRoom,
44
BarVisualizer,
@@ -15,46 +15,16 @@ import type { SVGProps } from 'react';
1515
import { ConnectionState } from 'livekit-client';
1616

1717

18-
export async function fetchJoinInfo(): Promise<{ url: string; token: string }> {
19-
const invoke = (window as any).google?.colab?.kernel?.invokeFunction;
20-
if (invoke) {
21-
const res = await invoke("get_join_token", []);
22-
return res.data["application/json"];
23-
}
24-
25-
26-
// This requires that JupyterLab was started with --LabApp.expose_app_in_browser,
27-
if ((window as any).jupyterapp && (window as any).jupyterapp.shell) {
28-
const currentWidget = (window as any).jupyterapp.shell.currentWidget;
29-
if (currentWidget && currentWidget.context?.sessionContext) {
30-
const session = currentWidget.context.sessionContext.session;
31-
if (session && session.kernel) {
32-
try {
33-
const comm = session.kernel.createComm("get_join_token_comm");
34-
comm.open();
35-
comm.send({ request: "token" });
36-
return new Promise((resolve) => {
37-
comm.onMsg = (msg: any) => {
38-
resolve(msg.content.data);
39-
};
40-
});
41-
} catch (error) {
42-
throw new Error("Error creating comm channel: " + error);
43-
}
44-
}
45-
}
46-
}
47-
18+
export function getJoinInfo(): { url: string; token: string } {
4819
if (import.meta.env.MODE === "development") {
4920
const url = import.meta.env.VITE_LIVEKIT_URL;
5021
const token = import.meta.env.VITE_LIVEKIT_TOKEN;
5122
return { url, token };
5223
}
5324

54-
throw new Error("No suitable kernel connection available");
25+
return { url: "##livekit-url-placeholder##", token: "##livekit-token-placeholder##" };
5526
}
5627

57-
5828
const LeaveIcon = (props: SVGProps<SVGSVGElement>) => (
5929
<svg xmlns="http://www.w3.org/2000/svg" width={16} height={16} fill="none" {...props}>
6030
<path
@@ -107,20 +77,12 @@ const ConnectedContent: React.FC<{ onDisconnect: () => void }> = ({ onDisconnect
10777
};
10878

10979
const App = () => {
110-
const [joinInfo, setJoinInfo] = useState<{ url: string; token: string } | null>(null);
11180
const [error, setError] = useState<string | null>(null);
11281
const [isConnected, setIsConnected] = useState(true);
113-
114-
useEffect(() => {
115-
fetchJoinInfo()
116-
.then((info) => setJoinInfo(info))
117-
.catch((err) => setError(err.message));
118-
}, []);
82+
const joinInfo = getJoinInfo();
11983

12084
if (error) return <div>Error: {error}</div>;
12185

122-
if (!joinInfo) return <div>Loading...</div>;
123-
12486
if (!isConnected) {
12587
return (
12688
<div className="content">

livekit-rtc/livekit/rtc/jupyter.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,41 @@
1313

1414

1515
def room_html(url: str, token: str) -> HTML:
16-
IN_COLAB = "google.colab" in sys.modules
17-
IN_JUPYTER = "ipykernel" in sys.modules
18-
19-
if IN_COLAB:
20-
from google.colab import output
21-
22-
def get_join_token():
23-
return JSON({"url": url, "token": token})
24-
25-
output.register_callback("get_join_token", get_join_token)
26-
elif IN_JUPYTER:
27-
from IPython import get_ipython
28-
29-
ip = get_ipython()
30-
if ip and hasattr(ip, "kernel"):
16+
"""
17+
Generate the HTML needed to embed a LiveKit room.
3118
32-
def token_comm_target(comm, open_msg):
33-
@comm.on_msg
34-
def handle_message(msg):
35-
comm.send({"url": url, "token": token})
19+
Args:
20+
url (str): The LiveKit room URL.
21+
token (str): The LiveKit join token.
3622
37-
ip.kernel.comm_manager.register_target("get_join_token_comm", token_comm_target)
23+
Important:
24+
The returned HTML contains the provided `url` and `token` values directly.
25+
Avoid using sensitive tokens in public notebooks (e.g., tokens with long expiration times).
26+
"""
27+
token_placeholder = "##livekit-token-placeholder##"
28+
url_placeholder = "##livekit-url-placeholder##"
3829

3930
index_path = files("livekit.rtc.resources") / "jupyter-html" / "index.html"
4031
index_path = _resource_stack.enter_context(as_file(index_path))
41-
return HTML(index_path.read_text())
32+
33+
# turns out that directly replacing the URL/token is necessary, as Colab or Jupyter comms become
34+
# unreliable when the main thread is busy/blocked
35+
html_text = index_path.read_text()
36+
html_text = html_text.replace(token_placeholder, token)
37+
html_text = html_text.replace(url_placeholder, url)
38+
return HTML(html_text)
4239

4340

4441
def display_room(url: str, token: str) -> None:
4542
"""
46-
Display a LiveKit room in Jupyter or Google Colab.
43+
Display a LiveKit room in a Jupyter notebook or Google Colab.
4744
4845
Args:
4946
url (str): The LiveKit room URL.
5047
token (str): The LiveKit join token.
48+
49+
Important:
50+
The rendered HTML will include the provided `url` and `token` in plain text.
51+
Avoid using sensitive tokens in public notebooks (e.g., tokens with long expiration times).
5152
"""
5253
display(room_html(url, token))

livekit-rtc/livekit/rtc/resources/jupyter-html/index.html

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)