Kraken SFU 仅支持简单的群组音频会议,可以轻松添加更多功能。
统一计划和 RTCP-MUX 都支持,因此每个参与者只有一个 UDP 端口,不管房间中有多少参与者。
Kraken 是一种即时音频会议服务,无需注册。
开始您的音频会议https://kraken.fm/ROOM-ID
ROOM-ID可以是任何东西,一个简单的词对公共房间有好处
ROOM-ID每次刷新首页获取随机匿名
项目地址:https://github.com/MixinNetwork/kraken https://github.com/MixinNetwork/kraken.fm
前端地址:https://github.com/lyricat/mornin.fm
项目源码:https://mornin.fm/
您必须拥有自己的域名,因为该项目使用相对路径。如果你使用 Github 的域名,它会被 deploy on .github.io/mornin.fm/,但它会尝试在其中查找 js 和 css.github.io/并且失败。
使用您的 DNS 提供商配置 CNAME 记录后,修改src/CNAME为您的自定义域名。
如果您使用自托管的kraken作为后端服务,请env.API_BASE在.github/workflows/master.yml
最后,转到您的分叉存储库,单击设置 -> 页面,选择gh-pages要保存的分支。
构建设置
# serve with hot reload at localhost:3000
# build for production and launch server
# generate static project
# install dependencies
$ yarn install
# serve with hot reload at localhost:3000
$ yarn dev
# build for production and launch server
$ yarn build
$ yarn start
# generate static project
$ yarn generate
# install dependencies
$ yarn install
# serve with hot reload at localhost:3000
$ yarn dev
# build for production and launch server
$ yarn build
$ yarn start
# generate static project
$ yarn generate
首先,获取海妖服务器代码并在本地启动引擎。
启动一个静态 Web 服务器来为 repo 目录提供服务。为了我们的目的,最简单的方法之一是使用 Python 的 SimpleHTTPServer。
确保已安装 Python 并导航到此 repo 的目录。运行命令。
$ python2 -m SimpleHTTPServer
$ python2 -m SimpleHTTPServer
$ python2 -m SimpleHTTPServer
您应该会看到服务器正在侦听端口 8000 的提示。
在 0.0.0.0 端口 8000 上提供 HTTP ...
在 0.0.0.0 端口 8000 上提供 HTTP ...
在 0.0.0.0 端口 8000 上提供 HTTP ...
打开浏览器,进入房间http://localhost:8000/?room=ROOM-ID
。
设置 Golang 开发环境。
git clone https://github.com/MixinNetwork/kraken
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
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
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
引擎处理房间,房间中的所有对等点都应该连接到同一个引擎实例。无需创建房间,房间只是分发流的 ID。
使用 HTTP JSON-RPC 访问引擎,一些代码来演示完整的过程。
var roomId = getUrlQueryParameter('room');
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)
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;
// 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)]);
async function rpc(method, params = []) {
const response = await fetch('http://localhost:7000', {
'Content-Type': 'application/json'
body: JSON.stringify({id: uuidv4(), method: method, params: params})
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();
}
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();
}

sicnature ---------------------------------------------------------------------
I P 地 址: 18.222.35.126
区 域 位 置: 美国俄亥俄
系 统 信 息:
Original content, please indicate the source:
同福客栈论坛 | 蟒蛇科普
| 海南乡情论坛 | JiaYu
Blog
sicnature ---------------------------------------------------------------------
Welcome to reprint. Please indicate the source https://myzhenai.com/post/4143.html
没有评论