stream volume and listener count
parent
3b288c9719
commit
4769e418e8
3
DOCS.md
3
DOCS.md
|
@ -1,3 +1,6 @@
|
|||
# NOTICE: this document is outdated
|
||||
# todo: update this document
|
||||
|
||||
# vybe websocket protocol - sent by client
|
||||
|
||||
socket.io actions + expected msg format and other info
|
||||
|
|
|
@ -46,25 +46,61 @@
|
|||
background: #303030;
|
||||
}
|
||||
button,
|
||||
input,
|
||||
input:not([type]), input[type='text'],
|
||||
.tab {
|
||||
padding: 4px 7px;
|
||||
}
|
||||
input {
|
||||
background: #1b1b1b;
|
||||
outline: none;
|
||||
&::placeholder {
|
||||
color: #aaa;
|
||||
}
|
||||
&:not([type]), &[type='text'] {
|
||||
border: 1px solid #444;
|
||||
&:focus {
|
||||
padding-bottom: 2px;
|
||||
border-bottom: 3px solid #777;
|
||||
}
|
||||
&::placeholder {
|
||||
color: #aaa;
|
||||
}
|
||||
&[type='radio'], &[type='checkbox'] {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
&[type='range'] {
|
||||
width: 100px;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background-color: #4f4f4f;
|
||||
border-radius: 1rem;
|
||||
height: 0.5rem;
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
&::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background-color: #555;
|
||||
border-radius: 1rem;
|
||||
border: 2px solid #909090;
|
||||
height: 17px;
|
||||
width: 17px;
|
||||
}
|
||||
&:focus::-webkit-slider-thumb {
|
||||
border: 2px solid #e0e0e0;
|
||||
}
|
||||
&::-moz-range-thumb {
|
||||
appearance: none;
|
||||
background-color: #555;
|
||||
border-radius: 1rem;
|
||||
border: 2px solid #909090;
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
}
|
||||
&:focus::-moz-range-thumb {
|
||||
border: 2px solid #e0e0e0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#register {
|
||||
margin-inline: 14px;
|
||||
|
@ -91,7 +127,7 @@
|
|||
display: block;
|
||||
}
|
||||
h3 {
|
||||
margin: 0;
|
||||
margin: 2px;
|
||||
}
|
||||
h4 {
|
||||
margin: 6px 0;
|
||||
|
@ -142,11 +178,14 @@
|
|||
}
|
||||
#home {
|
||||
margin: 0;
|
||||
max-width: 250px;
|
||||
max-width: 256px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
#instances {
|
||||
margin-inline: 2px;
|
||||
}
|
||||
#instancelist {
|
||||
overflow-y: auto;
|
||||
> :not(div) {
|
||||
|
|
|
@ -15,6 +15,7 @@ async function stream() {
|
|||
stop: true
|
||||
});
|
||||
document.getElementById('streaming').innerText = 'start streaming';
|
||||
document.getElementById('listeners').innerText = '';
|
||||
return;
|
||||
}
|
||||
if (!mediaStream)
|
||||
|
@ -71,8 +72,6 @@ async function stream() {
|
|||
});
|
||||
}
|
||||
|
||||
let audioctx;
|
||||
|
||||
function loadStreams() {
|
||||
let instance = window.currentInstance;
|
||||
|
||||
|
@ -93,7 +92,10 @@ function loadStreams() {
|
|||
name: this.value
|
||||
});
|
||||
window.currentThread.streamname = this.value;
|
||||
}}>`);
|
||||
}}>
|
||||
<p id='listeners'>${window.currentThread.listeners ?
|
||||
window.currentThread.listeners + ' listeners' : ''}
|
||||
</p>`);
|
||||
if (window.currentThread.streamname)
|
||||
document.getElementById('streamname').value = window.currentThread.streamname;
|
||||
}
|
||||
|
@ -104,18 +106,21 @@ function loadStreams() {
|
|||
function addStream(stream) {
|
||||
let p = html.node`
|
||||
<p>
|
||||
<button id='play' onclick=${e => {
|
||||
<button id='play' onclick=${function(event) {
|
||||
if (stream.playing) {
|
||||
audioctx.suspend();
|
||||
stream.audioctx.suspend();
|
||||
delete instance.streaming[stream.id];
|
||||
stream.playing = false;
|
||||
e.target.innerText = '▶';
|
||||
this.innerText = '▶';
|
||||
}
|
||||
else {
|
||||
audioctx = new AudioContext();
|
||||
stream.audioctx = new AudioContext();
|
||||
stream.gain = stream.audioctx.createGain();
|
||||
stream.gain.connect(stream.audioctx.destination);
|
||||
stream.gain.gain.value = p.children['volume'].value / 100;
|
||||
instance.streaming[stream.id] = stream;
|
||||
stream.playing = true;
|
||||
e.target.innerText = '⏹';
|
||||
this.innerText = '⏹';
|
||||
}
|
||||
instance.emit('play_stream', {
|
||||
id: stream.id,
|
||||
|
@ -126,11 +131,15 @@ function loadStreams() {
|
|||
console.log('play stream failed: ', msg.message);
|
||||
});
|
||||
}}>${instance.streaming[stream.id] ? '⏹' : '▶'}</button>
|
||||
<input id='volume' type='range' oninput=${function(event) {
|
||||
if (stream.gain)
|
||||
stream.gain.gain.value = this.value / 100;
|
||||
}}>
|
||||
<span id='name'>${stream.name ? ` - ${stream.name}` : ''}</span>
|
||||
</p>`;
|
||||
p.insertBefore(window.makeUser(stream.user,
|
||||
stream.user.id.split?.('@')[1] || window.currentInstance.url),
|
||||
p.children[1]);
|
||||
p.children[2]);
|
||||
p.id = 'stream' + stream.id;
|
||||
document.getElementById('streams').append(p);
|
||||
}
|
||||
|
@ -164,13 +173,23 @@ function loadStreams() {
|
|||
});
|
||||
|
||||
instance.socket.on('streamdata', async msg => {
|
||||
if (!instance.streaming[msg.id])
|
||||
let stream = instance.streaming[msg.id];
|
||||
if (!stream)
|
||||
return;
|
||||
let source = audioctx.createBufferSource();
|
||||
source.buffer = await audioctx.decodeAudioData(msg.audio);
|
||||
source.connect(audioctx.destination);
|
||||
let source = stream.audioctx.createBufferSource();
|
||||
source.buffer = await stream.audioctx.decodeAudioData(msg.audio);
|
||||
source.connect(stream.gain);
|
||||
source.start(/*audioStartTime*/);
|
||||
});
|
||||
|
||||
instance.socket.on('listeners', msg => {
|
||||
document.querySelector(
|
||||
`#instance${instance.id} > #threads > #threadlist > #thread${msg.thread}`)
|
||||
.thread.listeners = msg.count;
|
||||
if (msg.thread === window.currentThread?.id)
|
||||
document.getElementById('listeners').innerText =
|
||||
msg.count ? msg.count + ' listeners' : '';
|
||||
});
|
||||
}
|
||||
|
||||
if (window.currentThread)
|
||||
|
|
|
@ -110,7 +110,7 @@ io.on('connection', (socket) => {
|
|||
for (let id in vybe.streams) {
|
||||
const stream = vybe.streams[id];
|
||||
delete stream.listeners[socket.id];
|
||||
if (stream.socket === socket.id)
|
||||
if (stream.socket === socket)
|
||||
stream.stop();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -35,7 +35,7 @@ async function stream(msg, respond, socket) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (msg.id) {
|
||||
if (typeof msg.id === 'number') {
|
||||
stream = vybe.streams[msg.id];
|
||||
if (!stream)
|
||||
return respond({
|
||||
|
@ -79,7 +79,7 @@ async function stream(msg, respond, socket) {
|
|||
stream,
|
||||
userid: msg.auth_user.id,
|
||||
listeners: {},
|
||||
socket: socket.id,
|
||||
socket,
|
||||
stop: async () => {
|
||||
stream.stopped = true;
|
||||
thread.streams.splice(thread.streams.findIndex(s => s.id === stream.id), 1);
|
||||
|
@ -127,15 +127,20 @@ async function play_stream(msg, respond, socket) {
|
|||
message: "user doesn't have permission"
|
||||
});
|
||||
}
|
||||
if (!vybe.streams[msg.id])
|
||||
let stream = vybe.streams[msg.id];
|
||||
if (!stream)
|
||||
return respond({
|
||||
success: false,
|
||||
message: 'stream not found'
|
||||
});
|
||||
if (msg.playing)
|
||||
vybe.streams[msg.id].listeners[socket.id] = socket;
|
||||
stream.listeners[socket.id] = socket;
|
||||
else
|
||||
delete vybe.streams[msg.id].listeners[socket.id];
|
||||
delete stream.listeners[socket.id];
|
||||
stream.socket.emit('listeners', {
|
||||
thread: stream.stream.thread,
|
||||
count: Object.keys(stream.listeners).length
|
||||
});
|
||||
respond({
|
||||
success: true
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue