Live video on the AT Protocol
at next 112 lines 3.3 kB view raw
1import { BrowserWindow, session, WebFrameMain, webFrameMain } from "electron"; 2import { v7 as uuidv7 } from "uuid"; 3import { MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY } from "../env"; 4import { E2ETest, TestEnv } from "./test-env"; 5import { delay, PlayerReport } from "./util"; 6 7const SYNC_TOO_FAR = 20000; 8 9export const syncTest: E2ETest = { 10 test: async (testEnv: TestEnv): Promise<string | null> => { 11 // disabled until i can make the audio consistent 12 return null; 13 const playerId = `${uuidv7()}-sync-test`; 14 const window = new BrowserWindow({ 15 height: 720, 16 width: 1280, 17 webPreferences: { 18 preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, 19 }, 20 title: "streamplace-sync-test", 21 // titleBarStyle: "hidden", 22 // titleBarOverlay: true, 23 }); 24 let frame: WebFrameMain | undefined; 25 await new Promise<void>((resolve) => { 26 window.webContents.on( 27 "did-frame-navigate", 28 ( 29 event, 30 url, 31 httpResponseCode, 32 httpStatusText, 33 isMainFrame, 34 frameProcessId, 35 frameRoutingId, 36 ) => { 37 frame = webFrameMain.fromId(frameProcessId, frameRoutingId); 38 resolve(); 39 }, 40 ); 41 window.loadURL(`${testEnv.addr}/sync-test`); 42 }); 43 session.defaultSession.setDisplayMediaRequestHandler( 44 async (request, callback) => { 45 callback({ video: frame, audio: frame }); 46 }, 47 ); 48 const streamWindow = new BrowserWindow({ 49 height: 720, 50 width: 1280, 51 x: 0, 52 y: 0, 53 webPreferences: { 54 preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, 55 }, 56 title: "streamplace-sync-stream", 57 // titleBarStyle: "hidden", 58 // titleBarOverlay: true, 59 }); 60 const streamParams = new URLSearchParams({ 61 ingestMediaSource: "display", 62 ingestStreamKey: testEnv.multibaseKey, 63 ingestAutoStart: "true", 64 }); 65 streamWindow.loadURL( 66 `${testEnv.addr}/live/webcam?${streamParams.toString()}`, 67 ); 68 const playbackParams = new URLSearchParams({ 69 avSyncTest: "true", 70 playerId: playerId, 71 }); 72 const playbackWindow = new BrowserWindow({ 73 height: 720, 74 width: 1280, 75 x: 0, 76 y: 0, 77 webPreferences: { 78 preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, 79 }, 80 title: "streamplace-sync-playback", 81 // titleBarStyle: "hidden", 82 // titleBarOverlay: true, 83 }); 84 playbackWindow.loadURL( 85 `${testEnv.addr}/${testEnv.publicAddress}?${playbackParams.toString()}`, 86 ); 87 await delay(testEnv.testDuration); 88 await Promise.all([ 89 streamWindow.close(), 90 playbackWindow.close(), 91 window.close(), 92 ]); 93 const res = await fetch( 94 `${testEnv.internalAddr}/player-report/${playerId}`, 95 ); 96 const data = (await res.json()) as PlayerReport; 97 if (!data.avSync) { 98 return "av sync not present in output"; 99 } 100 console.log(JSON.stringify(data.avSync)); 101 let problems = []; 102 for (const f of ["min", "max", "avg"] as const) { 103 if (Math.abs(data.avSync[f]) > SYNC_TOO_FAR) { 104 problems.push(`av sync ${f} is ${data.avSync[f]}`); 105 } 106 } 107 if (problems.length > 0) { 108 return problems.join(", "); 109 } 110 return null; 111 }, 112};