DataChannel
DataChannel.js is a JavaScript library useful to write many-to-many i.e. group file/data sharing or text chat applications. Its syntax is easier to use and understand. It highly simplifies complex tasks like any or all user rejection/ejection; direct messages delivery; and more.
Install / Use
/learn @muaz-khan/DataChannelREADME
DataChannel.js : A JavaScript wrapper library for RTCDataChannel APIs / Demos
npm install datachannel
# or
bower install datachannel
DataChannel.js is a JavaScript library useful to write many-to-many i.e. group file/data sharing or text chat applications. Its syntax is easier to use and understand. It highly simplifies complex tasks like any or all user rejection/ejection; direct messages delivery; and more.
If you want all DataChannel.js functionalities along with media streaming and runtime additions/deletions then RTCMultiConnection.js is a good chose with similar APIs/syntax.
Features
- Direct messages — to any user using their
user-id - Eject/Reject any user — using their
user-id - Leave any room (i.e. data session) or close entire session using
leavemethod - File size is limitless!
- Text message length is limitless!
- Size of data is also limitless!
- Fallback to socket.io/websockets/etc.
- Users' presence detection using
onleave - Latency detection
- Multi-longest strings/files concurrent
- File queue support added. Previously shared files will be auto transmitted to each new peer.
Demos using DataChannel.js
- DataChannel basic demo
- Auto Session Establishment and Users presence detection
- Text Chat using Pusher and DataChannel.js
Try a Quick Demo (Text Chat)
<script src="//cdn.webrtc-experiment.com/DataChannel.js"> </script>
<button id="setup-datachannel" style="width:30%;">Open NEW DataChannel</button>
<input type="text" id="chat-input" disabled style="font-size: 2em; width: 65%;"><br />
<div id="chat-output"></div>
<script>
var chatOutput = document.getElementById('chat-output');
var chatInput = document.getElementById('chat-input');
chatInput.onkeypress = function (e) {
if (e.keyCode != 13) return;
channel.send(this.value);
chatOutput.innerHTML = 'Me: ' + this.value + '<hr />' + chatOutput.innerHTML;
this.value = '';
};
var channel = new DataChannel();
channel.onopen = function (userid) {
chatInput.disabled = false;
chatInput.value = 'Hi, ' + userid;
chatInput.focus();
};
channel.onmessage = function (message, userid) {
chatOutput.innerHTML = userid + ': ' + message + '<hr />' + chatOutput.innerHTML;
};
channel.onleave = function (userid) {
chatOutput.innerHTML = userid + ' Left.<hr />' + chatOutput.innerHTML;
};
// search for existing data channels
channel.connect();
document.querySelector('button#setup-datachannel').onclick = function () {
// setup new data channel
channel.open();
};
</script>
First Step: Link the library
<script src="//cdn.webrtc-experiment.com/DataChannel.js"></script>
Last Step: Start using it!
var channel = new DataChannel('[optional] channel-name');
channel.send(file || data || 'text-message');
open/connect data channels
// to create/open a new channel
channel.open('channel-name');
// if someone already created a channel; to join it: use "connect" method
channel.connect('channel-name');
onopen and onmessage
If you're familiar with WebSockets; these two methods works in the exact same way:
channel.onopen = function(userid) { }
channel.onmessage = function(message, userid, latency) { }
user-ids can be used to send direct messages or to eject/leave any user:
ondatachannel
Allows you show list of all available data channels to the user; and let him choose which one to join:
channel.ondatachannel = function(data_channel) {
channel.join(data_channel);
// or
channel.join({
id: data_channel.id,
owner: data_channel.owner
});
// id: unique identifier for the session
// owner: unique identifier for the session initiator
};
Use custom user-ids
channel.userid = 'predefined-userid';
Remember; custom defined user-id must be unique username.
Direct messages
channel.channels[userid].send(file || data || 'text message');
Eject/Reject users using their user-ids
channel.eject(userid); // throw a user out of your room!
Close/Leave the entire room
channel.leave(); // close your own entire data session
Detect users' presence
channel.onleave = function(userid) { };
Auto Close Entire Session
When room initiator leaves; you can enforce auto-closing of the entire session. By default: it is false:
channel.autoCloseEntireSession = true;
It means that session will be kept active all the time; even if initiator leaves the session.
You can set autoCloseEntireSession before calling leave method; which will enforce closing of the entire session:
channel.autoCloseEntireSession = true;
channel.leave(); // closing entire session
uuid for files
You can get uuid for each file (being sent) like this:
channel.send(file);
var uuid = file.uuid; // "file"-Dot-uuid
To Share files
var progressHelper = {};
// to make sure file-saver dialog is not invoked.
channel.autoSaveToDisk = false;
channel.onFileProgress = function (chunk, uuid) {
var helper = progressHelper[chunk.uuid];
helper.progress.value = chunk.currentPosition || chunk.maxChunks || helper.progress.max;
updateLabel(helper.progress, helper.label);
};
channel.onFileStart = function (file) {
var div = document.createElement('div');
div.title = file.name;
div.innerHTML = '<label>0%</label> <progress></progress>';
appendDIV(div, fileProgress);
progressHelper[file.uuid] = {
div: div,
progress: div.querySelector('progress'),
label: div.querySelector('label')
};
progressHelper[file.uuid].progress.max = file.maxChunks;
};
channel.onFileSent = function (file) {
progressHelper[file.uuid].div.innerHTML = '<a href="' + file.url + '" target="_blank" download="' + file.name + '">' + file.name + '</a>';
};
channel.onFileReceived = function (fileName, file) {
progressHelper[file.uuid].div.innerHTML = '<a href="' + file.url + '" target="_blank" download="' + file.name + '">' + file.name + '</a>';
};
function updateLabel(progress, label) {
if (progress.position == -1) return;
var position = +progress.position.toFixed(2).split('.')[1] || 100;
label.innerHTML = position + '%';
}
File Queue
File Queue support added to make sure newly connected users gets all previously shared files.
You can see list of previously shared files:
console.log( channel.fileQueue );
Auto-Save file to Disk
By default; autoSaveToDisk is set to true. When it is true; it will save file to disk as soon as it is received. To prevent auto-saving feature; just set it false:
channel.autoSaveToDisk = false; // prevent auto-saving!
channel.onFileReceived = function (fileName, file) {
// file.url
// file.uuid
hyperlink.href = file.url;
};
Latency Detection
channel.onmessage = function(message, userid, latency) {
console.log('latency:', latency, 'milliseconds');
};
Concurrent Transmission
You can send multiple files concurrently; or multiple longer text messages:
// individually
channel.send(fileNumber1);
channel.send(fileNumber2);
channel.send(fileNumber3);
// or as an array
channel.send([fileNumber1, fileNumber2, fileNumber3]);
channel.send('longer string-1');
channel.send('longer string-2');
channel.send('longer string-3');
Errors Handling
// error to open data ports
channel.onerror = function(event) {}
// data ports suddenly dropped
channel.onclose = function(event) {}
Data session direction
Default direction is many-to-many.
channel.direction = 'one-to-one';
channel.direction = 'one-to-many';
channel.direction = 'many-to-many';
=
For signaling; please check following page:
https://github.com/muaz-khan/WebRTC-Experiment/blob/master/Signaling.md
Remember, you can use any signaling implementation that exists out there without modifying any single line! Just skip below code and open above link!
Resources
- Video Presentation for
openSignalingChannel: https://vimeo.com/91780227 - Documentation for
openSignalingChannel: http://www.rtcmulticonnection.org/docs/openSignalingChannel/
Use your own socket.io for signaling
dataChannel.openSignalingChannel = function(config) {
var channel = config.channel || this.channel || 'default-channel';
var socket = io.connect('/?channel=' + channel);
socket.channel = channel;
socket.on('connect', function () {
if (config.callback) config.callback(socket);
});
socket.send = function (message) {
socket.emit('message', {
sender: dataChannel.userid,
data : message
});
};
socket.on('message', config.onmessage);
};
Use Pusher for signaling
A de
Related Skills
node-connect
346.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
107.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
346.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
346.8kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。

