🐙 High performance WebRTC SFU implemented with pure Go.

Kraken

🐙 High performance WebRTC SFU implemented with pure Go.

Architecture

Kraken SFU only supports simple group audio conferencing, more features may be added easily.

Both Unified Plan and RTCP-MUX supported, so that only one UDP port per participant despite the number of participants in a room.

monitor [WIP]

This is the daemon that load balance all engine instances according to their system load, and it will direct all peers in a room to the same engine instance.

engine

The engine handles rooms, all peers in a room should connect to the same engine instance. No need to create rooms, a room is just an ID to distribute streams.

Access the engine with HTTP JSON-RPC, some pseudocode to demonstrate the full procedure.

var roomId = getUrlQueryParameter('room');
var userId = uuidv4();
var trackId;

var pc = new RTCPeerConnection(configuration);

// send ICE candidate to engine
pc.onicecandidate = ({candidate}) => {
  rpc('trickle', [roomId, userId, trackId, JSON.stringify(candidate)]);
};

// play the audio stream when available
pc.ontrack = (event) => {
  el = document.createElement(event.track.kind)
  el.id = aid;
  el.srcObject = stream;
  el.autoplay = true;
  document.getElementById('peers').appendChild(el)
};

// setup local audio stream from microphone
const stream = await navigator.mediaDevices.getUserMedia(constraints);
stream.getTracks().forEach((track) => {
  pc.addTrack(track, stream);
});
await pc.setLocalDescription(await pc.createOffer());

// RPC publish to roomId, with SDP offer
var res = await rpc('publish', [roomId, userId, JSON.stringify(pc.localDescription)]);
// publish should respond an SDP answer
var jsep = JSON.parse(res.data.jsep);
if (jsep.type == 'answer') {
  await pc.setRemoteDescription(jsep);
  trackId = res.data.track;
  subscribe(pc);
}

// RPC subscribe to roomId periodically
async function subscribe(pc) {
  var res = await rpc('subscribe', [roomId, userId, trackId]);
  var jsep = JSON.parse(res.data.jsep);
  if (jsep.type == 'offer') {
    await pc.setRemoteDescription(jsep);
    var sdp = await pc.createAnswer();
    await pc.setLocalDescription(sdp);
    // RPC anwser the subscribe offer
    await rpc('answer', [roomId, userId, trackId, JSON.stringify(sdp)]);
  }
  setTimeout(function () {
    subscribe(pc);
  }, 3000);
}

async function rpc(method, params = []) {
  const response = await fetch('http://localhost:7000', {
    method: 'POST',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({id: uuidv4(), method: method, params: params})
  });
  return response.json();
}

Quick Start

Setup Golang development environment at first.

git clone https://github.com/MixinNetwork/kraken
cd kraken && go build

cp config/engine.example.toml config/engine.toml
ip address # get your network interface name, edit config/engine.toml

./kraken -c config/engine.toml -s engine

Get the source code of either kraken.fm or Mornin, follow their guides to use your local kraken API.

Community

Kraken is built with Pion, we have discussions over their Slack.

Owner
Mixin Network
We build open source software that always puts security, privacy and decentralization first.
Mixin Network
Comments
  • Try to set up kraken api server with nginx on local environment

    Try to set up kraken api server with nginx on local environment

    index_html

    I turn_server

    I've been struggling with local kraken api with nginx and turn server setting-up

    Whatever you need to resolve this situation, please leave any comment.

    Thanks for reading it.

  • Obscure API and very slow dev

    Obscure API and very slow dev

    https://vec.io/posts/kraken-high-performance-webrtc-sfu

    This is a very disrespectful post. It's ok that you discard SFUs just because they are not written in Go (the only language valid for you) but at least do not write shit about them.

    A "SFU just for audio" can be done in 15 minutes, so you have done nothing special.

    And BTW:

    • Unified-Plan is not a "super recent and cool WebRTC feature". It's been there for long years.
    • Adding video is not "an easy extension". Well, you'll see when you try to implement it.

    In short: you should not write shit about others just because you want to promote your own solution on Go.

  • Minor fixes

    Minor fixes

    Please review carefully--I am not set up to actually run these changes, and there are no tests.

    (Relatedly, it'd be nicer not to check in your go.mod pion replace directives.)

  • performance improvement: re-use timers

    performance improvement: re-use timers

    https://github.com/MixinNetwork/kraken/blob/221733d5bf764c9a1c6da5df61ee2937581b1dd1/engine/peer.go#L195

    Given that this for loop executes on every packet, it is probably better to use NewTimer and Reset in this loop. See e.g. https://medium.com/@oboturov/golang-time-after-is-not-garbage-collected-4cbc94740082 for a bit of discussion.

  • suspicious comparison in engine/peer.go

    suspicious comparison in engine/peer.go

    https://github.com/MixinNetwork/kraken/blob/221733d5bf764c9a1c6da5df61ee2937581b1dd1/engine/peer.go#L336

    Should this be next+uint32(gap) > 65535 instead of > 65536?

  • NACK (question)

    NACK (question)

    In Sean Dubois's broadcast example https://github.com/pion/webrtc/blob/master/examples/broadcast/main.go#L137 there's a loop to constantly read the sender (after AddTrack) using rtcpBuf := make([]byte, 1500)

    Why don't we need to do the same with Kraken? Is it because it's done somewhere else, like in the interceptor.Registry in router.go?

  • Possibility of memory leak?

    Possibility of memory leak?

    When someone get connected and disconnected to the kraken server, the occupied memory usage seems still consuming the resources.

    Is it due to nginx' cache problem or just time-consuming work to flush allocated memory?

  • Coturn to Kraken communication

    Coturn to Kraken communication

    Hi, Cedric. Thanks for your work on this! I've been troubleshooting my current setup pretty extensively. I was trying to mock up a production configuration for kraken while using the kraken.fm source code to test it out. I'm using the latest code from both projects, btw. And I'm using the "relay" option in the kraken.fm code. Could you embellish on a proper setup for coturn to get this working? Thanks!

    Current status:

    • kraken.fm is able to connect to the api (I'm running the coturn server and the kraken service on the same ec2 instance, btw)
    • the coturn server is handling packets and mapping ports
    • after about 10 seconds I get these errors:
    2020/09/21 14:18:16 HandlePeer(testing:ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D:aa8888df-fc40-4c6f-8df1-7b34d2e593b8) OnSignalingStateChange(have-remote-offer)
    2020/09/21 14:18:16 HandlePeer(testing:ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D:aa8888df-fc40-4c6f-8df1-7b34d2e593b8) OnICEConnectionStateChange(checking)
    2020/09/21 14:18:16 HandlePeer(testing:ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D:aa8888df-fc40-4c6f-8df1-7b34d2e593b8) OnSignalingStateChange(stable)
    2020/09/21 14:18:16 RPC.handle(id: 4d007d8a-76ee-4d0a-aa63-14f535455aa6, time: 0.026520s) OK
    2020/09/21 14:18:16 RPC.handle(id: 6b2ecad7-4984-4c19-afcd-4b1fa2a38db6, method: subscribe, params: [testing ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D aa8888df-fc40-4c6f-8df1-7b34d2e593b8])
    2020/09/21 14:18:16 RPC.handle(id: 6b2ecad7-4984-4c19-afcd-4b1fa2a38db6, time: 0.000125s) OK
    2020/09/21 14:18:20 RPC.handle(id: a2b36796-57b2-4c80-89d7-70057c4535ff, method: subscribe, params: [testing ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D aa8888df-fc40-4c6f-8df1-7b34d2e593b8])
    2020/09/21 14:18:20 RPC.handle(id: a2b36796-57b2-4c80-89d7-70057c4535ff, time: 0.000121s) OK
    2020/09/21 14:18:23 RPC.handle(id: defe36ab-20ae-4cd5-ad70-7a2cecd0be9c, method: subscribe, params: [testing ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D aa8888df-fc40-4c6f-8df1-7b34d2e593b8])
    2020/09/21 14:18:23 RPC.handle(id: defe36ab-20ae-4cd5-ad70-7a2cecd0be9c, time: 0.000090s) OK
    2020/09/21 14:18:26 RPC.handle(id: fda56f2d-7f59-43bf-b77a-bdf86c8c9c2d, method: subscribe, params: [testing ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D aa8888df-fc40-4c6f-8df1-7b34d2e593b8])
    2020/09/21 14:18:26 RPC.handle(id: fda56f2d-7f59-43bf-b77a-bdf86c8c9c2d, time: 0.000139s) OK
    2020/09/21 14:18:26 HandlePeer(testing:ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D:aa8888df-fc40-4c6f-8df1-7b34d2e593b8) OnTrackTimeout()
    2020/09/21 14:18:26 PeerClose(testing:ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D:aa8888df-fc40-4c6f-8df1-7b34d2e593b8) now
    2020/09/21 14:18:26 PeerClose(testing:ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D:CLOSED) with <nil>
    2020/09/21 14:18:26 HandlePeer(testing:ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D:CLOSED) OnConnectionStateChange(closed)
    2020/09/21 14:18:26 HandlePeer(testing:ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D:CLOSED) OnICEConnectionStateChange(closed)
    2020/09/21 14:18:29 RPC.handle(id: 72e68ef2-b410-4a91-9d30-92130868cd01, method: subscribe, params: [testing ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D aa8888df-fc40-4c6f-8df1-7b34d2e593b8])
    2020/09/21 14:18:29 RPC.handle(id: 72e68ef2-b410-4a91-9d30-92130868cd01, time: 0.000090s) ERROR {"status":202,"code":5002002,"description":"peer ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D closed in testing"}
    2020/09/21 14:18:32 RPC.handle(id: cde4f29a-df09-4606-87b4-229bf817e67b, method: subscribe, params: [testing ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D aa8888df-fc40-4c6f-8df1-7b34d2e593b8])
    2020/09/21 14:18:32 RPC.handle(id: cde4f29a-df09-4606-87b4-229bf817e67b, time: 0.000089s) ERROR {"status":202,"code":5002002,"description":"peer ca5a8823-64e2-4b0f-9851-8fc9cd9cfb75%3ASGV5dGhlcmU%3D closed in testing"}```
    
    
    
  • Is it possible to change opus bandwidth a little lower than 48000?

    Is it possible to change opus bandwidth a little lower than 48000?

    Hi, Cedric.

    After I checked the kraken system perfectly working on ec2 env, I found kraken using the opus codec and the setting has 48000 bandwidth.

    But, that means to me, even if I send just a bit of data stream, there is sort of waste of data on time, I think.

    Is it possible to change opus bandwidth a little lower than 48000?

    Thank you again, Cedric.

  • go build: cannot find package

    go build: cannot find package

    Following setup instructions, I get the following:

    $ go build
    main.go:11:2: cannot find package "github.com/MixinNetwork/kraken/engine" in any of:
            /usr/lib/go-1.6/src/github.com/MixinNetwork/kraken/engine (from $GOROOT)
            ($GOPATH not set)
    main.go:12:2: cannot find package "github.com/MixinNetwork/kraken/monitor" in any of:
            /usr/lib/go-1.6/src/github.com/MixinNetwork/kraken/monitor (from $GOROOT)
            ($GOPATH not set)
    main.go:13:2: cannot find package "github.com/MixinNetwork/mixin/logger" in any of:
            /usr/lib/go-1.6/src/github.com/MixinNetwork/mixin/logger (from $GOROOT)
            ($GOPATH not set)
    
  • Update pion/webrtc to v3.1.0-beta.3

    Update pion/webrtc to v3.1.0-beta.3

    Hey @cedricfung

    Good news I think you can use upstream again! I was trying to reproduce https://github.com/pion/webrtc/issues/1343 and everything seems to be working. If it works for you will resolve the issue.

    I used

    Chrome: Version 94.0.4606.20 (Official Build) dev (64-bit) FireFox: 88.0.1 (64-bit)

  • Why not delete room or peer if they are useless

    Why not delete room or peer if they are useless

    type pmap struct {
    	sync.RWMutex
    	id string
    	m  map[string]*Peer
    }
    type rmap struct {
    	sync.RWMutex
    	m map[string]*pmap
    }
    

    I found the peer and room data in these 2 struct will never be deleted. I think this memory leak is a problem if the service running for a long time. What do you think?

  • Scalability with limited amount of UDP port for kraken

    Scalability with limited amount of UDP port for kraken

    I saw your blog post, it stated each participants will consume 1 udp port on kraken, which means i could only have maximum of 48127 participants online simultaneously (common available udp port range 1024 to 49151), How to scale it up to allow more than that amount of users?

    Here's the idea i got, make a daemon that actively monitor the usage of the kraken UDP port availability, and magically use a Load Balancing to distribute the traffic to others instance

Pure Go implementation of the WebRTC API
Pure Go implementation of the WebRTC API

Pion WebRTC A pure Go implementation of the WebRTC API New Release Pion WebRTC v3.0.0 has been released! See the release notes to learn about new feat

Jan 1, 2023
Pure Go implementation of the WebRTC API
Pure Go implementation of the WebRTC API

Pure Go implementation of the WebRTC API

Jan 8, 2023
🚀 gnet is a high-performance, lightweight, non-blocking, event-driven networking framework written in pure Go./ gnet 是一个高性能、轻量级、非阻塞的事件驱动 Go 网络框架。
🚀 gnet is a high-performance, lightweight, non-blocking, event-driven networking framework written in pure Go./ gnet 是一个高性能、轻量级、非阻塞的事件驱动 Go 网络框架。

English | ???? 中文 ?? Introduction gnet is an event-driven networking framework that is fast and lightweight. It makes direct epoll and kqueue syscalls

Jan 2, 2023
gRPC over WebRTC

gRPC over WebRTC Just a proof of concept, please be kind. How to Start all the things Client, create-react-app + grpc-web signaling + webrtc extension

Dec 16, 2022
A yet to be voice call application in terminal. with the power of go and webRTC (pion).

Kenny I'm just trying to make a cli operated voice call chat application using go with help of webRTC and PortAudio. It might stay a Work In Progress

Dec 2, 2022
A toy MMO example built using Ebiten and WebRTC DataChannels (UDP)
A toy MMO example built using Ebiten and WebRTC DataChannels (UDP)

Ebiten WebRTC Toy MMO ⚠️ This is a piece of incomplete hobby work and not robust. Please read the "Why does this project exist?" section. What is this

Aug 28, 2022
Scalable WebRTC Signaling Server with ayame-like protocol.

ayu ayu is WebRTC Signaling Server with ayame-like protocol. Scalable: ayu uses Redis to store room states, so it can be used on serverless platforms

Nov 11, 2022
Example of using Pion WebRTC to play H264 + Ogg from disk

This repo demonstrates how you can use Pion WebRTC to play H264 and Ogg from disk. These same APIs can be used to pull from other sources. You can use

Sep 18, 2021
Demonstration of using Pion WebRTC with a shared socket

pion-webrtc-shared-socket This example demonstrates how Pion WebRTC can use an already listening UDP socket. On startup we listen on UDP Socket 8000.

Apr 4, 2022
WebRTC media servers stress testing tool (currently only Janus)
 WebRTC media servers stress testing tool (currently only Janus)

GHODRAT WebRTC media servers stress testing tool (currently only Janus) Architecture Janus media-server under load Deployment ghodrat # update or crea

Nov 9, 2022
This project is the eloboration of pion/webrtc.

This project is the eloboration of pion/webrtc. The idea is to make the (pion/webrtc) sfu-ws example be able to handle multiple rooms

Nov 29, 2021
Go Webrtc Signaling Server

Go Webrtc Signaling Server This package is used to listen for Remote SDP (Sessio

Sep 7, 2022
Peerconnection_explainer - PeerConnection-Explainer parses WebRTC Offers/Answers then provides summaries and suggestions

PeerConnection Explainer PeerConnection Explainer decodes WebRTC... so you don't have too! PeerConnection Explainer parses WebRTC Offers/Answers then

Oct 31, 2022
Overlay networks based on WebRTC.
Overlay networks based on WebRTC.

weron Overlay networks based on WebRTC. ⚠️ weron has not yet been audited! While we try to make weron as secure as possible, it has not yet undergone

Jan 4, 2023
Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http
Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http

fasthttp Fast HTTP implementation for Go. Currently fasthttp is successfully used by VertaMedia in a production serving up to 200K rps from more than

Jan 5, 2023
High performance async-io(proactor) networking for Golang。golangのための高性能非同期io(proactor)ネットワーキング
High performance async-io(proactor) networking for Golang。golangのための高性能非同期io(proactor)ネットワーキング

gaio Introduction 中文介绍 For a typical golang network program, you would first conn := lis.Accept() to get a connection and go func(net.Conn) to start a

Dec 29, 2022
🚀Gev is a lightweight, fast non-blocking TCP network library based on Reactor mode. Support custom protocols to quickly and easily build high-performance servers.
🚀Gev is a lightweight, fast non-blocking TCP network library based on Reactor mode. Support custom protocols to quickly and easily build high-performance servers.

gev 中文 | English gev is a lightweight, fast non-blocking TCP network library based on Reactor mode. Support custom protocols to quickly and easily bui

Jan 6, 2023
Gmqtt is a flexible, high-performance MQTT broker library that fully implements the MQTT protocol V3.1.1 and V5 in golang

中文文档 Gmqtt News: MQTT V5 is now supported. But due to those new features in v5, there area lots of breaking changes. If you have any migration problem

Jan 5, 2023