T-HUB/infra/peertube-workers/win/ipc-nvenc.cjs
glass beadian aa5e262f3a Tactical Media Broadcast Hub — initial release
Self-hosted multi-platform broadcast newsroom for activist collectives:
publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style
column wall with hostile-content-safe rendering, live control room with Auto
Director, bridged chat governance with polls and quorum, distributed sandboxed
transcode workers, encrypted content-addressed archive, monthly analytics.

MIT licensed. See README.md and docs/.
2026-10-10 11:56:42 +00:00

55 lines
3.9 KiB
JavaScript

#!/usr/bin/env node
'use strict';
// Same IPC protocol/library as the official runner 0.2.0; Windows named-pipe variant
// of infra/peertube-workers/ipc.cjs. Registration secret comes from stdin, never argv.
//
// Pipe-name derivation (verified in the shipped 0.2.0 bundle):
// ConfigManager id defaults to "default"; socket path is
// join(envPaths("peertube-runner", suffix "nodejs").data, id, "peertube-runner.sock")
// = %LOCALAPPDATA%\peertube-runner-nodejs\Data\default\peertube-runner.sock
// The bundled @peertube/net-ipc rewrites any path on win32:
// `\\\\.\\pipe\\${path.replace(/^\//, "").replace(/\//g, "-")}`
// so we pass the RAW Windows path and never build the \\.\pipe\ prefix ourselves.
const root = process.argv[3] || process.env.PT_ROOT || 'C:\\pt-worker';
process.env.APPDATA = require('node:path').join(root, 'profile', 'Roaming');
process.env.LOCALAPPDATA = require('node:path').join(root, 'profile', 'Local');
const { Client } = require(require('node:path').join(root, 'runner', 'node_modules', '@peertube', 'net-ipc'));
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const action = process.argv[2];
const base = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
const id = process.env.PT_RUNNER_ID || 'default';
const sock = path.join(base, 'peertube-runner-nodejs', 'Data', id, 'peertube-runner.sock');
let client = new Client({ path: sock, reconnect: false });
const deadline = setTimeout(() => { client.destroy(); process.exit(1); }, 15000);
(async () => {
try {
let connected = false;
for (let attempt = 0; attempt < 20; attempt++) {
try { await client.connect(); connected = true; break; }
catch { client.destroy(); await new Promise(resolve => setTimeout(resolve, 500)); client = new Client({path: sock, reconnect: false}); }
}
if (!connected) throw new Error('IPC unavailable');
let request = { type: action };
if (action === 'register') {
const cfg = JSON.parse(fs.readFileSync(process.env.PT_WORKER_CONFIG || path.join(root, 'state', 'worker.json'), 'utf8').replace(/^\uFEFF/, ''));
const proof = JSON.parse(fs.readFileSync(path.join(root, 'state', 'nvenc.json'), 'utf8').replace(/^\uFEFF/, ''));
const identity = require('node:child_process').execFileSync('nvidia-smi.exe', ['-i',String(cfg.nvenc_device || 0),'--query-gpu=uuid,driver_version','--format=csv,noheader,nounits'],{timeout:5000,encoding:'utf8'}).trim().split(/,\s*/);
if (identity[0] !== proof.gpu_uuid || identity[1] !== proof.driver_version) throw new Error('changed GPU');
if (!proof.nvenc_h264_ok || !proof.nvenc_hevc_ok || Date.now()/1000 - proof.tested_at > 86400) throw new Error('proof missing');
const registrationToken = fs.readFileSync(0, 'utf8').trim();
if (!registrationToken.startsWith('ptrrt-')) throw new Error('bad token');
request = { type: 'register', url: cfg.peertube_url, runnerName: cfg.name, registrationToken,
runnerDescription: 'Windows NVENC only; VOD; AC-only admission; concurrency 2' };
} else if (!['list-jobs', 'list-registered', 'graceful-shutdown'].includes(action)) throw new Error('bad action');
const result = await client.request(request);
if (!result.success) throw new Error('IPC failed');
if (action === 'list-jobs') {
// Drop payloads (can contain URLs); status consumers only need counts.
console.log(JSON.stringify({ concurrency: result.data.concurrency, active_jobs: result.data.processingJobs.length }));
} else if (action === 'list-registered') console.log(JSON.stringify({ registered_count: result.data.registeredInstances?.length || result.data.instances?.length || 0 }));
else console.log(JSON.stringify({ success: true }));
} catch { console.error('Runner IPC failed; inspect local service health'); process.exitCode = 1; }
finally { clearTimeout(deadline); client.destroy(); }
})();