Compare commits
10 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
d878a809d1 | |
|
|
1389107107 | |
|
|
59ba0499cd | |
|
|
8f87b1a3c1 | |
|
|
e03ab517e0 | |
|
|
bb02cee8ff | |
|
|
700f48b15c | |
|
|
9f8bc7896c | |
|
|
aeea4c76bf | |
|
|
f8d0a45dcc |
|
|
@ -0,0 +1,3 @@
|
||||||
|
*/node_modules
|
||||||
|
*/build
|
||||||
|
server/public
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
#FROM node:lts-alpine AS mm-builder
|
||||||
|
FROM node:10-slim AS mm-builder
|
||||||
|
|
||||||
|
|
||||||
|
# Args
|
||||||
|
ARG BASEDIR=/opt
|
||||||
|
ARG MM=multiparty-meeting
|
||||||
|
ARG NODE_ENV=production
|
||||||
|
ARG SERVER_DEBUG=''
|
||||||
|
ARG REACT_APP_DEBUG=''
|
||||||
|
|
||||||
|
|
||||||
|
#RUN apk add --no-cache git bash
|
||||||
|
RUN apt-get update;apt-get install -y git bash
|
||||||
|
|
||||||
|
WORKDIR ${BASEDIR}
|
||||||
|
COPY server ${BASEDIR}/${MM}/server
|
||||||
|
|
||||||
|
#install server dep
|
||||||
|
WORKDIR ${BASEDIR}/${MM}/server
|
||||||
|
|
||||||
|
#RUN apk add --no-cache git build-base python linux-headers
|
||||||
|
RUN apt-get install -y git build-essential python
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
|
||||||
|
COPY app ${BASEDIR}/${MM}/app
|
||||||
|
#install app dep
|
||||||
|
WORKDIR ${BASEDIR}/${MM}/app
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# set app in producion mode/minified/.
|
||||||
|
ENV NODE_ENV ${NODE_ENV}
|
||||||
|
|
||||||
|
# Workaround for the next yarn run build => rm -rf public dir even if it does not exists.
|
||||||
|
# TODO: Fix it smarter
|
||||||
|
RUN mkdir -p ${BASEDIR}/${MM}/server/public
|
||||||
|
|
||||||
|
ENV REACT_APP_DEBUG=${REACT_APP_DEBUG}
|
||||||
|
|
||||||
|
# package web app
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
|
||||||
|
#FROM node:lts-alpine
|
||||||
|
FROM node:10-slim
|
||||||
|
|
||||||
|
# Args
|
||||||
|
ARG BASEDIR=/opt
|
||||||
|
ARG MM=multiparty-meeting
|
||||||
|
ARG NODE_ENV=production
|
||||||
|
ARG SERVER_DEBUG=''
|
||||||
|
|
||||||
|
WORKDIR ${BASEDIR}
|
||||||
|
|
||||||
|
COPY --from=mm-builder ${BASEDIR}/${MM}/server ${BASEDIR}/${MM}/server
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Web PORTS
|
||||||
|
EXPOSE 80 443
|
||||||
|
EXPOSE 40000-49999/udp
|
||||||
|
|
||||||
|
|
||||||
|
## run server
|
||||||
|
ENV DEBUG ${SERVER_DEBUG}
|
||||||
|
|
||||||
|
COPY docker/docker-entrypoint.sh /
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
node {
|
||||||
|
stage('Checkout') {
|
||||||
|
checkout scm
|
||||||
|
}
|
||||||
|
stage('Build docker') {
|
||||||
|
customImage = docker.build("public/mm:${env.BUILD_ID}")
|
||||||
|
}
|
||||||
|
stage('Push to registry') {
|
||||||
|
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
|
||||||
|
docker.withRegistry('https://docker.briq.it', 'briq-docker-cred') {
|
||||||
|
customImage.push("${env.BRANCH_NAME}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -240,7 +240,7 @@ const ChooseRoom = ({
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
|
|
||||||
{ !isElectron() &&
|
{ !isElectron() && false &&
|
||||||
<CookieConsent buttonText={intl.formatMessage({
|
<CookieConsent buttonText={intl.formatMessage({
|
||||||
id : 'room.consentUnderstand',
|
id : 'room.consentUnderstand',
|
||||||
defaultMessage : 'I understand'
|
defaultMessage : 'I understand'
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ const styles = (theme) =>
|
||||||
},
|
},
|
||||||
divider :
|
divider :
|
||||||
{
|
{
|
||||||
marginLeft : theme.spacing(3),
|
marginLeft : theme.spacing(3)
|
||||||
},
|
},
|
||||||
show :
|
show :
|
||||||
{
|
{
|
||||||
|
|
@ -345,7 +345,7 @@ const TopBar = (props) =>
|
||||||
className={classes.actionButton}
|
className={classes.actionButton}
|
||||||
variant='contained'
|
variant='contained'
|
||||||
color='secondary'
|
color='secondary'
|
||||||
onClick={() => roomClient.close()}
|
onClick={() => { roomClient.close(); window.close(); }}
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='label.leave'
|
id='label.leave'
|
||||||
|
|
@ -364,7 +364,7 @@ TopBar.propTypes =
|
||||||
room : appPropTypes.Room.isRequired,
|
room : appPropTypes.Room.isRequired,
|
||||||
peersLength : PropTypes.number,
|
peersLength : PropTypes.number,
|
||||||
lobbyPeers : PropTypes.array,
|
lobbyPeers : PropTypes.array,
|
||||||
permanentTopBar : PropTypes.bool,
|
permanentTopBar : PropTypes.bool,
|
||||||
myPicture : PropTypes.string,
|
myPicture : PropTypes.string,
|
||||||
loggedIn : PropTypes.bool.isRequired,
|
loggedIn : PropTypes.bool.isRequired,
|
||||||
loginEnabled : PropTypes.bool.isRequired,
|
loginEnabled : PropTypes.bool.isRequired,
|
||||||
|
|
@ -383,14 +383,14 @@ TopBar.propTypes =
|
||||||
|
|
||||||
const mapStateToProps = (state) =>
|
const mapStateToProps = (state) =>
|
||||||
({
|
({
|
||||||
room : state.room,
|
room : state.room,
|
||||||
peersLength : peersLengthSelector(state),
|
peersLength : peersLengthSelector(state),
|
||||||
lobbyPeers : lobbyPeersKeySelector(state),
|
lobbyPeers : lobbyPeersKeySelector(state),
|
||||||
permanentTopBar : state.settings.permanentTopBar,
|
permanentTopBar : state.settings.permanentTopBar,
|
||||||
loggedIn : state.me.loggedIn,
|
loggedIn : state.me.loggedIn,
|
||||||
loginEnabled : state.me.loginEnabled,
|
loginEnabled : state.me.loginEnabled,
|
||||||
myPicture : state.me.picture,
|
myPicture : state.me.picture,
|
||||||
unread : state.toolarea.unreadMessages +
|
unread : state.toolarea.unreadMessages +
|
||||||
state.toolarea.unreadFiles
|
state.toolarea.unreadFiles
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -177,27 +177,11 @@ const JoinDialog = ({
|
||||||
{
|
{
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const handleKeyDown = (event) =>
|
roomClient.join({ roomId, joinVideo: true });
|
||||||
{
|
|
||||||
const { key } = event;
|
return (<div />);
|
||||||
|
|
||||||
switch (key)
|
/* return (
|
||||||
{
|
|
||||||
case 'Enter':
|
|
||||||
case 'Escape':
|
|
||||||
{
|
|
||||||
if (displayName === '')
|
|
||||||
changeDisplayName('Guest');
|
|
||||||
if (room.inLobby)
|
|
||||||
roomClient.changeDisplayName(displayName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<Dialog
|
<Dialog
|
||||||
open
|
open
|
||||||
|
|
@ -335,7 +319,7 @@ const JoinDialog = ({
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
}
|
}
|
||||||
|
|
||||||
{ !isElectron() &&
|
{ !isElectron() && false &&
|
||||||
<CookieConsent buttonText={intl.formatMessage({
|
<CookieConsent buttonText={intl.formatMessage({
|
||||||
id : 'room.consentUnderstand',
|
id : 'room.consentUnderstand',
|
||||||
defaultMessage : 'I understand'
|
defaultMessage : 'I understand'
|
||||||
|
|
@ -348,7 +332,7 @@ const JoinDialog = ({
|
||||||
}
|
}
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);*/
|
||||||
};
|
};
|
||||||
|
|
||||||
JoinDialog.propTypes =
|
JoinDialog.propTypes =
|
||||||
|
|
|
||||||
|
|
@ -153,17 +153,17 @@ class Room extends React.PureComponent
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
{ !isElectron() &&
|
{ !isElectron() && false &&
|
||||||
<CookieConsent
|
<CookieConsent
|
||||||
buttonText={
|
buttonText={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id = 'room.consentUnderstand'
|
id='room.consentUnderstand'
|
||||||
defaultMessage = 'I understand'
|
defaultMessage='I understand'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id = 'room.cookieConsent'
|
id='room.cookieConsent'
|
||||||
defaultMessage='This website uses cookies to enhance the user experience'
|
defaultMessage='This website uses cookies to enhance the user experience'
|
||||||
/>
|
/>
|
||||||
</CookieConsent>
|
</CookieConsent>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
BASEDIR=/opt
|
||||||
|
MM=multiparty-meeting
|
||||||
|
NODE_ENV=production
|
||||||
|
SERVER_DEBUG=
|
||||||
|
#SERVER_DEBUG=mediasoup*
|
||||||
|
TAG=latest
|
||||||
|
BRANCH=master
|
||||||
|
#REACT_APP_DEBUG='*'
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
// eslint-disable-next-line
|
||||||
|
var config =
|
||||||
|
{
|
||||||
|
loginEnabled : false,
|
||||||
|
developmentPort : 3443,
|
||||||
|
productionPort : 443,
|
||||||
|
multipartyServer : 'fqdn',
|
||||||
|
turnServers : [
|
||||||
|
{
|
||||||
|
urls : [
|
||||||
|
'turn:example.com:443?transport=tcp'
|
||||||
|
],
|
||||||
|
username : 'example',
|
||||||
|
credential : 'example'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* If defaultResolution is set, it will override user settings when joining:
|
||||||
|
* low ~ 320x240
|
||||||
|
* medium ~ 640x480
|
||||||
|
* high ~ 1280x720
|
||||||
|
* veryhigh ~ 1920x1080
|
||||||
|
* ultra ~ 3840x2560
|
||||||
|
**/
|
||||||
|
defaultResolution : 'medium',
|
||||||
|
// Enable or disable simulcast for webcam video
|
||||||
|
simulcast : true,
|
||||||
|
// Enable or disable simulcast for screen sharing video
|
||||||
|
simulcastSharing : false,
|
||||||
|
// Simulcast encoding layers and levels
|
||||||
|
simulcastEncodings :
|
||||||
|
[
|
||||||
|
{ scaleResolutionDownBy: 4 },
|
||||||
|
{ scaleResolutionDownBy: 2 },
|
||||||
|
{ scaleResolutionDownBy: 1 }
|
||||||
|
],
|
||||||
|
// Socket.io request timeout
|
||||||
|
requestTimeout : 10000,
|
||||||
|
transportOptions :
|
||||||
|
{
|
||||||
|
tcp : true
|
||||||
|
},
|
||||||
|
lastN : 4,
|
||||||
|
mobileLastN : 1,
|
||||||
|
background : 'images/background.jpg',
|
||||||
|
// Add file and uncomment for adding logo to appbar
|
||||||
|
// logo : 'images/logo.svg',
|
||||||
|
title : 'Multiparty meeting',
|
||||||
|
theme :
|
||||||
|
{
|
||||||
|
palette :
|
||||||
|
{
|
||||||
|
primary :
|
||||||
|
{
|
||||||
|
main : '#313131'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
overrides :
|
||||||
|
{
|
||||||
|
MuiAppBar :
|
||||||
|
{
|
||||||
|
colorPrimary :
|
||||||
|
{
|
||||||
|
backgroundColor : '#313131'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MuiFab :
|
||||||
|
{
|
||||||
|
primary :
|
||||||
|
{
|
||||||
|
backgroundColor : '#5F9B2D',
|
||||||
|
'&:hover' :
|
||||||
|
{
|
||||||
|
backgroundColor : '#518029'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
typography :
|
||||||
|
{
|
||||||
|
useNextVariants : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,158 @@
|
||||||
|
const os = require("os");
|
||||||
|
const ifaces = os.networkInterfaces();
|
||||||
|
|
||||||
|
function getListenIps() {
|
||||||
|
let listenIP = [];
|
||||||
|
Object.keys(ifaces).forEach(function (ifname) {
|
||||||
|
var alias = 0;
|
||||||
|
|
||||||
|
ifaces[ifname].forEach(function (iface) {
|
||||||
|
if (
|
||||||
|
(iface.family !== "IPv4" &&
|
||||||
|
(iface.family !== "IPv6" || iface.scopeid !== 0)) ||
|
||||||
|
iface.internal !== false
|
||||||
|
) {
|
||||||
|
// skip over internal (i.e. 127.0.0.1) and non-ipv4 or ipv6 non global addresses
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listenIP.push({ ip: iface.address, announcedIp: null });
|
||||||
|
|
||||||
|
++alias;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return listenIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// oAuth2 conf
|
||||||
|
/* auth :
|
||||||
|
{
|
||||||
|
lti :
|
||||||
|
{
|
||||||
|
consumerKey : '_bo2uqnwon1ym4qkte5hhd4fzlnoufvts5h3hblxzcy',
|
||||||
|
consumerSecret : '_1xpnaa4iw36cwpnx7991e630yo0u4044so1crhvcnz'
|
||||||
|
},
|
||||||
|
oidc:
|
||||||
|
{
|
||||||
|
// The issuer URL for OpenID Connect discovery
|
||||||
|
// The OpenID Provider Configuration Document
|
||||||
|
// could be discovered on:
|
||||||
|
// issuerURL + '/.well-known/openid-configuration'
|
||||||
|
|
||||||
|
issuerURL : 'https://example.com',
|
||||||
|
clientOptions :
|
||||||
|
{
|
||||||
|
client_id : '',
|
||||||
|
client_secret : '',
|
||||||
|
scope : 'openid email profile',
|
||||||
|
// where client.example.com is your multiparty meeting server
|
||||||
|
redirect_uri : 'https://client.example.com/auth/callback'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},*/
|
||||||
|
redisOptions: {},
|
||||||
|
// session cookie secret
|
||||||
|
cookieSecret: "T0P-S3cR3t_cook!e",
|
||||||
|
cookieName: "multiparty-meeting.sid",
|
||||||
|
tls: {
|
||||||
|
cert: `${__dirname}/../certs/cert.pem`,
|
||||||
|
key: `${__dirname}/../certs/privkey.pem`
|
||||||
|
},
|
||||||
|
// Listening port for https server.
|
||||||
|
listeningPort: 443,
|
||||||
|
// Any http request is redirected to https.
|
||||||
|
// Listening port for http server.
|
||||||
|
listeningRedirectPort: 80,
|
||||||
|
// Listens only on http, only on listeningPort
|
||||||
|
// listeningRedirectPort disabled
|
||||||
|
// use case: loadbalancer backend
|
||||||
|
httpOnly: false,
|
||||||
|
// WebServer/Express trust proxy config for httpOnly mode
|
||||||
|
// You can find more info:
|
||||||
|
// - https://expressjs.com/en/guide/behind-proxies.html
|
||||||
|
// - https://www.npmjs.com/package/proxy-addr
|
||||||
|
// use case: loadbalancer backend
|
||||||
|
trustProxy : '',
|
||||||
|
// If this is set to true, only signed-in users will be able
|
||||||
|
// to join a room directly. Non-signed-in users (guests) will
|
||||||
|
// always be put in the lobby regardless of room lock status.
|
||||||
|
// If false, there is no difference between guests and signed-in
|
||||||
|
// users when joining.
|
||||||
|
requireSignInToAccess: false,
|
||||||
|
// This flag has no effect when requireSignInToAccess is false
|
||||||
|
// When truthy, the room will be open to all users when the first
|
||||||
|
// authenticated user has already joined the room.
|
||||||
|
activateOnHostJoin: false,
|
||||||
|
// Mediasoup settings
|
||||||
|
mediasoup: {
|
||||||
|
numWorkers: Object.keys(os.cpus()).length,
|
||||||
|
// mediasoup Worker settings.
|
||||||
|
worker: {
|
||||||
|
logLevel: "warn",
|
||||||
|
logTags: ["info", "ice", "dtls", "rtp", "srtp", "rtcp"],
|
||||||
|
rtcMinPort: 40000,
|
||||||
|
rtcMaxPort: 49999
|
||||||
|
},
|
||||||
|
// mediasoup Router settings.
|
||||||
|
router: {
|
||||||
|
// Router media codecs.
|
||||||
|
mediaCodecs: [
|
||||||
|
{
|
||||||
|
kind: 'audio',
|
||||||
|
mimeType: 'audio/opus',
|
||||||
|
clockRate: 48000,
|
||||||
|
channels: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'video',
|
||||||
|
mimeType: 'video/VP8',
|
||||||
|
clockRate: 90000,
|
||||||
|
parameters:
|
||||||
|
{
|
||||||
|
'x-google-start-bitrate': 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'video',
|
||||||
|
mimeType: 'video/VP9',
|
||||||
|
clockRate: 90000,
|
||||||
|
parameters:
|
||||||
|
{
|
||||||
|
'profile-id': 2,
|
||||||
|
'x-google-start-bitrate': 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'video',
|
||||||
|
mimeType: 'video/h264',
|
||||||
|
clockRate: 90000,
|
||||||
|
parameters:
|
||||||
|
{
|
||||||
|
'packetization-mode': 1,
|
||||||
|
'profile-level-id': '4d0032',
|
||||||
|
'level-asymmetry-allowed': 1,
|
||||||
|
'x-google-start-bitrate': 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'video',
|
||||||
|
mimeType: 'video/h264',
|
||||||
|
clockRate: 90000,
|
||||||
|
parameters:
|
||||||
|
{
|
||||||
|
'packetization-mode': 1,
|
||||||
|
'profile-level-id': '42e01f',
|
||||||
|
'level-asymmetry-allowed': 1,
|
||||||
|
'x-google-start-bitrate': 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// mediasoup WebRtcTransport settings.
|
||||||
|
webRtcTransport: {
|
||||||
|
listenIps: getListenIps(),
|
||||||
|
maxIncomingBitrate: 1500000,
|
||||||
|
initialAvailableOutgoingBitrate: 1000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
BASEDIR=/opt
|
||||||
|
MM=multiparty-meeting
|
||||||
|
NODE_ENV=production
|
||||||
|
SERVER_DEBUG=
|
||||||
|
#SERVER_DEBUG=mediasoup*
|
||||||
|
TAG=latest
|
||||||
|
BRANCH=master
|
||||||
|
#REACT_APP_DEBUG='*'
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Multiparty Meeting => MM
|
||||||
|
MM stand as a shortcut for multiparty-meeting.
|
||||||
|
|
||||||
|
This is the container, or a "dockerized" version of the [multiparty meeting](https://github.com/havfo/multiparty-meeting),
|
||||||
|
and like MM is shortcut, this container is a simillar shortcut that saves time.
|
||||||
|
:)
|
||||||
|
|
||||||
|
## Run it in few easy step.
|
||||||
|
1. Git clone this code to your docker machine.
|
||||||
|
2. Copy your cert in `certs/cert.pem` and `certs/privkey.pem`
|
||||||
|
1. In case you need to generate a new cert and private key, you can use (note -nodes flag, which allows to generate unencrypted private key)
|
||||||
|
```
|
||||||
|
$ openssl req -x509 -newkey rsa:4096 -keyout privkey.pem -out cert.pem -days 365 -nodes
|
||||||
|
```
|
||||||
|
3. **Recomended**: set TURN server and credential in `configs/app/config.js`
|
||||||
|
1. In case you are using coturn, you can generate a user and key with
|
||||||
|
```
|
||||||
|
$ turnadmin -k -u <username> -p <password>
|
||||||
|
```
|
||||||
|
Placeholder looks like
|
||||||
|
```
|
||||||
|
turnServers : [
|
||||||
|
{
|
||||||
|
urls : [
|
||||||
|
'turn:example.com:443?transport=tcp'
|
||||||
|
],
|
||||||
|
username : 'example',
|
||||||
|
credential : 'example'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
You would need to replace example.com by your IP or domain, add the username previously used `<username>` and credential is the code generated by the above mentioned command.
|
||||||
|
|
||||||
|
4. **Optional:** Change other stuff in config:
|
||||||
|
1. **Optional:** replace logo/logo.svg with your company logo svg.
|
||||||
|
2. **Optional:** sort audio/video codecs according to preference.
|
||||||
|
|
||||||
|
## Run:
|
||||||
|
There is two ways
|
||||||
|
1. Simple use `docker run` command
|
||||||
|
```
|
||||||
|
$ sudo ./run.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Or with `docker-compose`
|
||||||
|
/ [install docker compose](https://docs.docker.com/compose/install/) /
|
||||||
|
```
|
||||||
|
$ sudo docker-compose up --detach
|
||||||
|
```
|
||||||
|
## Rebuild
|
||||||
|
|
||||||
|
If you change app-config.js or or something in .env then you have to rebuild the image.
|
||||||
|
```
|
||||||
|
$ sudo docker-compose up --build --detach
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker networking
|
||||||
|
Container works in "host" network mode, because birdge mode has the following issue
|
||||||
|
|
||||||
|
[Docker - Docker hangs when attempting to bind a large number of ports] (https://success.docker.com/article/docker-compose-and-docker-run-hang-when-binding-a-large-port-range)
|
||||||
|
|
||||||
|
|
||||||
|
## Further Informations
|
||||||
|
Read more about configs and settings in [multiparty meeting](https://github.com/havfo/multiparty-meeting) README.
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
// eslint-disable-next-line
|
||||||
|
var config =
|
||||||
|
{
|
||||||
|
loginEnabled : false,
|
||||||
|
developmentPort : 3443,
|
||||||
|
productionPort : 443,
|
||||||
|
multipartyServer : 'fqdn',
|
||||||
|
turnServers : [
|
||||||
|
{
|
||||||
|
urls : [
|
||||||
|
'turn:example.com:443?transport=tcp'
|
||||||
|
],
|
||||||
|
username : 'example',
|
||||||
|
credential : 'example'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* If defaultResolution is set, it will override user settings when joining:
|
||||||
|
* low ~ 320x240
|
||||||
|
* medium ~ 640x480
|
||||||
|
* high ~ 1280x720
|
||||||
|
* veryhigh ~ 1920x1080
|
||||||
|
* ultra ~ 3840x2560
|
||||||
|
**/
|
||||||
|
defaultResolution : 'medium',
|
||||||
|
// Enable or disable simulcast for webcam video
|
||||||
|
simulcast : true,
|
||||||
|
// Enable or disable simulcast for screen sharing video
|
||||||
|
simulcastSharing : false,
|
||||||
|
// Simulcast encoding layers and levels
|
||||||
|
simulcastEncodings :
|
||||||
|
[
|
||||||
|
{ scaleResolutionDownBy: 4 },
|
||||||
|
{ scaleResolutionDownBy: 2 },
|
||||||
|
{ scaleResolutionDownBy: 1 }
|
||||||
|
],
|
||||||
|
// Socket.io request timeout
|
||||||
|
requestTimeout : 10000,
|
||||||
|
transportOptions :
|
||||||
|
{
|
||||||
|
tcp : true
|
||||||
|
},
|
||||||
|
lastN : 4,
|
||||||
|
mobileLastN : 1,
|
||||||
|
background : 'images/background.jpg',
|
||||||
|
// Add file and uncomment for adding logo to appbar
|
||||||
|
// logo : 'images/logo.svg',
|
||||||
|
title : 'Multiparty meeting',
|
||||||
|
theme :
|
||||||
|
{
|
||||||
|
palette :
|
||||||
|
{
|
||||||
|
primary :
|
||||||
|
{
|
||||||
|
main : '#313131'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
overrides :
|
||||||
|
{
|
||||||
|
MuiAppBar :
|
||||||
|
{
|
||||||
|
colorPrimary :
|
||||||
|
{
|
||||||
|
backgroundColor : '#313131'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MuiFab :
|
||||||
|
{
|
||||||
|
primary :
|
||||||
|
{
|
||||||
|
backgroundColor : '#5F9B2D',
|
||||||
|
'&:hover' :
|
||||||
|
{
|
||||||
|
backgroundColor : '#518029'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
typography :
|
||||||
|
{
|
||||||
|
useNextVariants : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,158 @@
|
||||||
|
const os = require("os");
|
||||||
|
const ifaces = os.networkInterfaces();
|
||||||
|
|
||||||
|
function getListenIps() {
|
||||||
|
let listenIP = [];
|
||||||
|
Object.keys(ifaces).forEach(function (ifname) {
|
||||||
|
var alias = 0;
|
||||||
|
|
||||||
|
ifaces[ifname].forEach(function (iface) {
|
||||||
|
if (
|
||||||
|
(iface.family !== "IPv4" &&
|
||||||
|
(iface.family !== "IPv6" || iface.scopeid !== 0)) ||
|
||||||
|
iface.internal !== false
|
||||||
|
) {
|
||||||
|
// skip over internal (i.e. 127.0.0.1) and non-ipv4 or ipv6 non global addresses
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listenIP.push({ ip: iface.address, announcedIp: null });
|
||||||
|
|
||||||
|
++alias;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return listenIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// oAuth2 conf
|
||||||
|
/* auth :
|
||||||
|
{
|
||||||
|
lti :
|
||||||
|
{
|
||||||
|
consumerKey : '_bo2uqnwon1ym4qkte5hhd4fzlnoufvts5h3hblxzcy',
|
||||||
|
consumerSecret : '_1xpnaa4iw36cwpnx7991e630yo0u4044so1crhvcnz'
|
||||||
|
},
|
||||||
|
oidc:
|
||||||
|
{
|
||||||
|
// The issuer URL for OpenID Connect discovery
|
||||||
|
// The OpenID Provider Configuration Document
|
||||||
|
// could be discovered on:
|
||||||
|
// issuerURL + '/.well-known/openid-configuration'
|
||||||
|
|
||||||
|
issuerURL : 'https://example.com',
|
||||||
|
clientOptions :
|
||||||
|
{
|
||||||
|
client_id : '',
|
||||||
|
client_secret : '',
|
||||||
|
scope : 'openid email profile',
|
||||||
|
// where client.example.com is your multiparty meeting server
|
||||||
|
redirect_uri : 'https://client.example.com/auth/callback'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},*/
|
||||||
|
redisOptions: {},
|
||||||
|
// session cookie secret
|
||||||
|
cookieSecret: "T0P-S3cR3t_cook!e",
|
||||||
|
cookieName: "multiparty-meeting.sid",
|
||||||
|
tls: {
|
||||||
|
cert: `${__dirname}/../certs/cert.pem`,
|
||||||
|
key: `${__dirname}/../certs/privkey.pem`
|
||||||
|
},
|
||||||
|
// Listening port for https server.
|
||||||
|
listeningPort: 443,
|
||||||
|
// Any http request is redirected to https.
|
||||||
|
// Listening port for http server.
|
||||||
|
listeningRedirectPort: 80,
|
||||||
|
// Listens only on http, only on listeningPort
|
||||||
|
// listeningRedirectPort disabled
|
||||||
|
// use case: loadbalancer backend
|
||||||
|
httpOnly: false,
|
||||||
|
// WebServer/Express trust proxy config for httpOnly mode
|
||||||
|
// You can find more info:
|
||||||
|
// - https://expressjs.com/en/guide/behind-proxies.html
|
||||||
|
// - https://www.npmjs.com/package/proxy-addr
|
||||||
|
// use case: loadbalancer backend
|
||||||
|
trustProxy : '',
|
||||||
|
// If this is set to true, only signed-in users will be able
|
||||||
|
// to join a room directly. Non-signed-in users (guests) will
|
||||||
|
// always be put in the lobby regardless of room lock status.
|
||||||
|
// If false, there is no difference between guests and signed-in
|
||||||
|
// users when joining.
|
||||||
|
requireSignInToAccess: false,
|
||||||
|
// This flag has no effect when requireSignInToAccess is false
|
||||||
|
// When truthy, the room will be open to all users when the first
|
||||||
|
// authenticated user has already joined the room.
|
||||||
|
activateOnHostJoin: false,
|
||||||
|
// Mediasoup settings
|
||||||
|
mediasoup: {
|
||||||
|
numWorkers: Object.keys(os.cpus()).length,
|
||||||
|
// mediasoup Worker settings.
|
||||||
|
worker: {
|
||||||
|
logLevel: "warn",
|
||||||
|
logTags: ["info", "ice", "dtls", "rtp", "srtp", "rtcp"],
|
||||||
|
rtcMinPort: 40000,
|
||||||
|
rtcMaxPort: 49999
|
||||||
|
},
|
||||||
|
// mediasoup Router settings.
|
||||||
|
router: {
|
||||||
|
// Router media codecs.
|
||||||
|
mediaCodecs: [
|
||||||
|
{
|
||||||
|
kind: 'audio',
|
||||||
|
mimeType: 'audio/opus',
|
||||||
|
clockRate: 48000,
|
||||||
|
channels: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'video',
|
||||||
|
mimeType: 'video/VP8',
|
||||||
|
clockRate: 90000,
|
||||||
|
parameters:
|
||||||
|
{
|
||||||
|
'x-google-start-bitrate': 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'video',
|
||||||
|
mimeType: 'video/VP9',
|
||||||
|
clockRate: 90000,
|
||||||
|
parameters:
|
||||||
|
{
|
||||||
|
'profile-id': 2,
|
||||||
|
'x-google-start-bitrate': 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'video',
|
||||||
|
mimeType: 'video/h264',
|
||||||
|
clockRate: 90000,
|
||||||
|
parameters:
|
||||||
|
{
|
||||||
|
'packetization-mode': 1,
|
||||||
|
'profile-level-id': '4d0032',
|
||||||
|
'level-asymmetry-allowed': 1,
|
||||||
|
'x-google-start-bitrate': 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'video',
|
||||||
|
mimeType: 'video/h264',
|
||||||
|
clockRate: 90000,
|
||||||
|
parameters:
|
||||||
|
{
|
||||||
|
'packetization-mode': 1,
|
||||||
|
'profile-level-id': '42e01f',
|
||||||
|
'level-asymmetry-allowed': 1,
|
||||||
|
'x-google-start-bitrate': 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// mediasoup WebRtcTransport settings.
|
||||||
|
webRtcTransport: {
|
||||||
|
listenIps: getListenIps(),
|
||||||
|
maxIncomingBitrate: 1500000,
|
||||||
|
initialAvailableOutgoingBitrate: 1000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
version: "3.3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
# multiparty-meeting
|
||||||
|
mm:
|
||||||
|
env_file: .env
|
||||||
|
image: misi/mm:${TAG}
|
||||||
|
build:
|
||||||
|
args:
|
||||||
|
- BASEDIR=${BASEDIR}
|
||||||
|
- MM=${MM}
|
||||||
|
- NODE_ENV=${NODE_ENV}
|
||||||
|
- SERVER_DEBUG=${SERVER_DEBUG}
|
||||||
|
context: ./
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./configs/server:${BASEDIR}/${MM}/server/config
|
||||||
|
- ./configs/app:${BASEDIR}/${MM}/server/public/config
|
||||||
|
- ./certs:${BASEDIR}/${MM}/server/certs
|
||||||
|
- ./images:${BASEDIR}/${MM}/server/public/images
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- "40000-49999:40000-49999/udp"
|
||||||
|
network_mode: "host"
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
network_mode: "host"
|
||||||
|
entrypoint: redis-server /usr/local/etc/redis/redis.conf
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./configs/redis:/usr/local/etc/redis
|
||||||
|
ouroboros:
|
||||||
|
container_name: ouroboros
|
||||||
|
hostname: ouroboros
|
||||||
|
image: pyouroboros/ouroboros
|
||||||
|
environment:
|
||||||
|
- CLEANUP=true
|
||||||
|
- INTERVAL=300
|
||||||
|
- LOG_LEVEL=info
|
||||||
|
- SELF_UPDATE=true
|
||||||
|
- IGNORE=mongo influxdb postgres mariadb
|
||||||
|
- TZ=Europe/Budapest
|
||||||
|
- CRON="* 2 * * *"
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
|
|
@ -0,0 +1,79 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="81mm"
|
||||||
|
height="30mm"
|
||||||
|
viewBox="0 0 81 29.999998"
|
||||||
|
version="1.1"
|
||||||
|
id="svg3719"
|
||||||
|
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||||
|
sodipodi:docname="your_logo_here.svg">
|
||||||
|
<defs
|
||||||
|
id="defs3713" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.1935547"
|
||||||
|
inkscape:cx="112.68799"
|
||||||
|
inkscape:cy="95.311132"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer3"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
units="mm"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1020"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="444"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata3716">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
transform="translate(0,14.125)">
|
||||||
|
<rect
|
||||||
|
style="fill:#ff5555;fill-opacity:1;stroke-width:0.23147361"
|
||||||
|
id="rect3830"
|
||||||
|
width="79.138596"
|
||||||
|
height="23.497742"
|
||||||
|
x="0.93070221"
|
||||||
|
y="-10.873871"
|
||||||
|
ry="6.3722677" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.28888893px;line-height:125%;font-family:'Noto Sans Ethiopic';-inkscape-font-specification:'Noto Sans Ethiopic';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="7.4713254"
|
||||||
|
y="3.1760001"
|
||||||
|
id="text3760"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3758"
|
||||||
|
x="7.4713254"
|
||||||
|
y="3.1760001"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.28888893px;font-family:Chilanka;-inkscape-font-specification:Chilanka;fill:#ffffff;stroke-width:0.26458332px">{ your logo } </tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Container starting up..."
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd /opt/multiparty-meeting/server
|
||||||
|
ls -la
|
||||||
|
echo ".............."
|
||||||
|
ls -la /opt
|
||||||
|
echo ".............."
|
||||||
|
ls -la /opt/multiparty-meeting
|
||||||
|
node /opt/multiparty-meeting/server/server.js
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
|
|
@ -0,0 +1,79 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="81mm"
|
||||||
|
height="30mm"
|
||||||
|
viewBox="0 0 81 29.999998"
|
||||||
|
version="1.1"
|
||||||
|
id="svg3719"
|
||||||
|
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||||
|
sodipodi:docname="your_logo_here.svg">
|
||||||
|
<defs
|
||||||
|
id="defs3713" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.1935547"
|
||||||
|
inkscape:cx="112.68799"
|
||||||
|
inkscape:cy="95.311132"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer3"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
units="mm"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1020"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="444"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata3716">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
transform="translate(0,14.125)">
|
||||||
|
<rect
|
||||||
|
style="fill:#ff5555;fill-opacity:1;stroke-width:0.23147361"
|
||||||
|
id="rect3830"
|
||||||
|
width="79.138596"
|
||||||
|
height="23.497742"
|
||||||
|
x="0.93070221"
|
||||||
|
y="-10.873871"
|
||||||
|
ry="6.3722677" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.28888893px;line-height:125%;font-family:'Noto Sans Ethiopic';-inkscape-font-specification:'Noto Sans Ethiopic';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="7.4713254"
|
||||||
|
y="3.1760001"
|
||||||
|
id="text3760"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3758"
|
||||||
|
x="7.4713254"
|
||||||
|
y="3.1760001"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.28888893px;font-family:Chilanka;-inkscape-font-specification:Chilanka;fill:#ffffff;stroke-width:0.26458332px">{ your logo } </tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
Loading…
Reference in New Issue