Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08b1dd0ba0 | ||
|
|
5c2a3a1fa5 | ||
|
|
67cc21b1fa | ||
|
|
c1a9c715a4 | ||
|
|
ce2e4eb836 | ||
|
|
9e81f203cb | ||
|
|
4a88f47af5 | ||
|
|
3f44579508 | ||
|
|
18490b0496 | ||
|
|
f0d1db9044 | ||
|
|
eaacb94c54 | ||
|
|
352138dfef | ||
|
|
3f90be8598 | ||
|
|
05649aa2fd | ||
|
|
f54adc6b94 | ||
|
|
625b080752 | ||
|
|
1920eb583c | ||
|
|
8be8128d6e | ||
|
|
88826db4fd | ||
|
|
6154b9b734 | ||
|
|
3d02d3a79b | ||
|
|
58d0292ef9 | ||
|
|
1f04169aa5 | ||
|
|
c128f1d3f2 | ||
|
|
fdfa0d8f6f | ||
|
|
9d666e0879 | ||
|
|
6f5ecf878c | ||
|
|
486d64ff19 | ||
|
|
9277f04b4b | ||
|
|
f4708c23f0 | ||
|
|
a87ad7d614 | ||
|
|
8709d37738 | ||
|
|
9fad572ec0 | ||
|
|
1ab3e39ba0 | ||
|
|
ec7cc4bc47 | ||
|
|
f53be95e70 | ||
|
|
1e86878d75 |
29
CHANGELOG.md
29
CHANGELOG.md
@ -1,5 +1,34 @@
|
||||
# Restreamer-UI
|
||||
|
||||
## v1.13.0 > v1.14.0
|
||||
|
||||
- Add wettercom service
|
||||
- Add option to select which channels will be displayed on the playersite ([#392](https://github.com/datarhei/restreamer/issues/392), [#800](https://github.com/datarhei/restreamer/issues/800))
|
||||
- Mod updates public videojs >v8
|
||||
- Fix erroneous filter setting
|
||||
- Fix encoded address
|
||||
- Fix double -filter parameter when encoder sets filter
|
||||
- Fix Docker build ([#64](https://github.com/datarhei/restreamer-ui/issues/64))
|
||||
|
||||
## v1.12.0 > v1.13.0
|
||||
|
||||
- Add to allow stream hints in case probing fails
|
||||
- Mod enables ff-loglevel and prepares the logging component
|
||||
- Mod uses official Instagram-RTMP target
|
||||
- Mod Remove unused imports
|
||||
- Mod Update translations
|
||||
- Mod updates dep.
|
||||
- Fix player position
|
||||
- Fix missing stream URL, summarize streams in probe log, don't lock type for first stream
|
||||
|
||||
## v1.11.0 > v1.12.0
|
||||
|
||||
- Add option to select different SRT stream in wizard
|
||||
- Add option to select different RTMP stream in wizard
|
||||
- Fix selecting other than first audio stream ([#710](https://github.com/datarhei/restreamer/issues/710))
|
||||
- Fix reset of previous audio settings when editing profile ([#730](https://github.com/datarhei/restreamer/issues/730))
|
||||
- Fix RTMP URL for receive mode
|
||||
|
||||
## v1.10.0 > v1.11.0
|
||||
|
||||
- Add allow to stream HEVC and AV1 to Youtube via RTMP
|
||||
|
||||
17
Dockerfile
17
Dockerfile
@ -1,22 +1,17 @@
|
||||
ARG NODE_IMAGE=node:21-alpine3.17
|
||||
ARG CADDY_IMAGE=caddy:2.7.5-alpine
|
||||
ARG NODE_IMAGE=node:21-alpine3.20
|
||||
ARG CADDY_IMAGE=caddy:2.8.4-alpine
|
||||
|
||||
FROM $NODE_IMAGE as builder
|
||||
FROM $NODE_IMAGE AS builder
|
||||
|
||||
ARG NODE_SPACE_SIZE=10240
|
||||
ENV NODE_OPTIONS="--openssl-legacy-provider --max-old-space-size=$NODE_SPACE_SIZE"
|
||||
|
||||
ENV PUBLIC_URL "./"
|
||||
ENV PUBLIC_URL="./"
|
||||
|
||||
COPY . /ui
|
||||
|
||||
WORKDIR /ui
|
||||
|
||||
RUN cd /ui && \
|
||||
yarn set version berry && \
|
||||
yarn config set httpTimeout 600000 && \
|
||||
yarn install && \
|
||||
yarn run build
|
||||
yarn install && \
|
||||
yarn build
|
||||
|
||||
FROM $CADDY_IMAGE
|
||||
|
||||
|
||||
72
package.json
72
package.json
@ -1,52 +1,52 @@
|
||||
{
|
||||
"name": "restreamer-ui",
|
||||
"version": "1.11.0",
|
||||
"bundle": "restreamer-v2.9.0",
|
||||
"version": "1.14.0",
|
||||
"bundle": "restreamer-v2.12.0",
|
||||
"private": false,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@auth0/auth0-spa-js": "^2.1.3",
|
||||
"@babel/plugin-syntax-flow": "^7.23.3",
|
||||
"@babel/plugin-transform-react-jsx": "^7.23.4",
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@fontsource/dosis": "^5.0.18",
|
||||
"@fontsource/roboto": "^5.0.8",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@lingui/core": "^4.7.0",
|
||||
"@lingui/macro": "^4.7.0",
|
||||
"@lingui/react": "^4.7.0",
|
||||
"@mui/icons-material": "^5.15.6",
|
||||
"@mui/lab": "^5.0.0-alpha.162",
|
||||
"@mui/material": "^5.15.6",
|
||||
"@mui/styles": "^5.15.6",
|
||||
"@testing-library/dom": "^9.3.4",
|
||||
"@testing-library/jest-dom": "^6.3.0",
|
||||
"@testing-library/react": "^14.1.2",
|
||||
"@babel/plugin-syntax-flow": "^7.24.7",
|
||||
"@babel/plugin-transform-react-jsx": "^7.25.2",
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@emotion/styled": "^11.13.0",
|
||||
"@fontsource/dosis": "^5.0.21",
|
||||
"@fontsource/roboto": "^5.0.14",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.6.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.6.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@lingui/core": "^4.11.4",
|
||||
"@lingui/macro": "^4.11.4",
|
||||
"@lingui/react": "^4.11.4",
|
||||
"@mui/icons-material": "^6.0.1",
|
||||
"@mui/lab": "^6.0.0-beta.8",
|
||||
"@mui/material": "^6.0.1",
|
||||
"@mui/styles": "^6.0.1",
|
||||
"@testing-library/dom": "^10.4.0",
|
||||
"@testing-library/jest-dom": "^6.5.0",
|
||||
"@testing-library/react": "^16.0.1",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@types/react": "^18.2.48",
|
||||
"@types/react": "^18.3.5",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint": "^9.9.1",
|
||||
"handlebars": "^4.7.8",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"make-plural": "^7.3.0",
|
||||
"react": "^18.2.0",
|
||||
"make-plural": "^7.4.0",
|
||||
"react": "^18.3.1",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"react-router-dom": "^6.26.1",
|
||||
"react-scripts": "^5.0.1",
|
||||
"semver": "^7.5.4",
|
||||
"serve": "^14.2.1",
|
||||
"typescript": "^5.3.3",
|
||||
"semver": "^7.6.3",
|
||||
"serve": "^14.2.3",
|
||||
"typescript": "^5.5.4",
|
||||
"url-parse": "^1.5.10",
|
||||
"util": "^0.12.5",
|
||||
"uuid": "^9.0.1",
|
||||
"video.js": "^8.10.0",
|
||||
"uuid": "^10.0.0",
|
||||
"video.js": "^8.17.3",
|
||||
"videojs-overlay": "^3.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
@ -86,12 +86,12 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.9",
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@lingui/cli": "^4.7.0",
|
||||
"@lingui/cli": "^4.11.4",
|
||||
"babel-core": "^6.26.3",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"prettier": "^3.2.4",
|
||||
"prettier": "^3.3.3",
|
||||
"react-error-overlay": "^6.0.11"
|
||||
},
|
||||
"resolutions": {}
|
||||
|
||||
778
public/_player/videojs/dist/video-js.css
vendored
778
public/_player/videojs/dist/video-js.css
vendored
File diff suppressed because one or more lines are too long
2
public/_player/videojs/dist/video-js.min.css
vendored
2
public/_player/videojs/dist/video-js.min.css
vendored
File diff suppressed because one or more lines are too long
46801
public/_player/videojs/dist/video.js
vendored
46801
public/_player/videojs/dist/video.js
vendored
File diff suppressed because one or more lines are too long
56
public/_player/videojs/dist/video.min.js
vendored
56
public/_player/videojs/dist/video.min.js
vendored
File diff suppressed because one or more lines are too long
1
public/_player/videojs/dist/videojs-airplay.css
vendored
Normal file
1
public/_player/videojs/dist/videojs-airplay.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.vjs-airplay-button .vjs-icon-placeholder{background:url("ic_airplay_white_24px.svg") center center no-repeat;background-size:contain;display:inline-block;width:12px;height:12px}.vjs-airplay-button:hover{cursor:pointer}.vjs-airplay-button:hover .vjs-icon-placeholder{background-image:url("ic_airplay_white_24px.svg")}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden){display:flex;align-items:center;width:auto;padding:0 4px}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden) .vjs-airplay-button-label{flex-grow:1;margin-left:4px}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden) .vjs-icon-placeholder{flex-grow:1}
|
||||
308
public/_player/videojs/dist/videojs-airplay.js
vendored
Normal file
308
public/_player/videojs/dist/videojs-airplay.js
vendored
Normal file
@ -0,0 +1,308 @@
|
||||
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
var hasAirPlayAPISupport = require('../lib/hasAirPlayAPISupport');
|
||||
|
||||
/**
|
||||
* Registers the AirPlayButton Component with Video.js. Calls
|
||||
* {@link http://docs.videojs.com/Component.html#.registerComponent}, which will add a
|
||||
* component called `airPlayButton` to the list of globally registered Video.js
|
||||
* components. The `airPlayButton` is added to the player's control bar UI automatically
|
||||
* once {@link module:enableAirPlay} has been called. If you would like to specify the
|
||||
* order of the buttons that appear in the control bar, including this button, you can do
|
||||
* so in the options that you pass to the `videojs` function when creating a player:
|
||||
*
|
||||
* ```
|
||||
* videojs('playerID', {
|
||||
* controlBar: {
|
||||
* children: [
|
||||
* 'playToggle',
|
||||
* 'progressControl',
|
||||
* 'volumePanel',
|
||||
* 'fullscreenToggle',
|
||||
* 'airPlayButton',
|
||||
* ],
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param videojs {object} A reference to {@link http://docs.videojs.com/module-videojs.html|Video.js}
|
||||
* @see http://docs.videojs.com/module-videojs.html#~registerPlugin
|
||||
*/
|
||||
module.exports = function (videojs) {
|
||||
/**
|
||||
* The AirPlayButton module contains both the AirPlayButton class definition and the
|
||||
* function used to register the button as a Video.js Component.
|
||||
*
|
||||
* @module AirPlayButton
|
||||
*/
|
||||
|
||||
const ButtonComponent = videojs.getComponent('Button');
|
||||
|
||||
/**
|
||||
* The Video.js Button class is the base class for UI button components.
|
||||
*
|
||||
* @external Button
|
||||
* @see {@link http://docs.videojs.com/Button.html|Button}
|
||||
*/
|
||||
|
||||
/** @lends AirPlayButton.prototype */
|
||||
class AirPlayButton extends ButtonComponent {
|
||||
/**
|
||||
* This class is a button component designed to be displayed in the
|
||||
* player UI's control bar. It displays an Apple AirPlay selection
|
||||
* list when clicked.
|
||||
*
|
||||
* @constructs
|
||||
* @extends external:Button
|
||||
*/
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
if (!hasAirPlayAPISupport()) {
|
||||
this.hide();
|
||||
}
|
||||
this._reactToAirPlayAvailableEvents();
|
||||
if (options.addAirPlayLabelToButton) {
|
||||
this.el().classList.add('vjs-airplay-button-lg');
|
||||
this._labelEl = document.createElement('span');
|
||||
this._labelEl.classList.add('vjs-airplay-button-label');
|
||||
this._labelEl.textContent = this.localize('AirPlay');
|
||||
this.el().appendChild(this._labelEl);
|
||||
} else {
|
||||
this.controlText('Start AirPlay');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Button#buildCSSClass to return the classes used on the button element.
|
||||
*
|
||||
* @param {DOMElement} el
|
||||
* @see {@link http://docs.videojs.com/Button.html#buildCSSClass|Button#buildCSSClass}
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return 'vjs-airplay-button ' + super.buildCSSClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Button#handleClick to handle button click events. AirPlay
|
||||
* functionality is handled outside of this class, which should be limited
|
||||
* to UI related logic. This function simply triggers an event on the player.
|
||||
*
|
||||
* @fires AirPlayButton#airPlayRequested
|
||||
* @param {DOMElement} el
|
||||
* @see {@link http://docs.videojs.com/Button.html#handleClick|Button#handleClick}
|
||||
*/
|
||||
handleClick() {
|
||||
this.player().trigger('airPlayRequested');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying DOMElement used by the player.
|
||||
*
|
||||
* @private
|
||||
* @returns {DOMElement} either an <audio> or <video> tag, depending on the type of
|
||||
* player
|
||||
*/
|
||||
_getMediaEl() {
|
||||
var playerEl = this.player().el();
|
||||
return playerEl.querySelector('video, audio');
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a listener to the `webkitplaybacktargetavailabilitychanged` event, if it is
|
||||
* supported, that will show or hide this button Component based on the availability
|
||||
* of the AirPlay function.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_reactToAirPlayAvailableEvents() {
|
||||
var mediaEl = this._getMediaEl(),
|
||||
self = this;
|
||||
if (!mediaEl || !hasAirPlayAPISupport()) {
|
||||
return;
|
||||
}
|
||||
function onTargetAvailabilityChanged(event) {
|
||||
if (event.availability === 'available') {
|
||||
self.show();
|
||||
} else {
|
||||
self.hide();
|
||||
}
|
||||
}
|
||||
mediaEl.addEventListener('webkitplaybacktargetavailabilitychanged', onTargetAvailabilityChanged);
|
||||
this.on('dispose', function () {
|
||||
mediaEl.removeEventListener('webkitplaybacktargetavailabilitychanged', onTargetAvailabilityChanged);
|
||||
});
|
||||
}
|
||||
}
|
||||
videojs.registerComponent('airPlayButton', AirPlayButton);
|
||||
};
|
||||
|
||||
},{"../lib/hasAirPlayAPISupport":4}],2:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @module enableAirPlay
|
||||
*/
|
||||
|
||||
var hasAirPlayAPISupport = require('./lib/hasAirPlayAPISupport');
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {object} the Video.js Player instance
|
||||
* @returns {AirPlayButton} or `undefined` if it does not exist
|
||||
*/
|
||||
function getExistingAirPlayButton(player) {
|
||||
return player.controlBar.getChild('airPlayButton');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the AirPlayButton Component to the player's ControlBar component, if the
|
||||
* AirPlayButton does not already exist in the ControlBar.
|
||||
* @private
|
||||
* @param player {object} the Video.js Player instance
|
||||
* @param options {object}
|
||||
*/
|
||||
function ensureAirPlayButtonExists(player, options) {
|
||||
var existingAirPlayButton = getExistingAirPlayButton(player),
|
||||
indexOpt;
|
||||
if (options.addButtonToControlBar && !existingAirPlayButton) {
|
||||
// Figure out AirPlay button's index
|
||||
indexOpt = player.controlBar.children().length;
|
||||
if (typeof options.buttonPositionIndex !== 'undefined') {
|
||||
indexOpt = options.buttonPositionIndex >= 0 ? options.buttonPositionIndex : player.controlBar.children().length + options.buttonPositionIndex;
|
||||
}
|
||||
player.controlBar.addChild('airPlayButton', options, indexOpt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles requests for AirPlay triggered by the AirPlayButton Component.
|
||||
*
|
||||
* @private
|
||||
* @param player {object} the Video.js Player instance
|
||||
*/
|
||||
function onAirPlayRequested(player) {
|
||||
var mediaEl = player.el().querySelector('video, audio');
|
||||
if (mediaEl && mediaEl.webkitShowPlaybackTargetPicker) {
|
||||
mediaEl.webkitShowPlaybackTargetPicker();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event listener for the `airPlayRequested` event triggered by the AirPlayButton
|
||||
* Component.
|
||||
*
|
||||
* @private
|
||||
* @param player {object} the Video.js Player instance
|
||||
*/
|
||||
function listenForAirPlayEvents(player) {
|
||||
// Respond to requests for AirPlay. The AirPlayButton component triggers this event
|
||||
// when the user clicks the AirPlay button.
|
||||
player.on('airPlayRequested', onAirPlayRequested.bind(null, player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the AirPlay plugin.
|
||||
*
|
||||
* @private
|
||||
* @param player {object} the Video.js player
|
||||
* @param options {object} the plugin options
|
||||
*/
|
||||
function enableAirPlay(player, options) {
|
||||
if (!player.controlBar) {
|
||||
return;
|
||||
}
|
||||
if (hasAirPlayAPISupport()) {
|
||||
listenForAirPlayEvents(player);
|
||||
ensureAirPlayButtonExists(player, options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the AirPlay plugin with Video.js. Calls
|
||||
* {@link http://docs.videojs.com/module-videojs.html#~registerPlugin|videojs#registerPlugin},
|
||||
* which will add a plugin function called `airPlay` to any instance of a Video.js player
|
||||
* that is created after calling this function. Call `player.airPlay(options)`, passing in
|
||||
* configuration options, to enable the AirPlay plugin on your Player instance.
|
||||
*
|
||||
* Currently, the only configuration option is:
|
||||
*
|
||||
* * **buttonText** - the text to display inside of the button component. By default,
|
||||
* this text is hidden and is used for accessibility purposes.
|
||||
*
|
||||
* @param {object} videojs
|
||||
* @see http://docs.videojs.com/module-videojs.html#~registerPlugin
|
||||
*/
|
||||
module.exports = function (videojs) {
|
||||
videojs.registerPlugin('airPlay', function (options) {
|
||||
var pluginOptions = Object.assign({
|
||||
addButtonToControlBar: true
|
||||
}, options || {});
|
||||
|
||||
// `this` is an instance of a Video.js Player.
|
||||
// Wait until the player is "ready" so that the player's control bar component has
|
||||
// been created.
|
||||
this.ready(enableAirPlay.bind(this, this, pluginOptions));
|
||||
});
|
||||
};
|
||||
|
||||
},{"./lib/hasAirPlayAPISupport":4}],3:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
var createAirPlayButton = require('./components/AirPlayButton'),
|
||||
createAirPlayPlugin = require('./enableAirPlay');
|
||||
|
||||
/**
|
||||
* @module index
|
||||
*/
|
||||
|
||||
/**
|
||||
* Registers the AirPlay plugin and AirPlayButton Component with Video.js. See
|
||||
* {@link module:AirPlayButton} and {@link module:enableAirPlay} for more details about
|
||||
* how the plugin and button are registered and configured.
|
||||
*
|
||||
* @param {object} videojs
|
||||
* @see module:enableAirPlay
|
||||
* @see module:AirPlayButton
|
||||
*/
|
||||
module.exports = function (videojs) {
|
||||
videojs = videojs || window.videojs;
|
||||
createAirPlayButton(videojs);
|
||||
createAirPlayPlugin(videojs);
|
||||
};
|
||||
|
||||
},{"./components/AirPlayButton":1,"./enableAirPlay":2}],4:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @module hasAirPlayAPISupport
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns whether or not the current browser environment supports AirPlay.
|
||||
*
|
||||
* @private
|
||||
* @returns {boolean} true if AirPlay support is available
|
||||
*/
|
||||
module.exports = function () {
|
||||
return !!window.WebKitPlaybackTargetAvailabilityEvent;
|
||||
};
|
||||
|
||||
},{}],5:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This module is used as an entry point for the build system to bundle this plugin into a
|
||||
* single javascript file that can be loaded by a script tag on a web page. The javascript
|
||||
* file that is built assumes that `videojs` is available globally at `window.videojs`, so
|
||||
* Video.js must be loaded **before** this plugin is loaded.
|
||||
*
|
||||
* Run `npm install` and then `grunt build` to build the plugin's bundled javascript
|
||||
* file, as well as the CSS and image assets into the project's `./dist/` folder.
|
||||
*
|
||||
* @module standalone
|
||||
*/
|
||||
|
||||
require('./index')();
|
||||
|
||||
},{"./index":3}]},{},[5]);
|
||||
@ -1 +1 @@
|
||||
.vjs-airplay-button .vjs-icon-placeholder{background:url("ic_airplay_white_24px.svg") center center no-repeat;background-size:contain;display:inline-block;width:20px;height:20px}.vjs-airplay-button:hover{cursor:pointer}.vjs-airplay-button:hover .vjs-icon-placeholder{background-image:url("ic_airplay_white_24px.svg")}
|
||||
.vjs-airplay-button .vjs-icon-placeholder{background:url("ic_airplay_white_24px.svg") center center no-repeat;background-size:contain;display:inline-block;width:12px;height:12px}.vjs-airplay-button:hover{cursor:pointer}.vjs-airplay-button:hover .vjs-icon-placeholder{background-image:url("ic_airplay_white_24px.svg")}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden){display:flex;align-items:center;width:auto;padding:0 4px}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden) .vjs-airplay-button-label{flex-grow:1;margin-left:4px}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden) .vjs-icon-placeholder{flex-grow:1}
|
||||
1317
public/_player/videojs/dist/videojs-airplay.min.js
vendored
1317
public/_player/videojs/dist/videojs-airplay.min.js
vendored
File diff suppressed because it is too large
Load Diff
@ -1,65 +1 @@
|
||||
/** Silvermine Chromecast **/
|
||||
.vjs-chromecast-button .vjs-icon-placeholder {
|
||||
background: url('ic_cast_white_24dp.png') center center no-repeat;
|
||||
background-size: contain;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
.vjs-chromecast-button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.vjs-chromecast-button:hover .vjs-icon-placeholder {
|
||||
background-image: url('ic_cast_white_24dp.png');
|
||||
}
|
||||
.vjs-chromecast-button.vjs-chromecast-casting-state .vjs-icon-placeholder {
|
||||
background-image: url('ic_cast_connected_white_24dp.png');
|
||||
}
|
||||
.vjs-chromecast-button.vjs-chromecast-casting-state:hover .vjs-icon-placeholder {
|
||||
background-image: url('ic_cast_connected_white_24dp.png');
|
||||
}
|
||||
.vjs-tech-chromecast {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
.vjs-tech-chromecast .vjs-tech-chromecast-poster::after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
height: 2px;
|
||||
width: 100px;
|
||||
background-color: #cccccc;
|
||||
position: absolute;
|
||||
left: calc(50% - 50px);
|
||||
}
|
||||
.vjs-tech-chromecast .vjs-tech-chromecast-poster-img {
|
||||
max-height: 180px;
|
||||
width: auto;
|
||||
border: 2px solid #cccccc;
|
||||
}
|
||||
.vjs-tech-chromecast .vjs-tech-chromecast-poster-img.vjs-tech-chromecast-poster-img-empty {
|
||||
width: 160px;
|
||||
height: 90px;
|
||||
}
|
||||
.vjs-tech-chromecast .vjs-tech-chromecast-title-container {
|
||||
position: absolute;
|
||||
bottom: 50%;
|
||||
margin-bottom: 100px;
|
||||
color: #cccccc;
|
||||
text-align: center;
|
||||
}
|
||||
.vjs-tech-chromecast .vjs-tech-chromecast-title {
|
||||
font-size: 22px;
|
||||
}
|
||||
.vjs-tech-chromecast .vjs-tech-chromecast-title.vjs-tech-chromecast-title-empty {
|
||||
display: none;
|
||||
}
|
||||
.vjs-tech-chromecast .vjs-tech-chromecast-subtitle {
|
||||
font-size: 18px;
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
.vjs-tech-chromecast .vjs-tech-chromecast-subtitle.vjs-tech-chromecast-subtitle-empty {
|
||||
display: none;
|
||||
}
|
||||
.vjs-chromecast-button .vjs-icon-placeholder{background:url("ic_cast_white_24dp.png") center center no-repeat;background-size:contain;display:inline-block;width:12px;height:12px}.vjs-chromecast-button:hover{cursor:pointer}.vjs-chromecast-button:hover .vjs-icon-placeholder{background-image:url("ic_cast_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-casting-state .vjs-icon-placeholder{background-image:url("ic_cast_connected_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-casting-state:hover .vjs-icon-placeholder{background-image:url("ic_cast_connected_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden){display:flex;align-items:center;width:auto;padding:0 4px}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden) .vjs-chromecast-button-label{flex-grow:1;margin-left:4px}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden) .vjs-icon-placeholder{flex-grow:1}.vjs-tech-chromecast{display:flex;flex-direction:column;justify-content:center;align-items:center;overflow:hidden}.vjs-tech-chromecast .vjs-tech-chromecast-poster::after{content:" ";display:block;height:2px;width:100px;background-color:#ccc;position:absolute;left:calc(50% - 50px)}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img{max-height:180px;width:auto;border:2px solid #ccc}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img.vjs-tech-chromecast-poster-img-empty{width:160px;height:90px}.vjs-tech-chromecast .vjs-tech-chromecast-title-container{position:absolute;bottom:50%;margin-bottom:100px;color:#ccc;text-align:center}.vjs-tech-chromecast .vjs-tech-chromecast-title{font-size:22px}.vjs-tech-chromecast .vjs-tech-chromecast-title.vjs-tech-chromecast-title-empty{display:none}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle{font-size:18px;padding-top:.5em}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle.vjs-tech-chromecast-subtitle-empty{display:none}
|
||||
4100
public/_player/videojs/dist/videojs-chromecast.js
vendored
Normal file
4100
public/_player/videojs/dist/videojs-chromecast.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1 +1 @@
|
||||
.vjs-chromecast-button .vjs-icon-placeholder{background:url(ic_cast_white_24dp.png) center center no-repeat;background-size:contain;display:inline-block;width:20px;height:20px}.vjs-chromecast-button:hover{cursor:pointer}.vjs-chromecast-button:hover .vjs-icon-placeholder{background-image:url(ic_cast_white_24dp.png)}.vjs-chromecast-button.vjs-chromecast-casting-state .vjs-icon-placeholder{background-image:url(ic_cast_connected_white_24dp.png)}.vjs-chromecast-button.vjs-chromecast-casting-state:hover .vjs-icon-placeholder{background-image:url(ic_cast_connected_white_24dp.png)}.vjs-tech-chromecast{display:flex;flex-direction:column;justify-content:center;align-items:center;overflow:hidden}.vjs-tech-chromecast .vjs-tech-chromecast-poster::after{content:' ';display:block;height:2px;width:100px;background-color:#ccc;position:absolute;left:calc(50% - 50px)}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img{max-height:180px;width:auto;border:2px solid #ccc}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img.vjs-tech-chromecast-poster-img-empty{width:160px;height:90px}.vjs-tech-chromecast .vjs-tech-chromecast-title-container{position:absolute;bottom:50%;margin-bottom:100px;color:#ccc;text-align:center}.vjs-tech-chromecast .vjs-tech-chromecast-title{font-size:22px}.vjs-tech-chromecast .vjs-tech-chromecast-title.vjs-tech-chromecast-title-empty{display:none}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle{font-size:18px;padding-top:.5em}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle.vjs-tech-chromecast-subtitle-empty{display:none}
|
||||
.vjs-chromecast-button .vjs-icon-placeholder{background:url("ic_cast_white_24dp.png") center center no-repeat;background-size:contain;display:inline-block;width:12px;height:12px}.vjs-chromecast-button:hover{cursor:pointer}.vjs-chromecast-button:hover .vjs-icon-placeholder{background-image:url("ic_cast_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-casting-state .vjs-icon-placeholder{background-image:url("ic_cast_connected_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-casting-state:hover .vjs-icon-placeholder{background-image:url("ic_cast_connected_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden){display:flex;align-items:center;width:auto;padding:0 4px}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden) .vjs-chromecast-button-label{flex-grow:1;margin-left:4px}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden) .vjs-icon-placeholder{flex-grow:1}.vjs-tech-chromecast{display:flex;flex-direction:column;justify-content:center;align-items:center;overflow:hidden}.vjs-tech-chromecast .vjs-tech-chromecast-poster::after{content:" ";display:block;height:2px;width:100px;background-color:#ccc;position:absolute;left:calc(50% - 50px)}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img{max-height:180px;width:auto;border:2px solid #ccc}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img.vjs-tech-chromecast-poster-img-empty{width:160px;height:90px}.vjs-tech-chromecast .vjs-tech-chromecast-title-container{position:absolute;bottom:50%;margin-bottom:100px;color:#ccc;text-align:center}.vjs-tech-chromecast .vjs-tech-chromecast-title{font-size:22px}.vjs-tech-chromecast .vjs-tech-chromecast-title.vjs-tech-chromecast-title-empty{display:none}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle{font-size:18px;padding-top:.5em}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle.vjs-tech-chromecast-subtitle-empty{display:none}
|
||||
3149
public/_player/videojs/dist/videojs-chromecast.min.js
vendored
3149
public/_player/videojs/dist/videojs-chromecast.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
795
public/_player/videojs/dist/videojs-license.js
vendored
795
public/_player/videojs/dist/videojs-license.js
vendored
@ -1,459 +1,340 @@
|
||||
/*! @name videojs-license @version 0.1.0 @license MIT */
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js'), require('global/document')) :
|
||||
typeof define === 'function' && define.amd ? define(['video.js', 'global/document'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.videojsLicense = factory(global.videojs, global.document));
|
||||
}(this, (function (videojs, document) { 'use strict';
|
||||
|
||||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
||||
|
||||
var videojs__default = /*#__PURE__*/_interopDefaultLegacy(videojs);
|
||||
var document__default = /*#__PURE__*/_interopDefaultLegacy(document);
|
||||
|
||||
function createCommonjsModule(fn, basedir, module) {
|
||||
return module = {
|
||||
path: basedir,
|
||||
exports: {},
|
||||
require: function (path, base) {
|
||||
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
|
||||
}
|
||||
}, fn(module, module.exports), module.exports;
|
||||
}
|
||||
|
||||
function commonjsRequire () {
|
||||
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
|
||||
}
|
||||
|
||||
var assertThisInitialized = createCommonjsModule(function (module) {
|
||||
function _assertThisInitialized(self) {
|
||||
if (self === void 0) {
|
||||
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
module.exports = _assertThisInitialized;
|
||||
module.exports["default"] = module.exports, module.exports.__esModule = true;
|
||||
});
|
||||
|
||||
var setPrototypeOf = createCommonjsModule(function (module) {
|
||||
function _setPrototypeOf(o, p) {
|
||||
module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
|
||||
o.__proto__ = p;
|
||||
return o;
|
||||
};
|
||||
|
||||
module.exports["default"] = module.exports, module.exports.__esModule = true;
|
||||
return _setPrototypeOf(o, p);
|
||||
}
|
||||
|
||||
module.exports = _setPrototypeOf;
|
||||
module.exports["default"] = module.exports, module.exports.__esModule = true;
|
||||
});
|
||||
|
||||
var inheritsLoose = createCommonjsModule(function (module) {
|
||||
function _inheritsLoose(subClass, superClass) {
|
||||
subClass.prototype = Object.create(superClass.prototype);
|
||||
subClass.prototype.constructor = subClass;
|
||||
setPrototypeOf(subClass, superClass);
|
||||
}
|
||||
|
||||
module.exports = _inheritsLoose;
|
||||
module.exports["default"] = module.exports, module.exports.__esModule = true;
|
||||
});
|
||||
|
||||
var version = "0.1.0";
|
||||
|
||||
var Plugin = videojs__default['default'].getPlugin('plugin');
|
||||
var Component = videojs__default['default'].getComponent('Component');
|
||||
var Button = videojs__default['default'].getComponent('MenuButton'); // Default options for the plugin.
|
||||
|
||||
var defaults = {
|
||||
license: 'none',
|
||||
title: '',
|
||||
author: '',
|
||||
languages: {
|
||||
license: 'License',
|
||||
loading: 'Loading'
|
||||
}
|
||||
};
|
||||
/**
|
||||
* An advanced Video.js plugin. For more information on the API
|
||||
*
|
||||
* See: https://blog.videojs.com/feature-spotlight-advanced-plugins/
|
||||
*/
|
||||
|
||||
var License = /*#__PURE__*/function (_Plugin) {
|
||||
inheritsLoose(License, _Plugin);
|
||||
|
||||
/**
|
||||
* Create a License plugin instance.
|
||||
*
|
||||
* @param {Player} player
|
||||
* A Video.js Player instance.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* An optional options object.
|
||||
*
|
||||
* While not a core part of the Video.js plugin architecture, a
|
||||
* second argument of options is a convenient way to accept inputs
|
||||
* from your plugin's caller.
|
||||
*/
|
||||
function License(player, options) {
|
||||
var _this;
|
||||
|
||||
// the parent class will add player under this.player
|
||||
_this = _Plugin.call(this, player) || this;
|
||||
_this.playerId = _this.player.id();
|
||||
_this.options = videojs__default['default'].mergeOptions(defaults, options);
|
||||
|
||||
if (options.license === 'none') {
|
||||
return assertThisInitialized(_this);
|
||||
}
|
||||
|
||||
_this.player.ready(function () {
|
||||
_this.player.addClass('vjs-license');
|
||||
|
||||
_this.buildUI();
|
||||
|
||||
if (videojs__default['default'].browser.IS_IOS || videojs__default['default'].browser.IS_ANDROID) {
|
||||
_this.mobileBuildUI();
|
||||
}
|
||||
}); // close the menu if open on userinactive
|
||||
|
||||
|
||||
_this.player.on('userinactive', function () {
|
||||
document__default['default'].getElementById(_this.playerId).querySelectorAll('.vjs-menu').forEach(function (element) {
|
||||
element.classList.remove('vjs-lock-open');
|
||||
});
|
||||
}); // close the menu if anywhere in the player is clicked
|
||||
|
||||
|
||||
_this.player.on('click', function (evt) {
|
||||
if (evt.target.tagName === 'VIDEO') {
|
||||
document__default['default'].getElementById(_this.playerId).querySelectorAll('.vjs-menu').forEach(function (element) {
|
||||
element.classList.remove('vjs-lock-open');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
_this.player.on('loadstart', function (_event) {
|
||||
_this.removeElementsByClass('vjs-license-clear');
|
||||
|
||||
if (videojs__default['default'].browser.IS_IOS || videojs__default['default'].browser.IS_ANDROID) {
|
||||
_this.mobileBuildTopLevelMenu();
|
||||
} else {
|
||||
_this.buildTopLevelMenu();
|
||||
}
|
||||
});
|
||||
|
||||
return _this;
|
||||
}
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*/
|
||||
|
||||
|
||||
var _proto = License.prototype;
|
||||
|
||||
_proto.buildUI = function buildUI() {
|
||||
var playerId = this.playerId;
|
||||
var that = this;
|
||||
/**
|
||||
* LicenseMenuButton
|
||||
*/
|
||||
|
||||
var LicenseMenuButton = /*#__PURE__*/function (_Button) {
|
||||
inheritsLoose(LicenseMenuButton, _Button);
|
||||
|
||||
/**
|
||||
* Contructor
|
||||
*
|
||||
* @param {*} player videojs player instance
|
||||
* @param {*} options videojs player options
|
||||
*/
|
||||
function LicenseMenuButton(player, options) {
|
||||
var _this2;
|
||||
|
||||
_this2 = _Button.call(this, player, options) || this;
|
||||
|
||||
_this2.addClass('vjs-license');
|
||||
|
||||
_this2.controlText(that.options.languages.loading);
|
||||
|
||||
player.one('canplaythrough', function (_event) {
|
||||
_this2.controlText(that.options.languages.settings);
|
||||
});
|
||||
_this2.menu.contentEl_.id = playerId + '-vjs-license-default';
|
||||
return _this2;
|
||||
}
|
||||
/**
|
||||
* Handle click
|
||||
*/
|
||||
|
||||
|
||||
var _proto2 = LicenseMenuButton.prototype;
|
||||
|
||||
_proto2.handleClick = function handleClick() {
|
||||
if (videojs__default['default'].browser.IS_IOS || videojs__default['default'].browser.IS_ANDROID) {
|
||||
this.player.getChild('licenseMenuMobileModal').el().style.display = 'block';
|
||||
} else {
|
||||
this.el().classList.toggle('vjs-toogle-btn');
|
||||
this.menu.el().classList.toggle('vjs-lock-open');
|
||||
}
|
||||
};
|
||||
|
||||
return LicenseMenuButton;
|
||||
}(Button);
|
||||
|
||||
videojs__default['default'].registerComponent('licenseMenuButton', LicenseMenuButton);
|
||||
this.player.getChild('controlBar').addChild('licenseMenuButton');
|
||||
|
||||
if (this.player.getChild('controlBar').getChild('fullscreenToggle')) {
|
||||
this.player.getChild('controlBar').el().insertBefore(this.player.getChild('controlBar').getChild('licenseMenuButton').el(), this.player.getChild('controlBar').getChild('fullscreenToggle').el());
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* This is just build the top level menu no sub menus
|
||||
*/
|
||||
;
|
||||
|
||||
_proto.buildTopLevelMenu = function buildTopLevelMenu() {
|
||||
var settingsButton = this.player.getChild('controlBar').getChild('licenseMenuButton'); // settingsButton.addClass('vjs-license-is-loaded');
|
||||
|
||||
var main = settingsButton.menu.contentEl_; // Empty the main menu div to repopulate
|
||||
|
||||
main.innerHTML = '';
|
||||
main.classList.add('vjs-license-top-level'); // Start building new list items
|
||||
|
||||
var menuTitle = document__default['default'].createElement('li');
|
||||
menuTitle.className = 'vjs-license-top-level-header';
|
||||
var menuTitleInner = document__default['default'].createElement('span');
|
||||
menuTitleInner.innerHTML = 'About';
|
||||
menuTitleInner.className = 'vjs-license-top-level-header-titel';
|
||||
menuTitle.appendChild(menuTitleInner);
|
||||
main.appendChild(menuTitle);
|
||||
var itemTitel = document__default['default'].createElement('li');
|
||||
itemTitel.innerHTML = this.buildItemTitel();
|
||||
itemTitel.className = 'vjs-license-top-level-item';
|
||||
main.appendChild(itemTitel);
|
||||
|
||||
if (this.options.author) {
|
||||
var itemAuthor = document__default['default'].createElement('li');
|
||||
itemAuthor.innerHTML = this.buildItemAuthor();
|
||||
itemAuthor.className = 'vjs-license-top-level-item';
|
||||
main.appendChild(itemAuthor);
|
||||
}
|
||||
|
||||
var itemLicense = document__default['default'].createElement('li');
|
||||
itemLicense.innerHTML = this.buildItemLicense();
|
||||
itemLicense.className = 'vjs-license-top-level-item';
|
||||
main.appendChild(itemLicense);
|
||||
}
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*/
|
||||
;
|
||||
|
||||
_proto.mobileBuildUI = function mobileBuildUI() {
|
||||
/**
|
||||
* bla
|
||||
*/
|
||||
var LicenseMenuMobileModal = /*#__PURE__*/function (_Component) {
|
||||
inheritsLoose(LicenseMenuMobileModal, _Component);
|
||||
|
||||
/**
|
||||
* Contructor
|
||||
*
|
||||
* @param {*} player videojs player instance
|
||||
* @param {*} options videojs player options
|
||||
*/
|
||||
function LicenseMenuMobileModal(player, options) {
|
||||
return _Component.call(this, player, options) || this;
|
||||
}
|
||||
/**
|
||||
* Creates an HTML element
|
||||
*
|
||||
* @return {Object} HTML element
|
||||
*/
|
||||
|
||||
|
||||
var _proto3 = LicenseMenuMobileModal.prototype;
|
||||
|
||||
_proto3.createEl = function createEl() {
|
||||
return videojs__default['default'].createEl('div', {
|
||||
className: 'vjs-license-mobile'
|
||||
});
|
||||
};
|
||||
|
||||
return LicenseMenuMobileModal;
|
||||
}(Component);
|
||||
|
||||
videojs__default['default'].registerComponent('licenseMenuMobileModal', LicenseMenuMobileModal);
|
||||
videojs__default['default'].dom.prependTo(this.player.addChild('licenseMenuMobileModal').el(), document__default['default'].body);
|
||||
}
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*/
|
||||
;
|
||||
|
||||
_proto.mobileBuildTopLevelMenu = function mobileBuildTopLevelMenu() {
|
||||
var _this3 = this;
|
||||
|
||||
var settingsButton = this.player.getChild('licenseMenuMobileModal');
|
||||
var menuTopLevel = document__default['default'].createElement('ul');
|
||||
menuTopLevel.className = 'vjs-license-mob-top-level vjs-setting-menu-clear';
|
||||
settingsButton.el().appendChild(menuTopLevel); // Empty the main menu div to repopulate
|
||||
|
||||
var menuTitle = document__default['default'].createElement('li');
|
||||
menuTitle.innerHTML = 'About';
|
||||
menuTitle.className = 'vjs-setting-menu-mobile-top-header';
|
||||
menuTopLevel.appendChild(menuTitle);
|
||||
var itemTitel = document__default['default'].createElement('li');
|
||||
itemTitel.innerHTML = this.buildItemTitel();
|
||||
itemTitel.className = 'vjs-license-top-level-item';
|
||||
|
||||
if (this.options.author) {
|
||||
var itemAuthor = document__default['default'].createElement('li');
|
||||
itemAuthor.innerHTML = this.buildItemAuthor();
|
||||
itemAuthor.className = 'vjs-license-top-level-item';
|
||||
}
|
||||
|
||||
var itemLicense = document__default['default'].createElement('li');
|
||||
itemLicense.innerHTML = this.buildItemLicense();
|
||||
itemLicense.className = 'vjs-license-top-level-item';
|
||||
var menuClose = document__default['default'].createElement('li');
|
||||
menuClose.innerHTML = 'Close';
|
||||
menuClose.className = 'setting-menu-footer-default';
|
||||
|
||||
menuClose.onclick = function (e) {
|
||||
_this3.player.getChild('settingsMenuMobileModal').el().style.display = 'none';
|
||||
};
|
||||
|
||||
menuTopLevel.appendChild(menuClose);
|
||||
}
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*
|
||||
* @return {string} Returns license text
|
||||
*/
|
||||
;
|
||||
|
||||
_proto.buildItemTitel = function buildItemTitel() {
|
||||
var titel = '';
|
||||
|
||||
if (this.options.title) {
|
||||
titel = "" + this.options.title;
|
||||
}
|
||||
|
||||
return 'Title: ' + titel;
|
||||
}
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*
|
||||
* @return {string} Returns license text
|
||||
*/
|
||||
;
|
||||
|
||||
_proto.buildItemAuthor = function buildItemAuthor() {
|
||||
var author = '';
|
||||
|
||||
if (this.options.author) {
|
||||
author = " by " + this.options.author;
|
||||
}
|
||||
|
||||
return 'Author: ' + author;
|
||||
}
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*
|
||||
* @return {string} Returns license text
|
||||
*/
|
||||
;
|
||||
|
||||
_proto.buildItemLicense = function buildItemLicense() {
|
||||
var license = '';
|
||||
var reVersion = new RegExp('[0-9]+.[0-9]+$');
|
||||
var version = '4.0';
|
||||
var matches = this.options.license.match(reVersion);
|
||||
|
||||
if (matches !== null) {
|
||||
version = matches[0];
|
||||
}
|
||||
|
||||
var which = this.options.license.replace(reVersion, '').trim();
|
||||
var deed = null;
|
||||
|
||||
switch (which) {
|
||||
case 'CC0':
|
||||
deed = 'https://creativecommons.org/licenses/zero/1.0/';
|
||||
break;
|
||||
|
||||
case 'CC BY':
|
||||
deed = "https://creativecommons.org/licenses/by/" + version + "/";
|
||||
break;
|
||||
|
||||
case 'CC BY-SA':
|
||||
deed = "https://creativecommons.org/licenses/by-sa/" + version + "/";
|
||||
break;
|
||||
|
||||
case 'CC BY-NC':
|
||||
deed = "https://creativecommons.org/licenses/by-nc/" + version + "/";
|
||||
break;
|
||||
|
||||
case 'CC BY-NC-SA':
|
||||
deed = "https://creativecommons.org/licenses/by-nc-sa/" + version + "/";
|
||||
break;
|
||||
|
||||
case 'CC BY-ND':
|
||||
deed = "https://creativecommons.org/licenses/by-nd/" + version + "/";
|
||||
break;
|
||||
|
||||
case 'CC BY-NC-ND':
|
||||
deed = "https://creativecommons.org/licenses/by-nc-nd/" + version + "/";
|
||||
break;
|
||||
}
|
||||
|
||||
if (deed) {
|
||||
license = "<a href=\"" + deed + "\" onclick=\"window.open('" + deed + "')\" target=\"_blank\" rel=\"noopener\">" + this.options.license + "</a>";
|
||||
} else {
|
||||
license = this.options.license;
|
||||
}
|
||||
|
||||
return 'License: ' + license;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Helper class to clear menu items before rebuild
|
||||
*
|
||||
* @param {*} className Name of a class
|
||||
*/
|
||||
;
|
||||
|
||||
_proto.removeElementsByClass = function removeElementsByClass(className) {
|
||||
// Need to prevent the menu from not showing sometimes
|
||||
document__default['default'].querySelectorAll('.vjs-sm-top-level').forEach(function (element) {
|
||||
element.classList.remove('vjs-hidden');
|
||||
});
|
||||
var elements = document__default['default'].getElementsByClassName(className);
|
||||
|
||||
while (elements.length > 0) {
|
||||
elements[0].parentNode.removeChild(elements[0]);
|
||||
}
|
||||
};
|
||||
|
||||
return License;
|
||||
}(Plugin); // Define default values for the plugin's `state` object here.
|
||||
|
||||
|
||||
License.defaultState = {}; // Include the version number.
|
||||
|
||||
License.VERSION = version; // Register the plugin with video.js.
|
||||
|
||||
videojs__default['default'].registerPlugin('license', License);
|
||||
|
||||
return License;
|
||||
|
||||
})));
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
|
||||
typeof define === 'function' && define.amd ? define(['video.js'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.videojsLicense = factory(global.videojs));
|
||||
})(this, (function (videojs) { 'use strict';
|
||||
|
||||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
||||
|
||||
var videojs__default = /*#__PURE__*/_interopDefaultLegacy(videojs);
|
||||
|
||||
var version = "0.1.0";
|
||||
|
||||
const Plugin = videojs__default["default"].getPlugin('plugin');
|
||||
const Component = videojs__default["default"].getComponent('Component');
|
||||
const Button = videojs__default["default"].getComponent('MenuButton');
|
||||
|
||||
// Default options for the plugin.
|
||||
const defaults = {
|
||||
license: 'none',
|
||||
title: '',
|
||||
author: '',
|
||||
languages: {
|
||||
license: 'License',
|
||||
loading: 'Loading'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An advanced Video.js plugin. For more information on the API
|
||||
*
|
||||
* See: https://blog.videojs.com/feature-spotlight-advanced-plugins/
|
||||
*/
|
||||
class License extends Plugin {
|
||||
/**
|
||||
* Create a License plugin instance.
|
||||
*
|
||||
* @param {Player} player
|
||||
* A Video.js Player instance.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* An optional options object.
|
||||
*
|
||||
* While not a core part of the Video.js plugin architecture, a
|
||||
* second argument of options is a convenient way to accept inputs
|
||||
* from your plugin's caller.
|
||||
*/
|
||||
constructor(player, options) {
|
||||
// the parent class will add player under this.player
|
||||
super(player);
|
||||
this.playerId = this.player.id();
|
||||
this.options = videojs__default["default"].mergeOptions(defaults, options);
|
||||
if (options.license === 'none') {
|
||||
return;
|
||||
}
|
||||
player.addClass('vjs-license');
|
||||
this.buildUI();
|
||||
if (videojs__default["default"].browser.IS_IOS || videojs__default["default"].browser.IS_ANDROID) {
|
||||
this.mobileBuildUI();
|
||||
}
|
||||
|
||||
// close the menu if open on userinactive
|
||||
this.player.on('userinactive', () => {
|
||||
document.getElementById(this.playerId).querySelectorAll('.vjs-menu').forEach(element => {
|
||||
element.classList.remove('vjs-lock-open');
|
||||
});
|
||||
});
|
||||
|
||||
// close the menu if anywhere in the player is clicked
|
||||
this.player.on('click', evt => {
|
||||
if (evt.target.tagName === 'VIDEO') {
|
||||
document.getElementById(this.playerId).querySelectorAll('.vjs-menu').forEach(element => {
|
||||
element.classList.remove('vjs-lock-open');
|
||||
});
|
||||
}
|
||||
});
|
||||
this.player.on('loadstart', _event => {
|
||||
this.removeElementsByClass('vjs-license-clear');
|
||||
if (videojs__default["default"].browser.IS_IOS || videojs__default["default"].browser.IS_ANDROID) {
|
||||
this.mobileBuildTopLevelMenu();
|
||||
} else {
|
||||
this.buildTopLevelMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*/
|
||||
buildUI() {
|
||||
const playerId = this.playerId;
|
||||
const that = this;
|
||||
|
||||
/**
|
||||
* LicenseMenuButton
|
||||
*/
|
||||
class LicenseMenuButton extends Button {
|
||||
/**
|
||||
* Contructor
|
||||
*
|
||||
* @param {*} player videojs player instance
|
||||
* @param {*} options videojs player options
|
||||
*/
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
this.addClass('vjs-license');
|
||||
this.controlText(that.options.languages.loading);
|
||||
player.one('canplaythrough', _event => {
|
||||
this.controlText(that.options.languages.settings);
|
||||
});
|
||||
this.menu.contentEl_.id = playerId + '-vjs-license-default';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click
|
||||
*/
|
||||
handleClick() {
|
||||
if (videojs__default["default"].browser.IS_IOS || videojs__default["default"].browser.IS_ANDROID) {
|
||||
this.player.getChild('licenseMenuMobileModal').el().style.display = 'block';
|
||||
} else {
|
||||
this.el().classList.toggle('vjs-toogle-btn');
|
||||
this.menu.el().classList.toggle('vjs-lock-open');
|
||||
}
|
||||
}
|
||||
}
|
||||
videojs__default["default"].registerComponent('licenseMenuButton', LicenseMenuButton);
|
||||
this.player.getChild('controlBar').addChild('licenseMenuButton');
|
||||
if (this.player.getChild('controlBar').getChild('fullscreenToggle')) {
|
||||
this.player.getChild('controlBar').el().insertBefore(this.player.getChild('controlBar').getChild('licenseMenuButton').el(), this.player.getChild('controlBar').getChild('fullscreenToggle').el());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* This is just build the top level menu no sub menus
|
||||
*/
|
||||
buildTopLevelMenu() {
|
||||
const settingsButton = this.player.getChild('controlBar').getChild('licenseMenuButton');
|
||||
|
||||
// settingsButton.addClass('vjs-license-is-loaded');
|
||||
|
||||
const main = settingsButton.menu.contentEl_;
|
||||
|
||||
// Empty the main menu div to repopulate
|
||||
main.innerHTML = '';
|
||||
main.classList.add('vjs-license-top-level');
|
||||
|
||||
// Start building new list items
|
||||
const menuTitle = document.createElement('li');
|
||||
menuTitle.className = 'vjs-license-top-level-header';
|
||||
const menuTitleInner = document.createElement('span');
|
||||
menuTitleInner.innerHTML = 'About';
|
||||
menuTitleInner.className = 'vjs-license-top-level-header-titel';
|
||||
menuTitle.appendChild(menuTitleInner);
|
||||
main.appendChild(menuTitle);
|
||||
const itemTitel = document.createElement('li');
|
||||
itemTitel.innerHTML = this.buildItemTitel();
|
||||
itemTitel.className = 'vjs-license-top-level-item';
|
||||
main.appendChild(itemTitel);
|
||||
if (this.options.author) {
|
||||
const itemAuthor = document.createElement('li');
|
||||
itemAuthor.innerHTML = this.buildItemAuthor();
|
||||
itemAuthor.className = 'vjs-license-top-level-item';
|
||||
main.appendChild(itemAuthor);
|
||||
}
|
||||
const itemLicense = document.createElement('li');
|
||||
itemLicense.innerHTML = this.buildItemLicense();
|
||||
itemLicense.className = 'vjs-license-top-level-item';
|
||||
main.appendChild(itemLicense);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*/
|
||||
mobileBuildUI() {
|
||||
/**
|
||||
* bla
|
||||
*/
|
||||
class LicenseMenuMobileModal extends Component {
|
||||
/**
|
||||
* Contructor
|
||||
*
|
||||
* @param {*} player videojs player instance
|
||||
* @param {*} options videojs player options
|
||||
*/
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an HTML element
|
||||
*
|
||||
* @return {Object} HTML element
|
||||
*/
|
||||
createEl() {
|
||||
return videojs__default["default"].createEl('div', {
|
||||
className: 'vjs-license-mobile'
|
||||
});
|
||||
}
|
||||
}
|
||||
videojs__default["default"].registerComponent('licenseMenuMobileModal', LicenseMenuMobileModal);
|
||||
videojs__default["default"].dom.prependTo(this.player.addChild('licenseMenuMobileModal').el(), document.body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*/
|
||||
mobileBuildTopLevelMenu() {
|
||||
const settingsButton = this.player.getChild('licenseMenuMobileModal');
|
||||
const menuTopLevel = document.createElement('ul');
|
||||
menuTopLevel.className = 'vjs-license-mob-top-level vjs-setting-menu-clear';
|
||||
settingsButton.el().appendChild(menuTopLevel);
|
||||
|
||||
// Empty the main menu div to repopulate
|
||||
const menuTitle = document.createElement('li');
|
||||
menuTitle.innerHTML = 'About';
|
||||
menuTitle.className = 'vjs-setting-menu-mobile-top-header';
|
||||
menuTopLevel.appendChild(menuTitle);
|
||||
const itemTitel = document.createElement('li');
|
||||
itemTitel.innerHTML = this.buildItemTitel();
|
||||
itemTitel.className = 'vjs-license-top-level-item';
|
||||
if (this.options.author) {
|
||||
const itemAuthor = document.createElement('li');
|
||||
itemAuthor.innerHTML = this.buildItemAuthor();
|
||||
itemAuthor.className = 'vjs-license-top-level-item';
|
||||
}
|
||||
const itemLicense = document.createElement('li');
|
||||
itemLicense.innerHTML = this.buildItemLicense();
|
||||
itemLicense.className = 'vjs-license-top-level-item';
|
||||
const menuClose = document.createElement('li');
|
||||
menuClose.innerHTML = 'Close';
|
||||
menuClose.className = 'setting-menu-footer-default';
|
||||
menuClose.onclick = e => {
|
||||
this.player.getChild('settingsMenuMobileModal').el().style.display = 'none';
|
||||
};
|
||||
menuTopLevel.appendChild(menuClose);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*
|
||||
* @return {string} Returns license text
|
||||
*/
|
||||
buildItemTitel() {
|
||||
let titel = '';
|
||||
if (this.options.title) {
|
||||
titel = `${this.options.title}`;
|
||||
}
|
||||
return 'Title: ' + titel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*
|
||||
* @return {string} Returns license text
|
||||
*/
|
||||
buildItemAuthor() {
|
||||
let author = '';
|
||||
if (this.options.author) {
|
||||
author = ` by ${this.options.author}`;
|
||||
}
|
||||
return 'Author: ' + author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the menu ui button to the controlbar
|
||||
*
|
||||
* @return {string} Returns license text
|
||||
*/
|
||||
buildItemLicense() {
|
||||
let license = '';
|
||||
const reVersion = new RegExp('[0-9]+.[0-9]+$');
|
||||
let version = '4.0';
|
||||
const matches = this.options.license.match(reVersion);
|
||||
if (matches !== null) {
|
||||
version = matches[0];
|
||||
}
|
||||
const which = this.options.license.replace(reVersion, '').trim();
|
||||
let deed = null;
|
||||
switch (which) {
|
||||
case 'CC0':
|
||||
deed = 'https://creativecommons.org/licenses/zero/1.0/';
|
||||
break;
|
||||
case 'CC BY':
|
||||
deed = `https://creativecommons.org/licenses/by/${version}/`;
|
||||
break;
|
||||
case 'CC BY-SA':
|
||||
deed = `https://creativecommons.org/licenses/by-sa/${version}/`;
|
||||
break;
|
||||
case 'CC BY-NC':
|
||||
deed = `https://creativecommons.org/licenses/by-nc/${version}/`;
|
||||
break;
|
||||
case 'CC BY-NC-SA':
|
||||
deed = `https://creativecommons.org/licenses/by-nc-sa/${version}/`;
|
||||
break;
|
||||
case 'CC BY-ND':
|
||||
deed = `https://creativecommons.org/licenses/by-nd/${version}/`;
|
||||
break;
|
||||
case 'CC BY-NC-ND':
|
||||
deed = `https://creativecommons.org/licenses/by-nc-nd/${version}/`;
|
||||
break;
|
||||
}
|
||||
if (deed) {
|
||||
license = `<a href='${deed}' onclick='window.open('${deed}')' target='_blank' rel='noopener'>${this.options.license}</a>`;
|
||||
} else {
|
||||
license = this.options.license;
|
||||
}
|
||||
return 'License: ' + license;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Helper class to clear menu items before rebuild
|
||||
*
|
||||
* @param {*} className Name of a class
|
||||
*/
|
||||
removeElementsByClass(className) {
|
||||
// Need to prevent the menu from not showing sometimes
|
||||
document.querySelectorAll('.vjs-sm-top-level').forEach(element => {
|
||||
element.classList.remove('vjs-hidden');
|
||||
});
|
||||
const elements = document.getElementsByClassName(className);
|
||||
while (elements.length > 0) {
|
||||
elements[0].parentNode.removeChild(elements[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define default values for the plugin's `state` object here.
|
||||
License.defaultState = {};
|
||||
|
||||
// Include the version number.
|
||||
License.VERSION = version;
|
||||
|
||||
// Register the plugin with video.js.
|
||||
videojs__default["default"].registerPlugin('license', License);
|
||||
|
||||
return License;
|
||||
|
||||
}));
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -83,9 +83,6 @@
|
||||
responsive: true,
|
||||
fluid: true,
|
||||
sources: [{ src: window.location.origin + '/' + playerConfig.source, type: 'application/x-mpegURL' }],
|
||||
plugins: {
|
||||
license: playerConfig.license
|
||||
}
|
||||
};
|
||||
|
||||
if (playerConfig.chromecast) {
|
||||
@ -132,6 +129,8 @@
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
player.license(playerConfig.license);
|
||||
}
|
||||
|
||||
if (autoplay === true) {
|
||||
|
||||
@ -6,25 +6,32 @@ var config = {
|
||||
liveui: true,
|
||||
responsive: true,
|
||||
fluid: true,
|
||||
// Needed to append the url orgin in order for the source to properly pass to the cast device
|
||||
sources: [{ src: playerConfig.source, type: 'application/x-mpegURL' }],
|
||||
plugins: {
|
||||
license: playerConfig.license,
|
||||
},
|
||||
// Needed to append the url origin in order for the source to properly pass to the cast device
|
||||
sources: [{ src: window.location.origin + '/' + playerConfig.source, type: 'application/x-mpegURL' }],
|
||||
plugins: {},
|
||||
};
|
||||
|
||||
if (chromecast) {
|
||||
config.techOrder = ['chromecast', 'html5'];
|
||||
config.plugins.chromecast = {};
|
||||
}
|
||||
|
||||
if (airplay) {
|
||||
config.plugins.airPlay = {};
|
||||
// Provide a default reciever application ID
|
||||
config.plugins.chromecast = {
|
||||
receiverApplicationId: 'CC1AD845',
|
||||
};
|
||||
}
|
||||
|
||||
var player = videojs('player', config);
|
||||
|
||||
player.ready(function () {
|
||||
if (chromecast) {
|
||||
player.chromecast();
|
||||
}
|
||||
|
||||
if (airplay) {
|
||||
player.airPlay();
|
||||
}
|
||||
|
||||
player.license(playerConfig.license);
|
||||
|
||||
if (playerConfig.logo.image.length != 0) {
|
||||
var overlay = null;
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -15,16 +15,9 @@ const MenuProps = {
|
||||
|
||||
export default function Component(props) {
|
||||
return (
|
||||
<FormControl variant="outlined" fullWidth>
|
||||
<FormControl variant={props.variant} disabled={props.disabled} fullWidth>
|
||||
<InputLabel>{props.label}</InputLabel>
|
||||
<Select
|
||||
multiple
|
||||
value={props.value}
|
||||
onChange={props.onChange}
|
||||
input={<OutlinedInput />}
|
||||
renderValue={(selected) => selected.join(', ')}
|
||||
MenuProps={MenuProps}
|
||||
>
|
||||
<Select multiple value={props.value} onChange={props.onChange} input={<OutlinedInput />} renderValue={props.renderValue} MenuProps={MenuProps}>
|
||||
{props.children}
|
||||
</Select>
|
||||
</FormControl>
|
||||
@ -32,7 +25,10 @@ export default function Component(props) {
|
||||
}
|
||||
|
||||
Component.defaultProps = {
|
||||
variant: 'outlined',
|
||||
label: '',
|
||||
value: [],
|
||||
disabled: false,
|
||||
renderValue: (selected) => selected.join(', '),
|
||||
onChange: function (event) {},
|
||||
};
|
||||
|
||||
@ -41,7 +41,11 @@ export default function Component(props) {
|
||||
isCustom: v === props.customKey ? true : false,
|
||||
});
|
||||
|
||||
props.onChange(event);
|
||||
props.onChange({
|
||||
target: {
|
||||
value: v === props.customKey ? value.custom : value.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleCustomChange = (event) => {
|
||||
@ -59,7 +63,7 @@ export default function Component(props) {
|
||||
options.push(
|
||||
<MenuItem key={o.value} value={o.value} disabled={o.disabled === true}>
|
||||
{o.label}
|
||||
</MenuItem>
|
||||
</MenuItem>,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: [],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-hwaccel', 'cuda', '-c:v', 'av1_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: [],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'h264_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'h264_mmal'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'hevc_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'mjpeg_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'mpeg1_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'mpeg2_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'mpeg2_mmal'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'mpeg4_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'mpeg4_mmal'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'vc1_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'vc1_mmal'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-hwaccel', 'videotoolbox'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'vp8_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: ['-c:v', 'vp9_cuvid'],
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -27,6 +27,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -27,6 +27,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [['-vsync', 'drop']],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -15,6 +15,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -24,6 +24,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [['-vsync', 'drop']],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -11,6 +11,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -44,6 +44,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [['-vsync', 'drop']],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -23,6 +23,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -23,6 +23,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [['-vsync', 'drop']],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -23,6 +23,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [['-vsync', 'drop']],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -78,6 +78,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -11,6 +11,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -71,6 +71,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -64,6 +64,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -47,6 +47,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -125,6 +125,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -30,13 +30,12 @@ function createMapping(settings, stream, skills) {
|
||||
|
||||
const global = [];
|
||||
const local = [];
|
||||
const filter = [];
|
||||
|
||||
// https://trac.ffmpeg.org/wiki/Hardware/VAAPI
|
||||
global.push(['-vaapi_device', '/dev/dri/renderD128']);
|
||||
|
||||
local.push(
|
||||
'-vf',
|
||||
'format=nv12,hwupload',
|
||||
'-codec:v',
|
||||
'h264_vaapi',
|
||||
'-profile:v',
|
||||
@ -51,17 +50,18 @@ function createMapping(settings, stream, skills) {
|
||||
`${settings.bitrate}k`,
|
||||
'-r',
|
||||
`${settings.fps}`,
|
||||
'-g',
|
||||
`${settings.gop}`
|
||||
);
|
||||
|
||||
if (settings.gop !== 'auto') {
|
||||
local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`);
|
||||
}
|
||||
|
||||
filter.push('format=nv12', 'hwupload');
|
||||
|
||||
return {
|
||||
global: global,
|
||||
local: local,
|
||||
filter: filter,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -58,6 +58,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -71,6 +71,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -30,13 +30,12 @@ function createMapping(settings, stream, skills) {
|
||||
|
||||
const global = [];
|
||||
const local = [];
|
||||
const filter = [];
|
||||
|
||||
// https://trac.ffmpeg.org/wiki/Hardware/VAAPI
|
||||
global.push(['-vaapi_device', '/dev/dri/renderD128']);
|
||||
|
||||
local.push(
|
||||
'-vf',
|
||||
'format=nv12,hwupload',
|
||||
'-codec:v',
|
||||
'hevc_vaapi',
|
||||
'-profile:v',
|
||||
@ -59,9 +58,12 @@ function createMapping(settings, stream, skills) {
|
||||
local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`);
|
||||
}
|
||||
|
||||
filter.push('format=nv12', 'hwupload');
|
||||
|
||||
return {
|
||||
global: global,
|
||||
local: local,
|
||||
filter: filter,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +53,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -11,6 +11,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -11,6 +11,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -54,6 +54,7 @@ function createMapping(settings, stream, skills) {
|
||||
const mapping = {
|
||||
global: [],
|
||||
local: local,
|
||||
filter: [],
|
||||
};
|
||||
|
||||
return mapping;
|
||||
|
||||
@ -30,13 +30,12 @@ function createMapping(settings, stream, skills) {
|
||||
|
||||
const global = [];
|
||||
const local = [];
|
||||
const filter = [];
|
||||
|
||||
// https://trac.ffmpeg.org/wiki/Hardware/VAAPI
|
||||
global.push(['-vaapi_device', '/dev/dri/renderD128']);
|
||||
|
||||
local.push(
|
||||
'-vf',
|
||||
'format=nv12,hwupload',
|
||||
'-codec:v',
|
||||
'vp9_vaapi',
|
||||
'-profile:v',
|
||||
@ -52,16 +51,19 @@ function createMapping(settings, stream, skills) {
|
||||
'-r',
|
||||
`${settings.fps}`,
|
||||
'-g',
|
||||
`${settings.gop}`
|
||||
`${settings.gop}`,
|
||||
);
|
||||
|
||||
if (settings.gop !== 'auto') {
|
||||
local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`);
|
||||
}
|
||||
|
||||
filter.push('format=nv12', 'hwupload');
|
||||
|
||||
return {
|
||||
global: global,
|
||||
local: local,
|
||||
filter: filter,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -59,6 +59,46 @@ function Layout(props) {
|
||||
{ value: 'stereo', label: 'stereo' },
|
||||
];
|
||||
|
||||
if (props.extended) {
|
||||
options.push(
|
||||
...[
|
||||
{ value: '2.1', label: '2.1' },
|
||||
{ value: '3.0', label: '3.0' },
|
||||
{ value: '3.0(back)', label: '3.0 (back)' },
|
||||
{ value: '4.0', label: '4.0' },
|
||||
{ value: 'quad', label: 'quad' },
|
||||
{ value: 'quad(side)', label: 'quad (side)' },
|
||||
{ value: '3.1', label: '3.1' },
|
||||
{ value: '5.0', label: '5.0' },
|
||||
{ value: '5.0(side)', label: '5.0 (side)' },
|
||||
{ value: '4.1', label: '4.1' },
|
||||
{ value: '5.1', label: '5.1' },
|
||||
{ value: '5.1(side)', label: '5.1 (side)' },
|
||||
{ value: '6.0', label: '6.0' },
|
||||
{ value: '6.0(front)', label: '6.0 (front)' },
|
||||
{ value: '3.1.2', label: '3.1.2' },
|
||||
{ value: 'hexagonal', label: 'hexagonal' },
|
||||
{ value: '6.1', label: '6.1' },
|
||||
{ value: '6.1(back)', label: '6.1 (back)' },
|
||||
{ value: '6.1(front)', label: '6.1 (front)' },
|
||||
{ value: '7.0', label: '7.0' },
|
||||
{ value: '7.0(front)', label: '7.0 (front)' },
|
||||
{ value: '7.1', label: '7.1' },
|
||||
{ value: '7.1(wide)', label: '7.1 (wide)' },
|
||||
{ value: '7.1(wide-side)', label: '7.1 (wide-side)' },
|
||||
{ value: '5.1.2', label: '5.1.2' },
|
||||
{ value: 'octagonal', label: 'octagonal' },
|
||||
{ value: 'cube', label: 'cube' },
|
||||
{ value: '5.1.4', label: '5.1.4' },
|
||||
{ value: '7.1.2', label: '7.1.2' },
|
||||
{ value: '7.1.4', label: '7.1.4' },
|
||||
{ value: 'hexadecagonal', label: 'hexadecagonal' },
|
||||
{ value: 'downmix', label: 'downmix' },
|
||||
{ value: '22.2', label: '22.2' },
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
if (props.allowAuto === true) {
|
||||
options.unshift({ value: 'auto', label: 'auto' });
|
||||
}
|
||||
|
||||
@ -327,6 +327,43 @@ Format.defaultProps = {
|
||||
onChange: function (event) {},
|
||||
};
|
||||
|
||||
function PixFormat(props) {
|
||||
const { i18n } = useLingui();
|
||||
const sizes = [
|
||||
{ value: 'yuv420p', label: 'yuv420p' },
|
||||
{ value: 'nv12', label: 'nv12' },
|
||||
];
|
||||
|
||||
if (props.allowAuto === true) {
|
||||
sizes.unshift({ value: 'auto', label: 'auto' });
|
||||
}
|
||||
|
||||
if (props.allowCustom === true) {
|
||||
sizes.push({ value: 'custom', label: i18n._(t`Custom ...`) });
|
||||
}
|
||||
|
||||
return (
|
||||
<SelectCustom
|
||||
options={sizes}
|
||||
label={props.label}
|
||||
customLabel={props.customLabel}
|
||||
value={props.value}
|
||||
onChange={props.onChange}
|
||||
variant={props.variant}
|
||||
allowCustom={props.allowCustom}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
PixFormat.defaultProps = {
|
||||
allowAuto: false,
|
||||
allowCustom: false,
|
||||
variant: 'outlined',
|
||||
label: <Trans>Pixel Format</Trans>,
|
||||
customLabel: <Trans>Custom format</Trans>,
|
||||
onChange: function (event) {},
|
||||
};
|
||||
|
||||
function FpsMode(props) {
|
||||
return (
|
||||
<Select label={<Trans>Framerate mode</Trans>} value={props.value} onChange={props.onChange}>
|
||||
@ -360,5 +397,6 @@ export default {
|
||||
Width,
|
||||
Height,
|
||||
Format,
|
||||
PixFormat,
|
||||
FpsMode,
|
||||
};
|
||||
|
||||
205
src/misc/modals/Hint.js
Normal file
205
src/misc/modals/Hint.js
Normal file
@ -0,0 +1,205 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Trans } from '@lingui/macro';
|
||||
import Button from '@mui/material/Button';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
import Dialog from './Dialog';
|
||||
import Select from '../Select';
|
||||
import Video from '../coders/settings/Video';
|
||||
import Audio from '../coders/settings/Audio';
|
||||
|
||||
const Stream = function (props) {
|
||||
const handleChange = (what) => (event) => {
|
||||
const value = event.target.value;
|
||||
|
||||
let stream = {
|
||||
...props.stream,
|
||||
};
|
||||
|
||||
if (what === 'type') {
|
||||
if (value === 'audio') {
|
||||
stream.codec = 'aac';
|
||||
if (stream.sampling_hz === 0) {
|
||||
stream.sampling_hz = '44100';
|
||||
}
|
||||
if (stream.layout === '') {
|
||||
stream.layout = 'stereo';
|
||||
stream.channels = 2;
|
||||
}
|
||||
} else {
|
||||
stream.codec = 'h264';
|
||||
if (stream.width === 0) {
|
||||
stream.width = 1920;
|
||||
stream.height = 1080;
|
||||
}
|
||||
|
||||
if (stream.pix_fmt === '') {
|
||||
stream.pix_fmt = 'yuv240p';
|
||||
}
|
||||
}
|
||||
stream.type = value;
|
||||
} else if (what === 'size') {
|
||||
const [width, height] = value.split('x');
|
||||
|
||||
stream.width = width;
|
||||
stream.height = height;
|
||||
} else {
|
||||
stream[what] = value;
|
||||
}
|
||||
|
||||
props.onChange(stream);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container spacing={2}>
|
||||
{/* <Grid item xs={6}>
|
||||
<Select label={<Trans>Type</Trans>} value={props.stream.type} onChange={handleChange('type')}>
|
||||
<MenuItem value="audio">Audio</MenuItem>
|
||||
<MenuItem value="video">Video</MenuItem>
|
||||
</Select>
|
||||
</Grid> */}
|
||||
{props.stream.type === 'audio' ? (
|
||||
<React.Fragment>
|
||||
<Grid item xs={12}>
|
||||
<Select label={<Trans>Codec</Trans>} value={props.stream.codec} onChange={handleChange('codec')}>
|
||||
<MenuItem value="aac">AAC</MenuItem>
|
||||
<MenuItem value="mp3">MP3</MenuItem>
|
||||
</Select>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Audio.Sampling value={props.stream.sampling_hz} onChange={handleChange('sampling_hz')} allowCustom />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Audio.Layout value={props.stream.layout} onChange={handleChange('layout')} allowCustom />
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<React.Fragment>
|
||||
<Grid item xs={12}>
|
||||
<Select label={<Trans>Codec</Trans>} value={props.stream.codec} onChange={handleChange('codec')}>
|
||||
<MenuItem value="h264">H264</MenuItem>
|
||||
<MenuItem value="hevc">HEVC</MenuItem>
|
||||
<MenuItem value="vp9">VP9</MenuItem>
|
||||
<MenuItem value="av1">AV1</MenuItem>
|
||||
<MenuItem value="vp8">VP8</MenuItem>
|
||||
</Select>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Video.Size value={props.stream.width + 'x' + props.stream.height} onChange={handleChange('size')} allowCustom />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Video.PixFormat value={props.stream.pix_fmt} onChange={handleChange('pix_fmt')} allowCustom />
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
Stream.defaultProps = {
|
||||
stream: {},
|
||||
onChange: () => {},
|
||||
};
|
||||
|
||||
const Streams = function (props) {
|
||||
const handleChange = (index) => (stream) => {
|
||||
const streams = props.streams.slice();
|
||||
|
||||
streams[index] = stream;
|
||||
|
||||
props.onChange(streams);
|
||||
};
|
||||
|
||||
const handleAddStream = () => {
|
||||
const streams = props.streams.slice();
|
||||
|
||||
streams.push({
|
||||
index: props.type === 'video' ? 0 : 1,
|
||||
stream: streams.length,
|
||||
type: 'audio',
|
||||
codec: 'aac',
|
||||
width: 0,
|
||||
height: 0,
|
||||
sampling_hz: 44100,
|
||||
layout: 'stereo',
|
||||
channels: 2,
|
||||
});
|
||||
|
||||
props.onChange(streams);
|
||||
};
|
||||
|
||||
const handleRemoveStream = (index) => () => {
|
||||
const streams = props.streams.toSpliced(index, 1);
|
||||
|
||||
props.onChange(streams);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container spacing={1}>
|
||||
{props.streams.map((stream, index) => (
|
||||
<Grid key={stream.index + ':' + stream.stream} item xs={12}>
|
||||
<Stack>
|
||||
<Typography sx={{ textTransform: 'UPPERCASE', marginBottom: 2 }}>{stream.type}</Typography>
|
||||
<Stream stream={stream} onChange={handleChange(index)} />
|
||||
</Stack>
|
||||
</Grid>
|
||||
))}
|
||||
<Grid item xs={12}>
|
||||
{props.streams.length < 2 && (
|
||||
<Button variant="outlined" color="default" onClick={handleAddStream}>
|
||||
<Trans>Add Audio</Trans>
|
||||
</Button>
|
||||
)}
|
||||
{props.streams.length === 2 && (
|
||||
<Button variant="outlined" color="secondary" onClick={handleRemoveStream(1)}>
|
||||
<Trans>Remove Audio</Trans>
|
||||
</Button>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
Streams.defaultProps = {
|
||||
streams: [],
|
||||
type: '',
|
||||
onChange: () => {},
|
||||
};
|
||||
|
||||
const Component = function (props) {
|
||||
return (
|
||||
<Dialog
|
||||
open={props.open}
|
||||
onClose={props.onClose}
|
||||
title={props.title}
|
||||
buttonsLeft={
|
||||
<Button variant="outlined" color="secondary" onClick={props.onClose}>
|
||||
<Trans>Close</Trans>
|
||||
</Button>
|
||||
}
|
||||
buttonsRight={
|
||||
<Button variant="outlined" color="default" onClick={props.onDone}>
|
||||
<Trans>Save</Trans>
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Streams type={props.type} streams={props.streams} onChange={props.onChange} />
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default Component;
|
||||
|
||||
Component.defaultProps = {
|
||||
open: false,
|
||||
title: '',
|
||||
streams: [],
|
||||
type: '',
|
||||
onClose: null,
|
||||
onDone: () => {},
|
||||
onHelp: null,
|
||||
};
|
||||
@ -60,8 +60,43 @@ const initLogdata = (logdata) => {
|
||||
return data;
|
||||
};
|
||||
|
||||
// This requires updating all processes first.
|
||||
|
||||
// const loglevel = (level) => {
|
||||
// switch(level) {
|
||||
// case 'warning':
|
||||
// return [
|
||||
// '[warning]', '[error]', '[debug]', '[trace]',
|
||||
// ];
|
||||
// case 'error':
|
||||
// return [
|
||||
// '[error]', '[debug]', '[trace]',
|
||||
// ];
|
||||
// case 'debug':
|
||||
// return [
|
||||
// '[debug]', '[trace]',
|
||||
// ];
|
||||
// default:
|
||||
// return [
|
||||
// '[info]', '[warning]', '[error]', '[debug]', '[trace]',
|
||||
// ];
|
||||
// }
|
||||
// }
|
||||
|
||||
// const filterPrelude = (loglines) => {
|
||||
// return loglines
|
||||
// .filter(entry => entry.startsWith('[info]'))
|
||||
// .map(entry => entry.replace('[info]', ''));
|
||||
// }
|
||||
|
||||
// const filterLoglines = (loglines, level) => {
|
||||
// return loglines.filter((entry) => {
|
||||
// return loglevel(level).some((level) => entry[1].includes(level));
|
||||
// });
|
||||
// }
|
||||
|
||||
const formatLogline = (entry) => {
|
||||
let line = '@' + entry[0] + ' ';
|
||||
let line = new Date(entry[0] * 1000).toISOString() + ' ';
|
||||
|
||||
const matches = entry[1].match(/^\[([0-9A-Za-z]+) @ 0x[0-9a-f]+\]/i);
|
||||
if (matches !== null) {
|
||||
@ -107,6 +142,7 @@ const Component = function (props) {
|
||||
<Typography variant="body1" className={classes.title}>
|
||||
<Trans>Banner</Trans>
|
||||
</Typography>
|
||||
{/* <Textarea rows={9} value={filterPrelude(logdata.prelude).join('\n')} scrollTo="bottom" readOnly allowCopy /> */}
|
||||
<Textarea rows={9} value={logdata.prelude.join('\n')} scrollTo="bottom" readOnly allowCopy />
|
||||
</Grid>
|
||||
<Grid item xs={12} marginTop={2}>
|
||||
@ -116,6 +152,7 @@ const Component = function (props) {
|
||||
<Typography variant="body1" className={classes.title}>
|
||||
<Trans>Logging</Trans>
|
||||
</Typography>
|
||||
{/* <Textarea rows={16} value={filterLoglines(logdata.log, 'info').map(formatLogline).join('\n')} scrollTo="bottom" readOnly allowCopy /> */}
|
||||
<Textarea rows={16} value={logdata.log.map(formatLogline).join('\n')} scrollTo="bottom" readOnly allowCopy />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@ -662,14 +662,17 @@ const createInputsOutputs = (sources, profiles, requireVideo = true) => {
|
||||
|
||||
const local = profile.video.encoder.mapping.local.slice();
|
||||
|
||||
if (profile.video.encoder.coder !== 'copy' && profile.video.filter.graph.length !== 0) {
|
||||
// Check if there's already a video filter in the local mapping
|
||||
let filterIndex = local.indexOf('-filter:v');
|
||||
if (filterIndex !== -1) {
|
||||
local[filterIndex + 1] += ',' + profile.video.filter.graph;
|
||||
} else {
|
||||
local.unshift('-filter:v', profile.video.filter.graph);
|
||||
if (profile.video.encoder.coder !== 'copy' && (profile.video.filter.graph.length !== 0 || profile.video.encoder.mapping.filter.length !== 0)) {
|
||||
let filter = profile.video.filter.graph;
|
||||
if (profile.video.encoder.mapping.filter.length !== 0) {
|
||||
if (filter.length !== 0) {
|
||||
filter += ',';
|
||||
}
|
||||
|
||||
filter += profile.video.encoder.mapping.filter.join(',');
|
||||
}
|
||||
|
||||
local.unshift('-filter:v', filter);
|
||||
}
|
||||
|
||||
const options = ['-map', index + ':' + stream.stream, ...local];
|
||||
@ -696,14 +699,17 @@ const createInputsOutputs = (sources, profiles, requireVideo = true) => {
|
||||
|
||||
const local = profile.audio.encoder.mapping.local.slice();
|
||||
|
||||
if (profile.audio.encoder.coder !== 'copy' && profile.audio.filter.graph.length !== 0) {
|
||||
// Check if there's already a audio filter in the local mapping
|
||||
let filterIndex = local.indexOf('-filter:a');
|
||||
if (filterIndex !== -1) {
|
||||
local[filterIndex + 1] += ',' + profile.audio.filter.graph;
|
||||
} else {
|
||||
local.unshift('-filter:a', profile.audio.filter.graph);
|
||||
if (profile.audio.encoder.coder !== 'copy' && (profile.audio.filter.graph.length !== 0 || profile.audio.encoder.mapping.filter.length !== 0)) {
|
||||
let filter = profile.audio.filter.graph;
|
||||
if (profile.audio.encoder.mapping.filter.length !== 0) {
|
||||
if (filter.length !== 0) {
|
||||
filter += ',';
|
||||
}
|
||||
|
||||
filter += profile.audio.encoder.mapping.filter.join(',');
|
||||
}
|
||||
|
||||
local.unshift('-filter:a', filter);
|
||||
}
|
||||
|
||||
options.push('-map', index + ':' + stream.stream, ...local);
|
||||
@ -804,12 +810,6 @@ const initSource = (type, initialSource) => {
|
||||
streams: [],
|
||||
};
|
||||
|
||||
// Default pre-selection for custom audio
|
||||
if (type === 'audio') {
|
||||
source.type = 'virtualaudio';
|
||||
source.settings.source = 'silence';
|
||||
}
|
||||
|
||||
source = {
|
||||
...source,
|
||||
...initialSource,
|
||||
@ -850,11 +850,13 @@ const initProfile = (initialProfile) => {
|
||||
profile.video.encoder.mapping = {
|
||||
global: [],
|
||||
local: profile.video.encoder.mapping,
|
||||
filter: [],
|
||||
};
|
||||
} else {
|
||||
profile.video.encoder.mapping = {
|
||||
global: [],
|
||||
local: [],
|
||||
filter: [],
|
||||
...profile.video.encoder.mapping,
|
||||
};
|
||||
}
|
||||
@ -870,11 +872,13 @@ const initProfile = (initialProfile) => {
|
||||
profile.video.decoder.mapping = {
|
||||
global: [],
|
||||
local: profile.video.decoder.mapping,
|
||||
filter: [],
|
||||
};
|
||||
} else {
|
||||
profile.video.decoder.mapping = {
|
||||
global: [],
|
||||
local: [],
|
||||
filter: [],
|
||||
...profile.video.decoder.mapping,
|
||||
};
|
||||
}
|
||||
@ -905,11 +909,13 @@ const initProfile = (initialProfile) => {
|
||||
profile.audio.encoder.mapping = {
|
||||
global: [],
|
||||
local: profile.audio.encoder.mapping,
|
||||
filter: [],
|
||||
};
|
||||
} else {
|
||||
profile.audio.encoder.mapping = {
|
||||
global: [],
|
||||
local: [],
|
||||
filter: [],
|
||||
...profile.audio.encoder.mapping,
|
||||
};
|
||||
}
|
||||
@ -925,11 +931,13 @@ const initProfile = (initialProfile) => {
|
||||
profile.audio.decoder.mapping = {
|
||||
global: [],
|
||||
local: profile.audio.decoder.mapping,
|
||||
filter: [],
|
||||
};
|
||||
} else {
|
||||
profile.audio.decoder.mapping = {
|
||||
global: [],
|
||||
local: [],
|
||||
filter: [],
|
||||
...profile.audio.decoder.mapping,
|
||||
};
|
||||
}
|
||||
@ -955,12 +963,14 @@ const initStream = (initialStream) => {
|
||||
}
|
||||
|
||||
const stream = {
|
||||
url: '',
|
||||
index: 0,
|
||||
stream: 0,
|
||||
type: '',
|
||||
codec: '',
|
||||
width: 0,
|
||||
height: 0,
|
||||
pix_fmt: '',
|
||||
sampling_hz: 0,
|
||||
layout: '',
|
||||
channels: 0,
|
||||
@ -1026,9 +1036,10 @@ const analyzeStreams = (type, streams) => {
|
||||
* @param {*} streams Array of streams
|
||||
* @param {*} profile A profile
|
||||
* @param {*} encoders Array of supported (by ffmpeg) encoders
|
||||
* @param {*} preselectAudio Whether to preselect an audio profile if type == video
|
||||
* @returns A profile
|
||||
*/
|
||||
const preselectProfile = (type, streams, profile, encoders) => {
|
||||
const preselectProfile = (type, streams, profile, encoders, preselectAudio = true) => {
|
||||
const preselectAudioProfile = (streams, audio) => {
|
||||
audio.stream = -1;
|
||||
audio.encoder.coder = 'none';
|
||||
@ -1110,7 +1121,7 @@ const preselectProfile = (type, streams, profile, encoders) => {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (streams[audio.stream].codec !== 'aac' || streams[audio.stream].codec !== 'mp3') {
|
||||
if (streams[audio.stream].codec !== 'aac' && streams[audio.stream].codec !== 'mp3') {
|
||||
if (audio.encoder.coder === 'copy') {
|
||||
return false;
|
||||
}
|
||||
@ -1164,17 +1175,20 @@ const preselectProfile = (type, streams, profile, encoders) => {
|
||||
profile.video = video;
|
||||
}
|
||||
|
||||
if (isAudioPlausible(streams, profile.audio) === false) {
|
||||
profile.audio = preselectAudioProfile(streams, profile.audio);
|
||||
// Only select audio stream if explicitely asked to.
|
||||
if (preselectAudio === true) {
|
||||
if (isAudioPlausible(streams, profile.audio) === false) {
|
||||
profile.audio = preselectAudioProfile(streams, profile.audio);
|
||||
|
||||
if (profile.audio.stream >= 0) {
|
||||
profile.audio.source = 0;
|
||||
if (profile.audio.stream >= 0) {
|
||||
profile.audio.source = 0;
|
||||
|
||||
profile.custom.selected = false;
|
||||
profile.custom.stream = profile.audio.stream;
|
||||
} else {
|
||||
profile.custom.selected = true;
|
||||
profile.custom.stream = -2;
|
||||
profile.custom.selected = false;
|
||||
profile.custom.stream = profile.audio.stream;
|
||||
} else {
|
||||
profile.custom.selected = false;
|
||||
profile.custom.stream = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type === 'audio') {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user