livecam.js
function LiveCam(config) {

  const Assert = require('assert');

  config = config || {};
  Assert.ok(typeof(config), 'object');

  const gst_tcp_addr = config.gst_addr || "127.0.0.1";
  const gst_tcp_port = config.gst_port || 10000;
  const ui_addr = config.ui_addr || "127.0.0.1";
  const ui_port = config.ui_port || 11000;
  const broadcast_addr = config.broadcast_addr || "127.0.0.1";
  const broadcast_port = config.broadcast_port || 12000;
  const start = config.start;
  const webcam = config.webcam || {};

  if (start) Assert.ok(typeof(start), 'function');
  if (broadcast_port) Assert.ok(typeof(broadcast_port), 'number');
  if (broadcast_addr) Assert.ok(typeof(broadcast_addr), 'string');
  if (ui_port) Assert.ok(typeof(ui_port), 'number');
  if (ui_addr) Assert.ok(typeof(ui_addr), 'string');
  if (gst_tcp_port) Assert.ok(typeof(gst_tcp_port), 'number');
  if (gst_tcp_addr) Assert.ok(typeof(gst_tcp_addr), 'string');
  if (webcam) Assert.ok(typeof(webcam), 'object');

  if (!(new GstLaunch()).isAvailable()) {
    console.log("==================================================");
    console.log("Unable to locate gst-launch executable.");
    console.log("Look at https://github.com/sepehr-laal/livecam");
    console.log("You are most likely missing the GStreamer runtime.");
    console.log("==================================================");

    throw new Error('Unable to broadcast.');
  }

  console.log("LiveCam parameters:", {
    'broadcast_addr': broadcast_addr,
    'broadcast_port': broadcast_port,
    'ui_addr': ui_addr,
    'ui_port': ui_port,
    'gst_tcp_addr': gst_tcp_addr,
    'gst_tcp_port': gst_tcp_port
  });

  var broadcast = function() {
    var gst_cam_ui = new LiveCamUI();
    var gst_cam_wrap = new SocketCamWrapper();
    var gst_cam_server = new GstLiveCamServer(webcam);
    var gst_cam_process = gst_cam_server.start(gst_tcp_addr, gst_tcp_port);

    gst_cam_process.stdout.on('data', function(data) {
      console.log(data.toString());
      // This catches GStreamer when pipeline goes into PLAYING state
      if (data.toString().includes('Setting pipeline to PLAYING') > 0) {
        gst_cam_wrap.wrap(gst_tcp_addr, gst_tcp_port, broadcast_addr, broadcast_port);
        gst_cam_ui.serve(ui_addr, ui_port, broadcast_addr, broadcast_port);
        gst_cam_ui.close();

        if (start) start();
      }
    });

    gst_cam_process.stderr.on('data', function(data) {
      console.log(data.toString());
      gst_cam_ui.close();
    });
    gst_cam_process.on('error', function(err) {
      console.log("Webcam server error: " + err);
      gst_cam_ui.close();
    });
    gst_cam_process.on('exit', function(code) {
      console.log("Webcam server exited: " + code);
      gst_cam_ui.close();
    });
  }

  return {
    'broadcast': broadcast
  }

}
function LiveCam(config) {

  const Assert = require('assert');

  config = config || {};
  Assert.ok(typeof(config), 'object');

  const gst_tcp_addr = config.gst_addr || "127.0.0.1";
  const gst_tcp_port = config.gst_port || 10000;
  const ui_addr = config.ui_addr || "127.0.0.1";
  const ui_port = config.ui_port || 11000;
  const broadcast_addr = config.broadcast_addr || "127.0.0.1";
  const broadcast_port = config.broadcast_port || 12000;
  const start = config.start;
  const webcam = config.webcam || {};

  if (start) Assert.ok(typeof(start), 'function');
  if (broadcast_port) Assert.ok(typeof(broadcast_port), 'number');
  if (broadcast_addr) Assert.ok(typeof(broadcast_addr), 'string');
  if (ui_port) Assert.ok(typeof(ui_port), 'number');
  if (ui_addr) Assert.ok(typeof(ui_addr), 'string');
  if (gst_tcp_port) Assert.ok(typeof(gst_tcp_port), 'number');
  if (gst_tcp_addr) Assert.ok(typeof(gst_tcp_addr), 'string');
  if (webcam) Assert.ok(typeof(webcam), 'object');

  if (!(new GstLaunch()).isAvailable()) {
    console.log("==================================================");
    console.log("Unable to locate gst-launch executable.");
    console.log("Look at https://github.com/sepehr-laal/livecam");
    console.log("You are most likely missing the GStreamer runtime.");
    console.log("==================================================");

    throw new Error('Unable to broadcast.');
  }

  console.log("LiveCam parameters:", {
    'broadcast_addr': broadcast_addr,
    'broadcast_port': broadcast_port,
    'ui_addr': ui_addr,
    'ui_port': ui_port,
    'gst_tcp_addr': gst_tcp_addr,
    'gst_tcp_port': gst_tcp_port
  });

  var broadcast = function() {
    var gst_cam_ui = new LiveCamUI();
    var gst_cam_wrap = new SocketCamWrapper();
    var gst_cam_server = new GstLiveCamServer(webcam);
    var gst_cam_process = gst_cam_server.start(gst_tcp_addr, gst_tcp_port);

    gst_cam_process.stdout.on('data', function(data) {
      console.log(data.toString());
      // This catches GStreamer when pipeline goes into PLAYING state
      if (data.toString().includes('Setting pipeline to PLAYING') > 0) {
        gst_cam_wrap.wrap(gst_tcp_addr, gst_tcp_port, broadcast_addr, broadcast_port);
        gst_cam_ui.serve(ui_addr, ui_port, broadcast_addr, broadcast_port);
        gst_cam_ui.close();

        if (start) start();
      }
    });

    gst_cam_process.stderr.on('data', function(data) {
      console.log(data.toString());
      gst_cam_ui.close();
    });
    gst_cam_process.on('error', function(err) {
      console.log("Webcam server error: " + err);
      gst_cam_ui.close();
    });
    gst_cam_process.on('exit', function(code) {
      console.log("Webcam server exited: " + code);
      gst_cam_ui.close();
    });
  }

  return {
    'broadcast': broadcast
  }

}
/*!
@class LiveCam
@brief starts a livecam server at given config params
@note config can have the following options:
config.gst_tcp_addr --> where GStreamer TCP socket host is
[optional] [default: 127.0.0.1]
config.gst_tcp_port --> where GStreamer TCP socket port is
[optional] [default: 10000]
config.ui_addr --> where minimal UI host is
[optional] [default: 127.0.0.1]
config.ui_port --> where minimal UI port is
[optional] [default: 11000]
config.broadcast_addr --> where Socket IO host is (browser-visible)
[optional] [default: 127.0.0.1]
config.broadcast_port --> where Socket IO port is (browser-visible)
[optional] [default: 12000]
config.start --> event emitted when streaming is started
[optional] [default: null]