[wip] now display user's camera
next tricky thing is connecting users
This commit is contained in:
parent
484eea92e4
commit
079009a13e
20
priv/static/js/dist/webrtc.d.ts
vendored
20
priv/static/js/dist/webrtc.d.ts
vendored
@ -9,14 +9,14 @@
|
|||||||
*
|
*
|
||||||
* @module
|
* @module
|
||||||
*/
|
*/
|
||||||
type state = {
|
|
||||||
whoami: string;
|
|
||||||
roster: Array<string>;
|
|
||||||
};
|
|
||||||
declare let st: state;
|
|
||||||
declare function main(): Promise<void>;
|
declare function main(): Promise<void>;
|
||||||
type ws_msg = ["whoami", string] | ["roster", Array<string>];
|
/**
|
||||||
declare function handle_ws_msg(message: ws_msg): void;
|
* Try to get the user's camera
|
||||||
declare function ws_send_json(ws: WebSocket, x: any): void;
|
*
|
||||||
declare function render_state(): void;
|
* tries to get screenshare if user camera not available for whatever reason
|
||||||
declare function nickkk(nick: string): HTMLElement;
|
*
|
||||||
|
* chimps out if
|
||||||
|
* - not on https
|
||||||
|
* - user says no
|
||||||
|
*/
|
||||||
|
declare function getUserCamera(): Promise<MediaStream>;
|
||||||
|
|||||||
85
priv/static/js/dist/webrtc.js
vendored
85
priv/static/js/dist/webrtc.js
vendored
@ -10,71 +10,32 @@
|
|||||||
*
|
*
|
||||||
* @module
|
* @module
|
||||||
*/
|
*/
|
||||||
let st = { whoami: "",
|
|
||||||
roster: [] };
|
|
||||||
main();
|
main();
|
||||||
async function main() {
|
async function main() {
|
||||||
// start websocket immediately
|
console.log('peepy');
|
||||||
let ws;
|
let video = await getUserCamera();
|
||||||
let init = document.getElementById('init');
|
console.log('poopy');
|
||||||
let init_join = document.getElementById('init-join');
|
console.log('poopu');
|
||||||
// handle button click
|
let moi = document.getElementById('me');
|
||||||
init_join.addEventListener('click', function () {
|
moi.srcObject = video;
|
||||||
init.hidden = true;
|
console.log('poopa');
|
||||||
document.getElementById('run').hidden = false;
|
|
||||||
ws = new WebSocket('/ws/webrtc');
|
|
||||||
ws.onopen = function (e) { console.log('ws open'); };
|
|
||||||
ws.onclose = function (e) { console.warn('ws closed'); };
|
|
||||||
ws.onerror = function (e) { console.error('ws error:', e); };
|
|
||||||
ws.onmessage =
|
|
||||||
function (e) {
|
|
||||||
// console.log('ws message:', e.data);
|
|
||||||
let message = JSON.parse(e.data);
|
|
||||||
handle_ws_msg(message);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
function handle_ws_msg(message) {
|
/**
|
||||||
console.log('message from server:', message);
|
* Try to get the user's camera
|
||||||
switch (message[0]) {
|
*
|
||||||
case "whoami":
|
* tries to get screenshare if user camera not available for whatever reason
|
||||||
st.whoami = message[1];
|
*
|
||||||
break;
|
* chimps out if
|
||||||
case "roster":
|
* - not on https
|
||||||
st.roster = message[1];
|
* - user says no
|
||||||
break;
|
*/
|
||||||
default:
|
async function getUserCamera() {
|
||||||
console.warn("unknown message", message);
|
if (!(navigator.mediaDevices)) {
|
||||||
|
console.error('navigator.mediaDevices is null; user not on https or something');
|
||||||
}
|
}
|
||||||
render_state();
|
let availableDevices = await navigator.mediaDevices.enumerateDevices();
|
||||||
}
|
console.log(availableDevices);
|
||||||
function ws_send_json(ws, x) {
|
return await navigator.mediaDevices.getUserMedia({ video: true, audio: false });
|
||||||
let s = JSON.stringify(x, undefined, 4);
|
// return await navigator.mediaDevices.getDisplayMedia();
|
||||||
console.log('sending:\n', s);
|
|
||||||
ws.send(s);
|
|
||||||
}
|
|
||||||
function render_state() {
|
|
||||||
console.log('st', st);
|
|
||||||
// whoami
|
|
||||||
document.getElementById('whoami').innerText = st.whoami;
|
|
||||||
//
|
|
||||||
let roster_ul = document.getElementById('roster-ul');
|
|
||||||
let newChildren = [];
|
|
||||||
for (let nick of st.roster) {
|
|
||||||
if (!(nick === st.whoami)) {
|
|
||||||
let li = nickkk(nick);
|
|
||||||
newChildren.push(li);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roster_ul.replaceChildren(...newChildren);
|
|
||||||
}
|
|
||||||
function nickkk(nick) {
|
|
||||||
let li = document.createElement('li');
|
|
||||||
li.innerText += nick;
|
|
||||||
li.innerText += ' ';
|
|
||||||
let call_a = document.createElement('button');
|
|
||||||
call_a.innerText = 'call';
|
|
||||||
li.appendChild(call_a);
|
|
||||||
return li;
|
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=webrtc.js.map
|
//# sourceMappingURL=webrtc.js.map
|
||||||
2
priv/static/js/dist/webrtc.js.map
vendored
2
priv/static/js/dist/webrtc.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"webrtc.js","sourceRoot":"","sources":["../ts/webrtc.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;AAMH,IAAI,EAAE,GACF,EAAC,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,EAAE,EAAC,CAAC;AAEjB,IAAI,EAAE,CAAC;AAEP,KAAK,UACL,IAAI;IAIA,8BAA8B;IAC9B,IAAI,EAAa,CAAC;IAClB,IAAI,IAAI,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAmB,CAAC;IAC7D,IAAI,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAsB,CAAC;IAE1E,sBAAsB;IACtB,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAC9B;QACI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAE,CAAC,MAAM,GAAG,KAAK,CAAC;QAC/C,EAAE,GAAG,IAAI,SAAS,CAAC,YAAY,CAAC,CAAC;QACjC,EAAE,CAAC,MAAM,GAAM,UAAS,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,EAAE,CAAC,OAAO,GAAK,UAAS,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,EAAE,CAAC,OAAO,GAAK,UAAS,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,EAAE,CAAC,SAAS;YACR,UAAS,CAAC;gBACN,sCAAsC;gBACtC,IAAI,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAW,CAAC;gBAC3C,aAAa,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC,CAAC;IACV,CAAC,CACJ,CAAC;AACN,CAAC;AAKD,SACA,aAAa,CACR,OAAe;IAGhB,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;IAC7C,QAAO,OAAO,CAAC,CAAC,CAAC,EAAE;QACf,KAAK,QAAQ;YACT,EAAE,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM;QACV,KAAK,QAAQ;YACT,EAAE,CAAC,MAAM,GAAI,OAAO,CAAC,CAAC,CAAmB,CAAC;YAC1C,MAAM;QACV;YACI,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;KAChD;IAED,YAAY,EAAE,CAAC;AACnB,CAAC;AAID,SACA,YAAY,CACP,EAAc,EACd,CAAQ;IAGT,IAAI,CAAC,GAAW,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;IAE7B,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACf,CAAC;AAID,SACA,YAAY;IAIR,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACtB,SAAS;IACT,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAE,CAAC,SAAS,GAAG,EAAE,CAAC,MAAM,CAAC;IACzD,EAAE;IACF,IAAI,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAqB,CAAC;IACzE,IAAI,WAAW,GAAwB,EAAE,CAAC;IAC1C,KAAK,IAAI,IAAI,IAAI,EAAE,CAAC,MAAM,EAAE;QACxB,IAAI,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE;YACvB,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SACxB;KACJ;IACD,SAAS,CAAC,eAAe,CAAC,GAAG,WAAW,CAAC,CAAC;AAC9C,CAAC;AAED,SACA,MAAM,CACD,IAAY;IAGb,IAAI,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAEtC,EAAE,CAAC,SAAS,IAAI,IAAI,CAAC;IACrB,EAAE,CAAC,SAAS,IAAI,GAAG,CAAC;IAEpB,IAAI,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC;IAE1B,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,EAAE,CAAC;AACd,CAAC"}
|
{"version":3,"file":"webrtc.js","sourceRoot":"","sources":["../ts/webrtc.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;AAEH,IAAI,EAAE,CAAC;AAEP,KAAK,UACL,IAAI;IAIA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrB,IAAI,KAAK,GAAsB,MAAM,aAAa,EAAE,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrB,IAAI,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAqB,CAAC;IAC5D,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC;AAGD;;;;;;;;GAQG;AACH,KAAK,UACL,aAAa;IAIT,IAAI,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE;QAC3B,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;KACnF;IAED,IAAI,gBAAgB,GAChB,MAAM,SAAS,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAE9B,OAAO,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,EAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAC,CAAC,CAAC;IAC9E,yDAAyD;AAC7D,CAAC"}
|
||||||
@ -10,14 +10,6 @@
|
|||||||
* @module
|
* @module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type state =
|
|
||||||
{whoami: string,
|
|
||||||
roster: Array<string>};
|
|
||||||
|
|
||||||
let st: state =
|
|
||||||
{whoami: "",
|
|
||||||
roster: []};
|
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|
||||||
async function
|
async function
|
||||||
@ -25,103 +17,38 @@ main
|
|||||||
()
|
()
|
||||||
: Promise<void>
|
: Promise<void>
|
||||||
{
|
{
|
||||||
// start websocket immediately
|
console.log('peepy');
|
||||||
let ws: WebSocket;
|
let video : MediaStream = await getUserCamera();
|
||||||
let init = document.getElementById('init') as HTMLDivElement;
|
console.log('poopy');
|
||||||
let init_join = document.getElementById('init-join') as HTMLButtonElement;
|
console.log('poopu');
|
||||||
|
let moi = document.getElementById('me') as HTMLVideoElement;
|
||||||
// handle button click
|
moi.srcObject = video;
|
||||||
init_join.addEventListener('click',
|
console.log('poopa');
|
||||||
function() {
|
|
||||||
init.hidden = true;
|
|
||||||
document.getElementById('run')!.hidden = false;
|
|
||||||
ws = new WebSocket('/ws/webrtc');
|
|
||||||
ws.onopen = function(e) { console.log('ws open'); };
|
|
||||||
ws.onclose = function(e) { console.warn('ws closed'); };
|
|
||||||
ws.onerror = function(e) { console.error('ws error:', e); };
|
|
||||||
ws.onmessage =
|
|
||||||
function(e) {
|
|
||||||
// console.log('ws message:', e.data);
|
|
||||||
let message = JSON.parse(e.data) as ws_msg;
|
|
||||||
handle_ws_msg(message);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
type ws_msg = ["whoami", string]
|
|
||||||
| ["roster", Array<string>];
|
|
||||||
|
|
||||||
function
|
|
||||||
handle_ws_msg
|
|
||||||
(message: ws_msg)
|
|
||||||
: void
|
|
||||||
{
|
|
||||||
console.log('message from server:', message);
|
|
||||||
switch(message[0]) {
|
|
||||||
case "whoami":
|
|
||||||
st.whoami = message[1];
|
|
||||||
break;
|
|
||||||
case "roster":
|
|
||||||
st.roster = (message[1] as Array<string>);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.warn("unknown message", message);
|
|
||||||
}
|
|
||||||
|
|
||||||
render_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
function
|
* Try to get the user's camera
|
||||||
ws_send_json
|
*
|
||||||
(ws : WebSocket,
|
* tries to get screenshare if user camera not available for whatever reason
|
||||||
x : any)
|
*
|
||||||
: void
|
* chimps out if
|
||||||
{
|
* - not on https
|
||||||
let s: string = JSON.stringify(x, undefined, 4);
|
* - user says no
|
||||||
console.log('sending:\n', s);
|
*/
|
||||||
|
async function
|
||||||
ws.send(s);
|
getUserCamera
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function
|
|
||||||
render_state
|
|
||||||
()
|
()
|
||||||
: void
|
: Promise<MediaStream>
|
||||||
{
|
{
|
||||||
console.log('st', st);
|
if (!(navigator.mediaDevices)) {
|
||||||
// whoami
|
console.error('navigator.mediaDevices is null; user not on https or something');
|
||||||
document.getElementById('whoami')!.innerText = st.whoami;
|
|
||||||
//
|
|
||||||
let roster_ul = document.getElementById('roster-ul') as HTMLUListElement;
|
|
||||||
let newChildren : Array<HTMLElement> = [];
|
|
||||||
for (let nick of st.roster) {
|
|
||||||
if (!(nick === st.whoami)) {
|
|
||||||
let li = nickkk(nick);
|
|
||||||
newChildren.push(li);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
roster_ul.replaceChildren(...newChildren);
|
let availableDevices: Array<MediaDeviceInfo> =
|
||||||
}
|
await navigator.mediaDevices.enumerateDevices();
|
||||||
|
console.log(availableDevices);
|
||||||
function
|
|
||||||
nickkk
|
return await navigator.mediaDevices.getUserMedia({video: true, audio: false});
|
||||||
(nick: string)
|
// return await navigator.mediaDevices.getDisplayMedia();
|
||||||
: HTMLElement
|
|
||||||
{
|
|
||||||
let li = document.createElement('li');
|
|
||||||
|
|
||||||
li.innerText += nick;
|
|
||||||
li.innerText += ' ';
|
|
||||||
|
|
||||||
let call_a = document.createElement('button');
|
|
||||||
call_a.innerText = 'call';
|
|
||||||
|
|
||||||
li.appendChild(call_a);
|
|
||||||
|
|
||||||
return li;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,17 +15,10 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<h1 class="content-title">FEWD: webrtc demo</h1>
|
<h1 class="content-title">FEWD: webrtc demo</h1>
|
||||||
|
|
||||||
<div id="init">
|
<div class="content-body">
|
||||||
<button id="init-join">connect</button>
|
<textarea disabled id="wfc-output"></textarea>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<video id="me" autoplay muted></video>
|
||||||
<div id="run" hidden>
|
|
||||||
<h2>Whoami: <span id="whoami"></span></h2>
|
|
||||||
|
|
||||||
<h2>Roster</h2>
|
|
||||||
|
|
||||||
<ul id="roster-ul"></ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
127
scratch/webrtc01.ts
Normal file
127
scratch/webrtc01.ts
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* webrtc page script
|
||||||
|
*
|
||||||
|
* Author: Peter Harpending <peterharpending@qpq.swiss>
|
||||||
|
* Date: 2026-02-04
|
||||||
|
* Copyright: Copyright (c) 2026 QPQ AG
|
||||||
|
*
|
||||||
|
* Reference: https://git.qpq.swiss/QPQ-AG/research-megadoc/src/commit/c7c4592d4b21ad120145ef63334471a1a7ec1e60/paste/2026-02/grok-webrtc.html
|
||||||
|
*
|
||||||
|
* @module
|
||||||
|
*/
|
||||||
|
|
||||||
|
type state =
|
||||||
|
{whoami: string,
|
||||||
|
roster: Array<string>};
|
||||||
|
|
||||||
|
let st: state =
|
||||||
|
{whoami: "",
|
||||||
|
roster: []};
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
async function
|
||||||
|
main
|
||||||
|
()
|
||||||
|
: Promise<void>
|
||||||
|
{
|
||||||
|
// start websocket immediately
|
||||||
|
let ws: WebSocket;
|
||||||
|
let init = document.getElementById('init') as HTMLDivElement;
|
||||||
|
let init_join = document.getElementById('init-join') as HTMLButtonElement;
|
||||||
|
|
||||||
|
// handle button click
|
||||||
|
init_join.addEventListener('click',
|
||||||
|
function() {
|
||||||
|
init.hidden = true;
|
||||||
|
document.getElementById('run')!.hidden = false;
|
||||||
|
ws = new WebSocket('/ws/webrtc');
|
||||||
|
ws.onopen = function(e) { console.log('ws open'); };
|
||||||
|
ws.onclose = function(e) { console.warn('ws closed'); };
|
||||||
|
ws.onerror = function(e) { console.error('ws error:', e); };
|
||||||
|
ws.onmessage =
|
||||||
|
function(e) {
|
||||||
|
// console.log('ws message:', e.data);
|
||||||
|
let message = JSON.parse(e.data) as ws_msg;
|
||||||
|
handle_ws_msg(message);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type ws_msg = ["whoami", string]
|
||||||
|
| ["roster", Array<string>];
|
||||||
|
|
||||||
|
function
|
||||||
|
handle_ws_msg
|
||||||
|
(message: ws_msg)
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
console.log('message from server:', message);
|
||||||
|
switch(message[0]) {
|
||||||
|
case "whoami":
|
||||||
|
st.whoami = message[1];
|
||||||
|
break;
|
||||||
|
case "roster":
|
||||||
|
st.roster = (message[1] as Array<string>);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn("unknown message", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
render_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function
|
||||||
|
ws_send_json
|
||||||
|
(ws : WebSocket,
|
||||||
|
x : any)
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
let s: string = JSON.stringify(x, undefined, 4);
|
||||||
|
console.log('sending:\n', s);
|
||||||
|
|
||||||
|
ws.send(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function
|
||||||
|
render_state
|
||||||
|
()
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
console.log('st', st);
|
||||||
|
// whoami
|
||||||
|
document.getElementById('whoami')!.innerText = st.whoami;
|
||||||
|
//
|
||||||
|
let roster_ul = document.getElementById('roster-ul') as HTMLUListElement;
|
||||||
|
let newChildren : Array<HTMLElement> = [];
|
||||||
|
for (let nick of st.roster) {
|
||||||
|
if (!(nick === st.whoami)) {
|
||||||
|
let li = nickkk(nick);
|
||||||
|
newChildren.push(li);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roster_ul.replaceChildren(...newChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
nickkk
|
||||||
|
(nick: string)
|
||||||
|
: HTMLElement
|
||||||
|
{
|
||||||
|
let li = document.createElement('li');
|
||||||
|
|
||||||
|
li.innerText += nick;
|
||||||
|
li.innerText += ' ';
|
||||||
|
|
||||||
|
let call_a = document.createElement('button');
|
||||||
|
call_a.innerText = 'call';
|
||||||
|
|
||||||
|
li.appendChild(call_a);
|
||||||
|
|
||||||
|
return li;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user