initial commit

master
informatic 2023-11-06 22:34:51 +01:00
commit c95e86e214
4 changed files with 156 additions and 0 deletions

94
frontend.html Normal file
View File

@ -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>

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module github.com/informatic/wled-streamer
go 1.20
require github.com/gorilla/websocket v1.5.0 // indirect

2
go.sum Normal file
View File

@ -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=

55
server.go Normal file
View File

@ -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))
}