openvidu-server recording layout updated to use StreamManager API
This commit is contained in:
parent
2f2a42c439
commit
9e79fe351e
@ -4,7 +4,7 @@ MAINTAINER openvidu@gmail.com
|
||||
# Install Chrome
|
||||
RUN apt-get update && apt-get install -y wget
|
||||
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
|
||||
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list && \
|
||||
echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" | tee /etc/apt/sources.list.d/google-chrome.list && \
|
||||
apt-get update && apt-get install -y google-chrome-stable
|
||||
|
||||
# Install media packages
|
||||
@ -25,4 +25,3 @@ RUN ["chmod", "+x", "/entrypoint.sh"]
|
||||
RUN mkdir /recordings
|
||||
|
||||
ENTRYPOINT /entrypoint.sh
|
||||
|
||||
|
||||
@ -11,8 +11,8 @@ fi
|
||||
URL=${URL:-https://www.youtube.com/watch?v=JMuzlEQz3uo}
|
||||
RESOLUTION=${RESOLUTION:-1920x1080}
|
||||
FRAMERATE=${FRAMERATE:-24}
|
||||
VIDEO_SIZE=$RESOLUTION
|
||||
ARRAY=(${VIDEO_SIZE//x/ })
|
||||
WIDTH="$(cut -d'x' -f1 <<< $RESOLUTION)"
|
||||
HEIGHT="$(cut -d'x' -f2 <<< $RESOLUTION)"
|
||||
VIDEO_ID=${VIDEO_ID:-video}
|
||||
VIDEO_NAME=${VIDEO_NAME:-video}
|
||||
VIDEO_FORMAT=${VIDEO_FORMAT:-mp4}
|
||||
@ -21,8 +21,8 @@ RECORDING_JSON="${RECORDING_JSON}"
|
||||
export URL
|
||||
export RESOLUTION
|
||||
export FRAMERATE
|
||||
export VIDEO_SIZE
|
||||
export ARRAY
|
||||
export WIDTH
|
||||
export HEIGHT
|
||||
export VIDEO_ID
|
||||
export VIDEO_NAME
|
||||
export VIDEO_FORMAT
|
||||
@ -83,7 +83,7 @@ touch xvfb.log
|
||||
chmod 777 xvfb.log
|
||||
|
||||
function3() {
|
||||
xvfb-run --server-num=${DISPLAY_NUM} --server-args="-ac -screen 0 ${RESOLUTION}x24 -noreset" google-chrome -no-sandbox -test-type -disable-infobars -window-size=${ARRAY[0]},${ARRAY[1]} -no-first-run -ignore-certificate-errors --kiosk $URL &> xvfb.log &
|
||||
xvfb-run --server-num=${DISPLAY_NUM} --server-args="-ac -screen 0 ${RESOLUTION}x24 -noreset" google-chrome -start-maximized -no-sandbox -test-type -disable-infobars -window-size=$WIDTH,$HEIGHT -no-first-run -ignore-certificate-errors --kiosk $URL &> xvfb.log &
|
||||
}
|
||||
export -f function3
|
||||
if [[ $CURRENT_UID != $USER_ID ]]; then
|
||||
|
||||
@ -2,7 +2,7 @@ FROM ubuntu:16.04
|
||||
MAINTAINER openvidu@gmail.com
|
||||
|
||||
# Install Kurento Media Server (KMS)
|
||||
RUN echo "deb http://ubuntu.openvidu.io/6.7.0 xenial kms6" | tee /etc/apt/sources.list.d/kurento.list \
|
||||
RUN echo "deb http://ubuntu.openvidu.io/6.7.2 xenial kms6" | tee /etc/apt/sources.list.d/kurento.list \
|
||||
&& apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5AFA7A83 \
|
||||
&& apt-get update \
|
||||
&& apt-get -y dist-upgrade \
|
||||
|
||||
@ -17,6 +17,7 @@ import { DashboardComponent } from './components/dashboard/dashboard.component';
|
||||
import { SessionDetailsComponent } from './components/session-details/session-details.component';
|
||||
import { CredentialsDialogComponent } from './components/dashboard/credentials-dialog.component';
|
||||
import { LayoutBestFitComponent } from './components/layouts/layout-best-fit/layout-best-fit.component';
|
||||
import { OpenViduVideoComponent } from './components/layouts/ov-video.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
@ -26,6 +27,7 @@ import { LayoutBestFitComponent } from './components/layouts/layout-best-fit/lay
|
||||
SessionDetailsComponent,
|
||||
CredentialsDialogComponent,
|
||||
LayoutBestFitComponent,
|
||||
OpenViduVideoComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
<div id="layout" class="bounds">
|
||||
<div *ngFor="let s of streams" class="OT_root OT_publisher custom-class">
|
||||
<div *ngFor="let s of subscribers" class="OT_root OT_publisher custom-class">
|
||||
<div class="OT_widget-container">
|
||||
<video [id]="'native-video-' + s.streamId" autoplay="true" [srcObject]="s.getMediaStream()" (playing)="onVideoPlaying($event)"></video>
|
||||
<app-ov-video [subscriber]="s"></app-ov-video>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, OnInit, OnDestroy, HostListener, ViewEncapsulation, ApplicationRef } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { OpenVidu, Session, Stream, Subscriber, StreamEvent } from 'openvidu-browser';
|
||||
import { OpenVidu, Session, Stream, Subscriber, StreamEvent, StreamManagerEvent } from 'openvidu-browser';
|
||||
|
||||
import { OpenViduLayout } from '../openvidu-layout';
|
||||
|
||||
@ -17,7 +17,7 @@ export class LayoutBestFitComponent implements OnInit, OnDestroy {
|
||||
secret: string;
|
||||
|
||||
session: Session;
|
||||
streams: Stream[] = [];
|
||||
subscribers: Subscriber[] = [];
|
||||
|
||||
layout: any;
|
||||
resizeTimeout;
|
||||
@ -51,13 +51,17 @@ export class LayoutBestFitComponent implements OnInit, OnDestroy {
|
||||
this.session = OV.initSession();
|
||||
|
||||
this.session.on('streamCreated', (event: StreamEvent) => {
|
||||
const subscriber: Subscriber = this.session.subscribe(event.stream, '');
|
||||
this.addRemoteStream(event.stream);
|
||||
const subscriber: Subscriber = this.session.subscribe(event.stream, undefined);
|
||||
subscriber.on('streamPlaying', (e: StreamManagerEvent) => {
|
||||
const video: HTMLVideoElement = subscriber.videos[0].video;
|
||||
video.parentElement.parentElement.classList.remove('custom-class');
|
||||
this.openviduLayout.updateLayout();
|
||||
});
|
||||
this.addSubscriber(subscriber);
|
||||
});
|
||||
|
||||
this.session.on('streamDestroyed', (event: StreamEvent) => {
|
||||
event.preventDefault();
|
||||
this.deleteRemoteStream(event.stream);
|
||||
this.deleteSubscriber(<Subscriber>event.stream.streamManager);
|
||||
this.openviduLayout.updateLayout();
|
||||
});
|
||||
|
||||
@ -83,36 +87,29 @@ export class LayoutBestFitComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
private addRemoteStream(stream: Stream): void {
|
||||
this.streams.push(stream);
|
||||
private addSubscriber(subscriber: Subscriber): void {
|
||||
this.subscribers.push(subscriber);
|
||||
this.appRef.tick();
|
||||
}
|
||||
|
||||
private deleteRemoteStream(stream: Stream): void {
|
||||
private deleteSubscriber(subscriber: Subscriber): void {
|
||||
let index = -1;
|
||||
for (let i = 0; i < this.streams.length; i++) {
|
||||
if (this.streams[i].streamId === stream.streamId) {
|
||||
for (let i = 0; i < this.subscribers.length; i++) {
|
||||
if (this.subscribers[i] === subscriber) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index > -1) {
|
||||
this.streams.splice(index, 1);
|
||||
this.subscribers.splice(index, 1);
|
||||
}
|
||||
this.appRef.tick();
|
||||
}
|
||||
|
||||
leaveSession() {
|
||||
if (this.session) { this.session.disconnect(); };
|
||||
this.streams = [];
|
||||
this.subscribers = [];
|
||||
this.session = null;
|
||||
}
|
||||
|
||||
onVideoPlaying(event) {
|
||||
const video: HTMLVideoElement = event.target;
|
||||
video.parentElement.parentElement.classList.remove('custom-class');
|
||||
this.openviduLayout.updateLayout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
import { Component, Input, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
|
||||
import { Subscriber } from 'openvidu-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'app-ov-video',
|
||||
template: '<video #videoElement></video>'
|
||||
})
|
||||
export class OpenViduVideoComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild('videoElement') elementRef: ElementRef;
|
||||
|
||||
_subscriber: Subscriber;
|
||||
|
||||
ngAfterViewInit() {
|
||||
this._subscriber.addVideoElement(this.elementRef.nativeElement);
|
||||
}
|
||||
|
||||
@Input()
|
||||
set subscriber(subscriber: Subscriber) {
|
||||
this._subscriber = subscriber;
|
||||
if (!!this.elementRef) {
|
||||
this._subscriber.addVideoElement(this.elementRef.nativeElement);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -208,7 +208,6 @@ public class OpenViduServer implements JsonRpcConfigurer {
|
||||
default:
|
||||
|
||||
URL url = new URL(publicUrl);
|
||||
int port = url.getPort();
|
||||
|
||||
type = "custom";
|
||||
|
||||
@ -223,11 +222,6 @@ public class OpenViduServer implements JsonRpcConfigurer {
|
||||
if (!OpenViduServer.publicUrl.startsWith("wss://")) {
|
||||
OpenViduServer.publicUrl = "wss://" + OpenViduServer.publicUrl;
|
||||
}
|
||||
if (port == -1) {
|
||||
OpenViduServer.publicUrl += ":" + openviduConf.getServerPort();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (OpenViduServer.publicUrl == null) {
|
||||
|
||||
@ -2,7 +2,7 @@ spring.profiles.active=docker
|
||||
|
||||
server.address: 0.0.0.0
|
||||
server.ssl.enabled: true
|
||||
openvidu.recording.version: 2.0.1
|
||||
openvidu.recording.version: 2.1.0
|
||||
|
||||
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ spring.profiles.active=ngrok
|
||||
server.port: 5000
|
||||
server.address: 0.0.0.0
|
||||
server.ssl.enabled: false
|
||||
openvidu.recording.version: 2.0.1
|
||||
openvidu.recording.version: 2.1.0
|
||||
|
||||
kms.uris=[\"ws://localhost:8888/kurento\"]
|
||||
openvidu.secret: MY_SECRET
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
server.address: 0.0.0.0
|
||||
server.ssl.enabled: true
|
||||
openvidu.recording.version: 2.0.1
|
||||
openvidu.recording.version: 2.1.0
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
{"version":3,"sources":["webpack/bootstrap 347280613b71b908df0e"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAY,2BAA2B;AACvC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA,kDAA0C,oBAAoB,WAAW","file":"inline.bundle.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t\"inline\": 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 347280613b71b908df0e"],"sourceRoot":"webpack:///"}
|
||||
{"version":3,"sources":["webpack/bootstrap 20d6fb8adf9ed6d01cc2"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAY,2BAA2B;AACvC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA,kDAA0C,oBAAoB,WAAW","file":"inline.bundle.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t\"inline\": 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 20d6fb8adf9ed6d01cc2"],"sourceRoot":"webpack:///"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user