Skip to content

Commit 05bb92a

Browse files
committed
Refactor data-only-v2 to look good
1 parent c55d647 commit 05bb92a

File tree

2 files changed

+281
-46
lines changed

2 files changed

+281
-46
lines changed
Lines changed: 275 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,290 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta charset="utf-8" />
4+
<title>WebRTC Samples > Data Channel Only (TS v2)</title>
55
<meta name="viewport" content="width=device-width, initial-scale=1" />
6-
<title>webrtc-sdk data-only sample</title>
7-
<style> body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 16px; } </style>
6+
<meta charset="UTF-8" />
7+
<link
8+
rel="stylesheet"
9+
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
10+
/>
11+
<style>
12+
.jumbotron {
13+
text-align: center;
14+
padding: 2em;
15+
padding-top: 3em;
16+
}
17+
.header,
18+
.footer {
19+
padding: 15px;
20+
}
21+
.header {
22+
padding-bottom: 20px;
23+
}
24+
@media (min-width: 768px) {
25+
.container {
26+
max-width: 730px;
27+
}
28+
}
29+
#dataMessagesTextarea {
30+
font-size: 12px;
31+
background-color: #f8f9fa;
32+
}
33+
pre#log {
34+
text-align: left;
35+
max-height: 200px;
36+
overflow: auto;
37+
background: #f8f9fa;
38+
padding: 10px;
39+
font-size: 12px;
40+
margin-top: 20px;
41+
}
42+
</style>
843
</head>
44+
945
<body>
10-
<h2>Data-Only Publish (TS v2)</h2>
11-
<div>
12-
<input id="streamId" placeholder="stream id" />
13-
<button id="start">Start</button>
14-
<button id="stop" disabled>Stop</button>
46+
<div class="container">
47+
<div class="header clearfix">
48+
<div class="row">
49+
<h3 class="col text-muted">
50+
<a href="samples.html">WebRTC Samples</a> > Data Channel Only (TS v2)
51+
</h3>
52+
</div>
53+
</div>
54+
55+
<div class="jumbotron">
56+
<div class="alert alert-primary text-center" role="alert" style="margin-top: -2em">
57+
WebRTC Data Channel is an enterprise edition feature. <br />
58+
<a href="https://antmedia.io">Try Enterprise Edition for free at antmedia.io</a>
59+
</div>
60+
61+
<div class="form-group col-sm-12 text-left">
62+
<input
63+
type="text"
64+
class="form-control"
65+
id="streamName"
66+
placeholder="Type stream name"
67+
/>
68+
</div>
69+
70+
<div class="form-group col-sm-12 text-left">
71+
<label>Data Channel Messages</label>
72+
<textarea
73+
class="form-control"
74+
id="dataMessagesTextarea"
75+
rows="10"
76+
readonly
77+
></textarea>
78+
<div class="form-row mt-2">
79+
<div class="form-group col-sm-10">
80+
<input
81+
type="text"
82+
class="form-control"
83+
id="dataTextbox"
84+
placeholder="Write your message to send"
85+
/>
86+
</div>
87+
<div class="form-group col-sm-2">
88+
<button
89+
type="button"
90+
id="send"
91+
class="btn btn-outline-primary btn-block"
92+
disabled
93+
>
94+
Send
95+
</button>
96+
</div>
97+
</div>
98+
</div>
99+
100+
<div class="form-group col-sm-12 text-center" id="offlineInfo">
101+
<div class="form-group text-center" style="font-size: 1.2em">
102+
<span class="badge badge-secondary">Status: Offline</span>
103+
</div>
104+
</div>
105+
<div
106+
class="form-group col-sm-12 text-center"
107+
id="broadcastingInfo"
108+
style="display: none"
109+
>
110+
<div class="form-group text-center" style="margin-bottom: 8px; font-size: 1em;">
111+
<a href="" id="playlink" target="_blank">Join channel in a New Tab</a>
112+
</div>
113+
<div class="form-group text-center" style="font-size: 1.2em">
114+
<span class="badge badge-success" id="statusBadge">Status: Connected</span>
115+
</div>
116+
</div>
117+
118+
<div class="form-group">
119+
<button class="btn btn-primary" id="connect_channel_button">
120+
Join Channel
121+
</button>
122+
<button class="btn btn-primary" disabled id="disconnect_channel_button">
123+
Disconnect
124+
</button>
125+
</div>
126+
</div>
127+
128+
<pre id="log"></pre>
129+
130+
<footer class="footer text-left">
131+
<div class="row">
132+
<div class="col-sm-6 text-left">
133+
<a href="http://antmedia.io" target="_blank">antmedia.io</a>
134+
</div>
135+
<div class="col-sm-6 text-right">
136+
<span class="text-muted">Ant Media Server</span>
137+
</div>
138+
</div>
139+
</footer>
15140
</div>
16-
<fieldset style="margin-top:12px;">
17-
<legend>Data Channel</legend>
18-
<input id="dcText" placeholder="message" />
19-
<button id="sendText" disabled>Send Text</button>
20-
<button id="sendJSON" disabled>Send JSON</button>
21-
</fieldset>
22-
<pre id="log"></pre>
141+
142+
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
143+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
23144

24145
<script type="module">
25-
import { StreamingClient, getWebSocketURL, generateRandomString } from './js/index.js';
26-
const websocketURL = getWebSocketURL(window.location);
27-
const streamIdEl = document.getElementById('streamId');
28-
const startBtn = document.getElementById('start');
29-
const stopBtn = document.getElementById('stop');
30-
const dcText = document.getElementById('dcText');
31-
const sendTextBtn = document.getElementById('sendText');
32-
const sendJSONBtn = document.getElementById('sendJSON');
33-
const logEl = document.getElementById('log');
146+
import {
147+
StreamingClient,
148+
getWebSocketURL,
149+
generateRandomString,
150+
} from "./js/index.js";
151+
152+
const streamNameInput = document.getElementById("streamName");
153+
const connectBtn = document.getElementById("connect_channel_button");
154+
const disconnectBtn = document.getElementById("disconnect_channel_button");
155+
const sendBtn = document.getElementById("send");
156+
const dataTextbox = document.getElementById("dataTextbox");
157+
const messagesTextarea = document.getElementById("dataMessagesTextarea");
158+
const logEl = document.getElementById("log");
159+
const offlineInfo = document.getElementById("offlineInfo");
160+
const broadcastingInfo = document.getElementById("broadcastingInfo");
161+
const statusBadge = document.getElementById("statusBadge");
162+
const playlink = document.getElementById("playlink");
163+
34164
let client = null;
35-
let currentId = '';
36-
function log(m) { logEl.textContent += m + '\n'; }
165+
let currentId = "";
166+
let isPublisher = false;
167+
168+
function log(msg) {
169+
logEl.textContent += msg + "\n";
170+
logEl.scrollTop = logEl.scrollHeight;
171+
}
172+
173+
function appendMessage(msg) {
174+
messagesTextarea.value += msg + "\r\n";
175+
messagesTextarea.scrollTop = messagesTextarea.scrollHeight;
176+
}
37177

38-
startBtn.onclick = async () => {
39-
const id = streamIdEl.value.trim() || 'data_' + generateRandomString(6);
178+
const websocketURL = getWebSocketURL(window.location);
179+
180+
async function initClient() {
181+
if (!client) {
182+
client = new StreamingClient({
183+
websocketURL,
184+
onlyDataChannel: true,
185+
});
186+
187+
client.on("initialized", () => log("initialized"));
188+
client.on("data_channel_opened", () => {
189+
log("data channel opened");
190+
sendBtn.disabled = false;
191+
});
192+
client.on("data_channel_closed", () => {
193+
log("data channel closed");
194+
sendBtn.disabled = true;
195+
});
196+
client.on("data_received", ({ data }) => {
197+
const msg = typeof data === "string" ? data : data.byteLength + " bytes";
198+
log("dc <- " + msg);
199+
appendMessage("Received: " + msg);
200+
});
201+
client.on("publish_started", (o) => {
202+
log("publish_started " + o.streamId);
203+
isPublisher = true;
204+
updateStatus(true, "Connected (Publisher)");
205+
});
206+
client.on("play_started", (o) => {
207+
log("play_started " + o.streamId);
208+
isPublisher = false;
209+
updateStatus(true, "Connected (Player)");
210+
});
211+
client.on("publish_finished", () => updateStatus(false));
212+
client.on("play_finished", () => updateStatus(false));
213+
client.on("error", (e) => log("error: " + (e.error || e.message || e)));
214+
215+
await client.ready();
216+
}
217+
return client;
218+
}
219+
220+
function updateStatus(connected, text = "Connected") {
221+
if (connected) {
222+
offlineInfo.style.display = "none";
223+
broadcastingInfo.style.display = "block";
224+
statusBadge.textContent = "Status: " + text;
225+
connectBtn.disabled = true;
226+
disconnectBtn.disabled = false;
227+
playlink.href = window.location.pathname + "?id=" + currentId;
228+
} else {
229+
offlineInfo.style.display = "block";
230+
broadcastingInfo.style.display = "none";
231+
connectBtn.disabled = false;
232+
disconnectBtn.disabled = true;
233+
sendBtn.disabled = true;
234+
}
235+
}
236+
237+
connectBtn.onclick = async () => {
238+
const id = streamNameInput.value.trim() || "stream_" + generateRandomString(6);
239+
currentId = id;
240+
40241
try {
41-
const r = await StreamingClient.createSession({ websocketURL, role: 'publisher', streamId: id, onlyDataChannel: true });
42-
client = r.client; currentId = id; stopBtn.disabled = false;
43-
client.on('data_channel_opened', () => { sendTextBtn.disabled = false; sendJSONBtn.disabled = false; log('data channel opened'); });
44-
client.on('data_channel_closed', () => { sendTextBtn.disabled = true; sendJSONBtn.disabled = true; log('data channel closed'); });
45-
client.on('data_received', ({ data }) => log('dc <- ' + (typeof data === 'string' ? data : (data.byteLength + ' bytes'))));
46-
log('started data-only for ' + id);
47-
} catch(e) { log('start failed: ' + (e && e.message ? e.message : e)); }
242+
const sdk = await initClient();
243+
log("Attempting to join as player...");
244+
try {
245+
await sdk.join({ role: "player", streamId: id, timeoutMs: 5000 });
246+
} catch (e) {
247+
log("Join as player failed or timed out, attempting as publisher...");
248+
await sdk.join({ role: "publisher", streamId: id, timeoutMs: 5000 });
249+
}
250+
} catch (e) {
251+
log("Connection failed: " + (e.message || e));
252+
updateStatus(false);
253+
}
254+
};
255+
256+
disconnectBtn.onclick = () => {
257+
if (client && currentId) {
258+
client.stop(currentId);
259+
}
48260
};
49-
stopBtn.onclick = () => { if (client && currentId) { client.stop(currentId); stopBtn.disabled = true; } };
50-
sendTextBtn.onclick = async () => { if (client && currentId) { await client.sendData(currentId, dcText.value || 'hello'); log('dc -> ' + (dcText.value || 'hello')); } };
51-
sendJSONBtn.onclick = async () => { if (client && currentId) { await client.sendJSON(currentId, { hello: 'world' }); log('dc -> {"hello":"world"}'); } };
261+
262+
sendBtn.onclick = async () => {
263+
if (client && currentId) {
264+
const val = dataTextbox.value || "hello";
265+
try {
266+
await client.sendData(currentId, val);
267+
log("dc -> " + val);
268+
appendMessage("Sent: " + val);
269+
dataTextbox.value = "";
270+
} catch (e) {
271+
log("send failed: " + e.message);
272+
}
273+
}
274+
};
275+
276+
dataTextbox.onkeypress = (e) => {
277+
if (e.key === "Enter") sendBtn.click();
278+
};
279+
280+
// Set initial stream ID if present in URL
281+
const urlParams = new URLSearchParams(window.location.search);
282+
const idParam = urlParams.get("id") || urlParams.get("name");
283+
if (idParam) {
284+
streamNameInput.value = idParam;
285+
} else {
286+
streamNameInput.value = "stream1";
287+
}
52288
</script>
53289
</body>
54-
</html>
55-
290+
</html>

packages/webrtc-sdk/examples/play-v2.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,8 @@ <h3 class="col text-muted">
496496
adaptor.on('ice_connection_state_changed', ({ state }) => log('ice: ' + state));
497497
adaptor.on('reconnected', ({ streamId }) => log('reconnected ' + streamId));
498498
adaptor.on('error', (e) => log('error: ' + e.error));
499-
adaptor.on('data_channel_opened', () => { log('data channel opened'); sendTextBtn.disabled = false; sendFileBtn.disabled = false; });
500-
adaptor.on('data_channel_closed', () => { log('data channel closed'); sendTextBtn.disabled = true; sendFileBtn.disabled = true; });
499+
adaptor.on('data_channel_opened', () => { log('data channel opened'); sendTextBtn.disabled = false; sendFileBtn.disabled = false; });
500+
adaptor.on('data_channel_closed', () => { log('data channel closed'); sendTextBtn.disabled = true; sendFileBtn.disabled = true; });
501501

502502
adaptor.on('data_received', ({ data }) => {
503503
if (typeof data === 'string') {
@@ -734,10 +734,10 @@ <h3 class="col text-muted">
734734
};
735735

736736
stopBtn.onclick = () => { if (currentId) { adaptor.stop(currentId); stopBtn.disabled = true; } };
737-
optionsBtn.addEventListener("click", toggleOptions, false);
738-
sendTextBtn.onclick = sendData;
739-
sendFileBtn.onclick = () => sendFileInput.click();
740-
sendFileInput.addEventListener("change", send_image);
737+
optionsBtn.addEventListener("click", toggleOptions, false);
738+
sendTextBtn.onclick = sendData;
739+
sendFileBtn.onclick = () => sendFileInput.click();
740+
sendFileInput.addEventListener("change", send_image);
741741

742742
levelOn.onclick = async () => {
743743
if (!currentId) return;

0 commit comments

Comments
 (0)