Skip to content

Instantly share code, notes, and snippets.

@aberenyi
Created February 11, 2020 15:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aberenyi/eb431adc064e6dd1807f51964d5383b6 to your computer and use it in GitHub Desktop.
Save aberenyi/eb431adc064e6dd1807f51964d5383b6 to your computer and use it in GitHub Desktop.
Stream to a Jitsi room using an RPi and a webcam
// Based on https://code.saghul.net/2017/09/streaming-a-webcam-to-a-jitsi-meet-room/
// extended to work on ARM (RPi)
const puppeteer = require('puppeteer');
// Streams the first webcam in the system to the specified Jitsi Meet room. Audio is currently
// not sent, but it can be easily enabled by disabling the corresponding setting in `meetArgs`.
//
// TODO
// - Detect if we are kicked from the room
// - Support authenticated deployments
//
// NOTE: only tested on GNU/Linux.
async function main(room, baseUrl='https://meet.jit.si')
{
const chromeArgs =
[
// Disable sandboxing, gives an error on Linux
'--no-sandbox',
'--disable-setuid-sandbox',
// Automatically give permission to use media devices
'--use-fake-ui-for-media-stream',
// Silence all output, just in case
'--alsa-output-device=plug:null',
// additional args from https://github.com/puppeteer/puppeteer/issues/550
'--display=:1',
'--disable-extensions'
];
const meetArgs =
[
// Disable receiving of video
'config.channelLastN=0',
// Mute our audio
'config.startWithAudioMuted=true',
// Don't use simulcast to save resources on the sender (our) side
'config.disableSimulcast=true',
// No need to process audio levels
'config.disableAudioLevels=true',
// Disable P2P mode due to a bug in Jitsi Meet
'config.p2p.enabled=false'
];
const url = `${baseUrl}/${room}#${meetArgs.join('&')}`;
console.log(`Loading ${url}`);
const browser = await puppeteer.launch
({
args: chromeArgs,
handleSIGINT: false,
defaultViewport: {width: 1920, height: 1080},
headless: false,
// make sure it's there
executablePath: '/usr/bin/chromium-browser'
});
const page = await browser.newPage();
// Manual handling on SIGINT to gracefully hangup and exit
process.on('SIGINT', async () =>
{
console.log('Exiting...');
await page.evaluate('APP.conference.hangup();');
await page.close();
browser.close();
console.log('Done!');
process.exit();
});
await page.goto(url);
try
{
const watchDog = page.waitForFunction('window.APP.conference._room !== undefined');
await watchDog
await page.evaluate('APP.conference._room.setDisplayName("Streamer");');
}
catch(e) { console.error(e) }
console.log('Running...');
}
main(process.argv[2] || 'test123');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment