Skip to content

Instantly share code, notes, and snippets.

@voltrevo
Last active February 20, 2017 07:04
Show Gist options
  • Save voltrevo/27cfd5757b1a62670ceeb17241545692 to your computer and use it in GitHub Desktop.
Save voltrevo/27cfd5757b1a62670ceeb17241545692 to your computer and use it in GitHub Desktop.
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
module.exports = function PositionalAudioPlayer(stream, leftRightBalance = 0.5) {
const player = {};
const audioCtx = new AudioContext();
const source = audioCtx.createMediaStreamSource(stream);
const splitter = audioCtx.createChannelSplitter(2);
const merger = audioCtx.createChannelMerger(2);
source.connect(splitter);
const leftGainNode = audioCtx.createGain();
const rightGainNode = audioCtx.createGain();
player.setLeftRightBalance = (balance) => {
leftGainNode.gain.value = Math.cos(0.5 * Math.PI * balance);
rightGainNode.gain.value = Math.sin(0.5 * Math.PI * balance);
};
player.setLeftRightBalance(leftRightBalance);
splitter.connect(leftGainNode, 0);
splitter.connect(rightGainNode, 1);
leftGainNode.connect(merger, 0, 0);
rightGainNode.connect(merger, 0, 1);
merger.connect(audioCtx.destination);
return player;
};
},{}],2:[function(require,module,exports){
'use strict';
const { SessionGroup } = require('./index');
const msg = (str) => {
const div = document.createElement('div');
div.style.borderRadius = '5px';
div.style.backgroundColor = '#cff';
div.style.color = '#000';
div.style.zIndex = '100';
div.textContent = str;
div.style.position = 'fixed';
div.style.right = '10px';
div.style.bottom = '10px';
div.style.padding = '10px';
document.body.appendChild(div);
let timerId;
const clearTimer = () => clearTimeout(timerId);
const setTimer = () => {
timerId = setTimeout(() => {
div.remove();
}, 3000);
};
setTimer();
div.addEventListener('mouseover', () => {
clearTimer();
div.style.backgroundColor = '#cfc';
});
div.addEventListener('mouseout', () => {
setTimer();
div.style.backgroundColor = '#cff';
});
};
const run = () => {
const OT = window.OT;
if (!window.OT) {
msg('OpenTok not found on this page.');
return;
}
if (window.opentokStereoActivated) {
msg('OpenTok Stereo should already be active.');
return;
}
const session = OT.sessions.find();
if (!session) {
msg('Session not found.');
}
window.opentokStereoSessionGroup = SessionGroup(session);
window.opentokStereoActivated = true;
msg('OpenTok Stereo activated.');
};
try {
run();
} catch (e) {
msg(`Exception thrown on set-up: ${e.msg}`);
window.opentokStereoErrors = window.opentokStereoErrors || [];
window.opentokStereoErrors.push(e);
throw e;
}
},{"./index":3}],3:[function(require,module,exports){
'use strict';
/* eslint-disable no-restricted-syntax */
const PositionalAudioPlayer = require('./PositionalAudioPlayer');
const range = n => (new Array(n)).fill(0).map((x, i) => i);
function SubscriberAudioPlayer(subscriber) {
subscriber.setAudioVolume(0);
const vid = subscriber.element.querySelector('video');
const stream = vid.srcObject;
const player = {};
player.setLeftRightBalance = PositionalAudioPlayer(stream).setLeftRightBalance;
player.getDomBasedBalance = () => {
const rect = vid.getBoundingClientRect();
return (0.5 * (rect.left + rect.right)) / window.innerWidth;
};
return player;
}
function SubscriberGroup() {
const group = {};
const subscribers = [];
const playerMap = new WeakMap();
group.add = (subscriber) => {
const index = subscribers.indexOf(subscriber);
if (index !== -1) {
return;
}
if (!(subscriber.element && subscriber.element.querySelector('video'))) {
subscriber.on('videoElementCreated', () => group.add(subscriber));
return;
}
subscribers.push(subscriber);
playerMap.set(subscriber, SubscriberAudioPlayer(subscriber));
subscriber.on('destroyed', () => group.remove(subscriber));
group.update();
};
group.remove = (subscriber) => {
const index = subscribers.indexOf(subscriber);
if (index === -1) {
return;
}
subscribers.splice(index, 1);
group.update();
};
group.update = () => {
if (subscribers.length === 1) {
playerMap.get(subscribers[0]).setLeftRightBalance(0.5);
} else if (subscribers.length === 0) {
return;
}
const rawBalances = subscribers.map(sub => playerMap.get(sub).getDomBasedBalance());
const least = rawBalances.reduce((x, y) => Math.min(x, y));
const most = rawBalances.reduce((x, y) => Math.max(x, y));
if (least === most) {
for (const sub of subscribers) {
playerMap.get(sub).setLeftRightBalance(0.5);
}
return;
}
const balances = rawBalances.map(bal => (bal - least) / (most - least));
for (const i of range(balances.length)) {
playerMap.get(subscribers[i]).setLeftRightBalance(balances[i]);
}
};
group.watch = (period = 100) => {
setInterval(group.update, period);
};
return group;
}
function SessionGroup(session, watchPeriod = 100) {
const group = SubscriberGroup();
const update = () => {
for (const stream of session.streams.where()) {
for (const sub of session.getSubscribersForStream(stream)) {
group.add(sub);
}
}
group.update();
};
update();
setInterval(update, watchPeriod);
return group;
}
module.exports = {
SubscriberAudioPlayer,
SubscriberGroup,
SessionGroup,
};
},{"./PositionalAudioPlayer":1}]},{},[2]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment