Record coordinated reception results and prepare scoped web H264 option
This commit is contained in:
@@ -8,19 +8,20 @@ const option = (name, fallback) => process.argv.find(a => a.startsWith('--' + na
|
||||
const duration = Number(option('duration', '900')), joinAt = Number(option('join', '300')), leaveAt = Number(option('leave', '600'));
|
||||
const channel = option('channel', 'TVP 1 HD');
|
||||
const reportPath = option('report', 'reception-trial.json');
|
||||
const bridgeFile = option('bridge-file', null);
|
||||
if (!process.argv.includes('--coordinated') || !Number.isFinite(duration) || !Number.isFinite(joinAt) || !Number.isFinite(leaveAt) || !(0 < joinAt && joinAt < leaveAt && leaveAt < duration)) {
|
||||
console.error('Requires --coordinated after explicit start signal, and 0 < join < leave < duration (seconds).');
|
||||
process.exit(2);
|
||||
}
|
||||
const origin = 'http://192.168.100.191:8096', web = origin + '/web/index.html';
|
||||
const safe = value => String(value).replace(/(api_key|access_token|Token|password)([=:\s]+)[^\s,"&]+/gi, '$1$2<redacted>').replace(/(https?:\/\/[^\s?"']+)\?[^\s"']*/g, '$1?<redacted>').slice(0, 500);
|
||||
const report = { started_utc: new Date().toISOString(), channel, relay_id: null, schedule_seconds: { duration, join: joinAt, leave: leaveAt }, checks: [], events: [], snapshots: [], audio_scope: 'Decoded byte counter when available; no human audible verification.' };
|
||||
const report = { started_utc: new Date().toISOString(), channel, relay_id: null, isolated_bridge_override: Boolean(bridgeFile), schedule_seconds: { duration, join: joinAt, leave: leaveAt }, checks: [], events: [], snapshots: [], audio_scope: 'Decoded byte counter when available; no human audible verification.' };
|
||||
fs.writeFileSync(reportPath + '.jsonl', '');
|
||||
const record = (type, data) => { const row = { utc: new Date().toISOString(), type, ...data }; fs.appendFileSync(reportPath + '.jsonl', JSON.stringify(row) + '\n'); return row; };
|
||||
const check = (name, ok, evidence) => { const row = { name, status: ok ? 'PASS' : 'FAIL', evidence }; report.checks.push(row); console.log(name + ': ' + row.status); record('check', row); };
|
||||
const admin = `import json,sqlite3,urllib.request,pathlib,secrets\nc=sqlite3.connect('file:/var/lib/jellyfin/data/jellyfin.db?mode=ro',uri=True);k=c.execute('SELECT AccessToken FROM ApiKeys LIMIT 1').fetchone()[0];c.close()\ndef api(p,d=None,method=None):\n r=urllib.request.Request('http://127.0.0.1:8096'+p,headers={'Authorization':'MediaBrowser Token="'+k+'", Client="ReceptionTrial", Device="Maintenance", DeviceId="decoder-reception-trial", Version="1"','Content-Type':'application/json'},data=json.dumps(d).encode() if d is not None else None,method=method)\n b=urllib.request.urlopen(r,timeout=10).read();return json.loads(b) if b else None\n`;
|
||||
const ssh = code => JSON.parse(execFileSync('ssh', ['-o', 'BatchMode=yes', 'root@192.168.100.25', 'pct exec 100191 -- python3 -'], { input: admin + code, encoding: 'utf8', timeout: 20000 }).trim().split('\n').at(-1));
|
||||
let browser, started, serviceReference, baseline, stopRequested = false;
|
||||
let browser, started, serviceReference, baseline, testedChannelId, stopRequested = false;
|
||||
process.on('SIGINT', () => { stopRequested = true; });
|
||||
process.on('SIGTERM', () => { stopRequested = true; });
|
||||
const accounts = [], viewers = [];
|
||||
@@ -30,6 +31,19 @@ async function makeViewer(index) {
|
||||
accounts.push(account);
|
||||
ssh(`api('/Users/${account.id}/Password',{'CurrentPw':'','NewPw':${JSON.stringify(account.password)}});print('{}')`);
|
||||
const context = await browser.newContext({ viewport: { width: 1280, height: 900 } }), page = await context.newPage();
|
||||
if (bridgeFile) {
|
||||
// A/B evaluation only: replace the plugin JS in this isolated browser, never on the server.
|
||||
await context.route('**/decoder-channel-playback.js*', route => {
|
||||
record('isolated_bridge_served', { viewer: index });
|
||||
return route.fulfill({ contentType: 'application/javascript', body: fs.readFileSync(bridgeFile, 'utf8') });
|
||||
});
|
||||
await context.route('**/DecoderIntegration/WebPlaybackPolicy?*', route => {
|
||||
const requested = new URL(route.request().url()).searchParams.get('channelId')?.replace(/-/g, '').toLowerCase();
|
||||
const matched = requested === testedChannelId.replace(/-/g, '').toLowerCase();
|
||||
record('isolated_policy_request', { viewer: index, matched });
|
||||
return route.fulfill({ json: { IsEnigmaChannel: matched, PreferH264: true } });
|
||||
});
|
||||
}
|
||||
const viewer = { index, context, page, active: false, closing: false, samples: [], errors: [], hls: { manifests: 0, segments: 0, failed: [], request_failed: [] } }; viewers.push(viewer);
|
||||
await page.addInitScript(() => {
|
||||
window.__trialEvents = [];
|
||||
@@ -123,8 +137,8 @@ function identifyRelay(snapshot) {
|
||||
(async () => {
|
||||
try {
|
||||
browser = await chromium.launch({ headless: true, channel: 'msedge', args: ['--autoplay-policy=no-user-gesture-required','--disable-background-timer-throttling','--disable-backgrounding-occluded-windows','--disable-renderer-backgrounding'] });
|
||||
testedChannelId = ssh(`c=next(x for x in api('/LiveTv/Channels?Limit=1000')['Items'] if x['Name']==${JSON.stringify(channel)});print(json.dumps(c['Id']))`);
|
||||
const primary = await makeViewer(1), secondary = await makeViewer(2);
|
||||
ssh(`c=next(x for x in api('/LiveTv/Channels?Limit=1000')['Items'] if x['Name']==${JSON.stringify(channel)});print('{}')`);
|
||||
baseline = await serverSnapshot('before');
|
||||
await open(primary); started = performance.now(); report.first_video_utc = new Date().toISOString();
|
||||
const first = await serverSnapshot('primary-started');
|
||||
|
||||
Reference in New Issue
Block a user