add trash

This commit is contained in:
도로롱
2025-11-03 22:08:03 +09:00
parent e8d40aed64
commit bc60033c19
2 changed files with 218 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
// Minimal Service Worker to expose a streaming endpoint: /mjpeg?key=...
// Page sends {type:'start'|'chunk'|'eof', key, ...} via postMessage.
const sessions = new Map(); // key -> {headers, status, controller, queue:[], started, ended, waiter}
self.addEventListener('install', (e) => self.skipWaiting());
self.addEventListener('activate', (e) => e.waitUntil(self.clients.claim()));
self.addEventListener('message', (e) => {
const d = e.data || {};
const key = d.key || 'default';
let s = sessions.get(key);
if (!s) {
s = {headers:null, status:200, controller:null, queue:[], started:false, ended:false, waiter:null};
sessions.set(key, s);
}
if (d.type === 'start') {
s.headers = d.headers || {};
s.status = d.status || 200;
s.started = true;
if (s.waiter) { s.waiter(); s.waiter = null; }
} else if (d.type === 'chunk') {
if (s.controller) {
s.controller.enqueue(new Uint8Array(d.chunk));
} else {
s.queue.push(d.chunk);
}
} else if (d.type === 'eof') {
s.ended = true;
if (s.controller) s.controller.close();
}
});
self.addEventListener('fetch', (e) => {
const url = new URL(e.request.url);
if (url.pathname === '/mjpeg') {
const key = url.searchParams.get('key') || 'default';
let s = sessions.get(key);
if (!s) {
s = {headers:null, status:200, controller:null, queue:[], started:false, ended:false, waiter:null};
sessions.set(key, s);
}
const stream = new ReadableStream({
start(controller) {
s.controller = controller;
if (s.queue.length) {
for (const q of s.queue) controller.enqueue(new Uint8Array(q));
s.queue = [];
}
if (s.ended) controller.close();
},
cancel() {
sessions.delete(key);
}
});
const waitHeaders = s.started ? Promise.resolve() : new Promise((resolve) => { s.waiter = resolve; setTimeout(resolve, 5000); });
e.respondWith((async () => {
await waitHeaders;
const h = new Headers();
// 받은 헤더를 그대로 복사(다중값 지원)
if (s.headers) {
for (const k in s.headers) {
const v = s.headers[k];
if (Array.isArray(v)) { v.forEach(x => h.append(k, x)); }
else if (v != null) { h.set(k, String(v)); }
}
}
if (!h.has('Content-Type')) {
// MJPEG 기본값(필요 시 실제 헤더에서 boundary가 전달됨)
h.set('Content-Type', 'multipart/x-mixed-replace; boundary=--frame');
}
return new Response(stream, {status: s.status || 200, headers: h});
})());
}
});