initial commit
commit
c95e86e214
|
@ -0,0 +1,94 @@
|
|||
<p>
|
||||
<button onClick="openCamera()">Camera</button>
|
||||
<button onClick="openScreensharing()">Screensharing</button>
|
||||
<input type="number" id="x" />
|
||||
<input type="number" id="y" />
|
||||
<input type="number" id="width" />
|
||||
<input type="number" id="height" />
|
||||
<button onClick="startStream()">Start stream</button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<video autoplay style=""></video>
|
||||
<canvas style="display: none; transform: scale(1000%); image-rendering: crisp-edges;"></canvas>
|
||||
</p>
|
||||
|
||||
<script>
|
||||
const video = document.querySelector('video');
|
||||
const canvas = document.querySelector('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
async function openCamera() {
|
||||
const media = await navigator.mediaDevices.getUserMedia({ video: true, audio: false });
|
||||
video.srcObject = media;
|
||||
}
|
||||
|
||||
async function openScreensharing() {
|
||||
const media = await navigator.mediaDevices.getDisplayMedia();
|
||||
video.srcObject = media;
|
||||
}
|
||||
|
||||
async function startStream() {
|
||||
const width = 12;
|
||||
const height = 10;
|
||||
|
||||
const buffer = new ArrayBuffer(width * height * 3 + 2);
|
||||
const fb = new Uint8Array(buffer);
|
||||
fb[0] = 2;
|
||||
fb[1] = 1;
|
||||
const offset = 2;
|
||||
let skip = 0;
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const ws = new WebSocket("ws://127.0.0.1:8080/stream");
|
||||
|
||||
ws.onmessage = (ev) => {
|
||||
console.info('onmessage', ev);
|
||||
};
|
||||
ws.onopen = (ev) => {
|
||||
console.info('onopen');
|
||||
// fb[0] = 97;
|
||||
ws.send(buffer);
|
||||
ws.send('dupa!');
|
||||
};
|
||||
ws.onclose = (ev) => {
|
||||
console.info('onclose');
|
||||
};
|
||||
|
||||
const interval = 1000/30.0;
|
||||
const blob = new Blob([`setInterval(() => postMessage(0), ${interval});`]);
|
||||
const workerScript = URL.createObjectURL(blob);
|
||||
const worker = new Worker(workerScript);
|
||||
worker.onmessage = () => {
|
||||
render();
|
||||
};
|
||||
|
||||
function render() {
|
||||
//skip = (skip + 1) % 3;
|
||||
if (skip === 0) {
|
||||
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
||||
ctx.filter = 'contrast(300%)';
|
||||
const pixel = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
|
||||
for (var i = 0; i < width * height; i++) {
|
||||
fb[offset+3*i] = pixel.data[4*i];
|
||||
fb[offset+3*i+1] = pixel.data[4*i+1];
|
||||
fb[offset+3*i+2] = pixel.data[4*i+2];
|
||||
}
|
||||
|
||||
if (ws.readyState === 1) {
|
||||
ws.send(fb);
|
||||
}
|
||||
}
|
||||
|
||||
// setTimeout(render, 1000/30.0);
|
||||
// requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
//render();
|
||||
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,5 @@
|
|||
module github.com/informatic/wled-streamer
|
||||
|
||||
go 1.20
|
||||
|
||||
require github.com/gorilla/websocket v1.5.0 // indirect
|
|
@ -0,0 +1,2 @@
|
|||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
|
@ -0,0 +1,55 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"html/template"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var addr = flag.String("addr", "localhost:8080", "http service address")
|
||||
var target = flag.String("target", "localhost:2137", "target wled UDP port")
|
||||
|
||||
var upgrader = websocket.Upgrader{} // use default options
|
||||
|
||||
func stream(w http.ResponseWriter, r *http.Request) {
|
||||
c, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Print("upgrade:", err)
|
||||
return
|
||||
}
|
||||
conn, err := net.Dial("udp", *target)
|
||||
|
||||
defer c.Close()
|
||||
for {
|
||||
mt, message, err := c.ReadMessage()
|
||||
if err != nil {
|
||||
log.Println("read:", err)
|
||||
break
|
||||
}
|
||||
log.Printf("recv: %d mt: %s", len(message), mt)
|
||||
conn.Write(message)
|
||||
// err = c.WriteMessage(mt, message)
|
||||
if err != nil {
|
||||
log.Println("write:", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func home(w http.ResponseWriter, r *http.Request) {
|
||||
homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
http.HandleFunc("/stream", stream)
|
||||
http.HandleFunc("/", home)
|
||||
upgrader.CheckOrigin = func(r *http.Request) bool { return true }
|
||||
log.Printf("Listening on %s...", *addr)
|
||||
log.Fatal(http.ListenAndServe(*addr, nil))
|
||||
}
|
Loading…
Reference in New Issue