@muhkoo/theater-transcoder 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muhkoo/theater-transcoder",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Drain a Muhkoo Theater transcode queue with NATIVE ffmpeg. Run it on any machine signed in as you to add transcoding power to your library.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,6 +27,7 @@
27
27
  "dependencies": {
28
28
  "@muhkoo/connect": "0.10.1-alpha.0",
29
29
  "ffmpeg-static": "^5.2.0",
30
+ "node-datachannel": "^0.12.0",
30
31
  "snarkjs": "^0.7.5",
31
32
  "ws": "^8.18.0"
32
33
  }
package/src/client.js CHANGED
@@ -11,11 +11,19 @@ import { mkdtemp, writeFile } from "node:fs/promises";
11
11
  import { tmpdir } from "node:os";
12
12
  import { join } from "node:path";
13
13
  import { WebSocket } from "ws";
14
+ import * as ndc from "node-datachannel/polyfill";
14
15
  import { Client } from "@muhkoo/connect";
15
16
 
16
17
  // Node 20's global WebSocket is flag-gated; ensure the Space socket has one.
17
18
  if (!globalThis.WebSocket) globalThis.WebSocket = WebSocket;
18
19
 
20
+ // WebRTC polyfill so connect's P2P (browser-only by default) runs in Node — the
21
+ // worker then pulls raw shards directly from the uploader's browser over the LAN.
22
+ // `isP2pCapable()` only checks for RTCPeerConnection; set the whole surface.
23
+ for (const k of ["RTCPeerConnection", "RTCDataChannel", "RTCSessionDescription", "RTCIceCandidate"]) {
24
+ if (!globalThis[k] && ndc[k]) globalThis[k] = ndc[k];
25
+ }
26
+
19
27
  /** snarkjs (Node) reads circuit assets off disk — download them to a temp dir. */
20
28
  async function downloadCircuits(baseUrl) {
21
29
  const dir = await mkdtemp(join(tmpdir(), "muhkoo-circuits-"));
@@ -47,7 +55,10 @@ export async function connect({ baseUrl, appKey, username, password }) {
47
55
  apiKey: appKey,
48
56
  circuits,
49
57
  offline: { enabled: false },
50
- p2p: { enabled: false },
58
+ // P2P on: fetch raw shards from a browser peer over WebRTC. Empty iceServers
59
+ // → direct LAN (host) candidates, no STUN — ideal same-network transcoding;
60
+ // origin remains the fallback. The block engine runs main-thread in Node.
61
+ p2p: { enabled: true, iceServers: [], debug: process.env.MUHKOO_P2P_DEBUG === "1" },
51
62
  });
52
63
  const user = await client.auth.zk.login(username, password);
53
64
  return { client, user };
package/src/worker.js CHANGED
@@ -5,11 +5,14 @@
5
5
  * set) are claimable here — a browser's freshly-created job is stored in the
6
6
  * background, and the browser can also process it locally from memory.
7
7
  */
8
- import { hostname } from "node:os";
8
+ import { hostname, cpus } from "node:os";
9
9
  import { transcodeToHls } from "./transcode.js";
10
10
 
11
11
  const WORKER_ID = `node-${Math.random().toString(36).slice(2, 10)}`;
12
12
  const WORKER_LABEL = `the transcoder (${hostname()})`;
13
+ // Capability score: native ffmpeg on many cores far outranks a browser's wasm
14
+ // (cores×~30), so browsers defer manifest-ready jobs to this machine.
15
+ const MY_SCORE = cpus().length * 30;
13
16
  const STALE_MS = 90_000;
14
17
  const POLL_MS = 4_000;
15
18
 
@@ -104,7 +107,10 @@ export function startWorker({ client, space, appKey, baseUrl }) {
104
107
 
105
108
  let stopped = false;
106
109
  (async () => {
107
- log(`worker ${WORKER_ID} draining queue as ${client.auth.zk.user.username} (${WORKER_LABEL})`);
110
+ log(`worker ${WORKER_ID} draining queue as ${client.auth.zk.user.username} (${WORKER_LABEL}, score ${MY_SCORE})`);
111
+ // Announce capability so browsers defer manifest-ready jobs to us.
112
+ const hello = () => void postSignal({ kind: "hello", score: MY_SCORE, worker: WORKER_LABEL });
113
+ hello(); setInterval(hello, 12_000);
108
114
  // Real-time wake on new jobs; the poll below is the durable fallback.
109
115
  space.onMessage((e) => { const b = e?.message?.body; if (b?._t === "jobsig" && b.kind === "new" && b.src !== WORKER_ID) tick(); });
110
116
  let ticking = false;