Warning
This package is under heavy development. Expect API to change
with minor version bumps until a major version of > 0 gets
published. While the core library API is relatively stable,
other addons such as @rtcio/react
will change quickly
Inspired by socket.io, rtcio is an easier to use way of dealing with WebRTC. It wraps the logic of creating RTCPeerConnections in easy-to-use callback chaining.
The GIF below highlights the use of the @rtcio/signal-local
, the debug features,
and the @rtcio/react
wrapper to get working peer to peer connections for
local development. The demo is currently a work in progress, but can be viewed
in the demo
package in the GitHub repository.
- Built in TypeScript and is fully typed
- Works with your custom signal server via an implemented interface
- Also has pre-built client-side signal server implementations
- @rtcio/socket-io-client
- @rtcio/signal-local
- Default server side signaler implementation available at:
- @rtcio/socket-io-server
- Also has pre-built client-side signal server implementations
- Binary data handling
- Automatic data chunking with configurable chunk sizes
- Support for out-of-order binary data receiving
- Native support for sending
File
s- Uses
ReadableStream
under the hood to reduce memory allocations for both sending and receiving large data files - Binary data is handled on a completely different data channel so as not to clog up real time messaging events
- Uses
- Generic typed parameters for custom events listeners and emitters
- Logging available via the debug library
- All packages are scoped to their npm name --
rtcio:{pkg-name}:{class-name}:[instanceId]{:logLevel?}
- Log Levels:
- warn
- error
- verbose
- log (will not include a log level)
- eg.
rtcio:core:RTC:[1a2b3c4d]:warn This is a warning level
- eg.
rtcio:signal-local:LocalSignalServer:[1a2b3c4d] This is a standard log
- Log Levels:
- All packages are scoped to their npm name --
- Create your own signaler by extending
ClientSignaler
in@rtcio/signaling
- A React wrapper via the
@rtcio/react
package.
- Handle audio and visual streams
- Custom signaler with raw websockets
- Custom signaler with raw Server Sent Events (SSE)
import { RTC } from "@rtcio/core";
import { SocketIoSignaler } from "@rtcio/socket-io-client";
const ROOM_NAME = "signalerRoom1";
interface MyCustomEvents {
message: (messageText: string) => void;
}
// There is a default server implementation for socket.io at
// `@rtcio/socket-io-server`
const io = new RTC<MyCustomEvents>(new SocketIoSignaler(socketArgs), ROOM_NAME);
const idResult = await io.connectToRoom();
if (idResult.isError()) {
// Unable to connect to the signal server
console.error(idResult.error);
return;
}
const myLocalId = idResult.value;
// Here we are 100% sure we have a valid connection AND a data channel
// This event is fired when a new remote peer has a direct connection to you.
// You can subscribe, unsubscribe, and emit events directly to the peer
io.on("connected", (newPeer) => {
newPeer.emit("message", "Hello, and welcome to rtcio!");
newPeer.on("message", (messageText) => {
console.log(`New message from ${newPeer.id}: ${messageText}`);
});
});
const roomPeers = io.getRoomPeers();
for (const peerId of roomPeers) {
// awaiting here doesn't actually wait for the connection.
// it's purely for the RTCPeerConnection to acquire all the
// data it needs to send to the signal server.
// You do _not_ have to await this for the connection to process.
await io.connectToPeer(peerId);
}
rtcio provides a local signaler as well which is useful for testing.
The package is @rtcio/signal-local
. Just remember that because
signalers should happen on each client, and here you are emulating 2
clients, you need 2 signal servers.
import { RTC } from "@rtcio/core";
import { LocalSignalServer } from "@rtcio/signal-local";
const ROOM_NAME = "TEST_ROOM";
const client1 = new RTC(new LocalSignalServer(), ROOM_NAME);
const client2 = new RTC(new LocalSignalServer(), ROOM_NAME);
// This should not be done in production, but the LocalSignalServer will
// not fail to connect as it uses BroadcastChannel behind the scenes.
const client2Id = (await client2.connectToRoom()).unwrap();
const client1Id = (await client1.connectToRoom()).unwrap();
client2.on("connectionRequest", async (req) => {
if (req.remoteId === client1Id) {
await req.accept();
} else {
req.reject();
}
});
client2.on("connected", (peer1) => {
console.log(`Peer1 connected with id ${peer1.id}`);
});
await client1.connectToPeer(client2Id);
Important
If testing locally on Firefox, you MUST use your local IP instead of localhost
.
This is a known issue in Firefox and cannot be fixed.
- locahost:5173 for localdev would be 192.168.xx.x:5173
- This can be easily done using vite --host as seen in the
demo
package in this repository
API documentation is coming in the near future, implemented via typedoc
,
and will be available on GitHub Pages once the integration is complete.