├── assets ├── vendor │ └── plyr │ │ ├── .nvmrc │ │ ├── .stickler.yml │ │ ├── dist │ │ ├── blank.mp4 │ │ ├── plyr.svg │ │ └── plyr.css │ │ ├── .travis.yml │ │ ├── .gitpod.yml │ │ ├── .prettierrc │ │ ├── .editorconfig │ │ ├── gulpfile.js │ │ ├── .eslintrc │ │ ├── .stylelintrc.json │ │ ├── cspell.json │ │ ├── license.md │ │ ├── contributing.md │ │ ├── package.json │ │ ├── controls.md │ │ └── changelog.md ├── plyr_be_init.js ├── plyr_init.js ├── plyr_playlist.js ├── youtube_vimeo_playlist.js ├── youtube_vimeo_playlist.css └── plyr_playlist.css ├── .gitignore ├── package.yml ├── update_how_to.md ├── .travis.yml ├── lib ├── plyr_mediapool.php ├── rex_var_plyr.php └── rex_plyr.php ├── .github └── workflows │ └── publish-to-redaxo.yml ├── boot.php ├── LICENSE.md ├── fragments └── consent.php └── README.md /assets/vendor/plyr/.nvmrc: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /assets/vendor/plyr/.stickler.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | eslint: 3 | files: 4 | ignore: 5 | - 'node_modules/*' 6 | -------------------------------------------------------------------------------- /assets/vendor/plyr/dist/blank.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfREDAXO/plyr/HEAD/assets/vendor/plyr/dist/blank.mp4 -------------------------------------------------------------------------------- /assets/vendor/plyr/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: lts/* 3 | 4 | script: 5 | - npm run lint 6 | - npm run build 7 | -------------------------------------------------------------------------------- /assets/vendor/plyr/.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - before: npm install && npm i gulp -g 3 | command: gulp 4 | ports: 5 | - port: 3000 6 | onOpen: open-preview 7 | -------------------------------------------------------------------------------- /assets/vendor/plyr/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": false, 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "printWidth": 120 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | assets/vendor/plyr/yarn-error.log 4 | assets/vendor/plyr/.node-version 5 | assets/vendor/plyr/.travis.yml 6 | assets/vendor/plyr/.nvmrc 7 | -------------------------------------------------------------------------------- /assets/vendor/plyr/.editorconfig: -------------------------------------------------------------------------------- 1 | # See editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | -------------------------------------------------------------------------------- /package.yml: -------------------------------------------------------------------------------- 1 | package: plyr 2 | version: '3.24.1' 3 | vendor: 'v3.7.8' 4 | author: Friends Of REDAXO 5 | supportpage: https://github.com/FriendsOfREDAXO/plyr 6 | 7 | requires: 8 | redaxo: '^5.10' 9 | php: 10 | version: '>=7.3' 11 | -------------------------------------------------------------------------------- /update_how_to.md: -------------------------------------------------------------------------------- 1 | # Update erstellen 2 | 3 | plyr lokal mit yarn oder npm builden 4 | 5 | `npm install plyr` 6 | 7 | und den den den Ordner /node_modules/plyr in die assets des AddOns kopieren 8 | 9 | - Version anheben 10 | - PR erstellen. 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - '7.4' 5 | 6 | cache: 7 | directories: 8 | - $HOME/.composer/cache 9 | 10 | before_install: 11 | - phpenv config-rm xdebug.ini || echo "xdebug not available" 12 | 13 | script: 14 | - composer require --dev friendsofredaxo/linter 15 | - vendor/bin/rexlint 16 | -------------------------------------------------------------------------------- /assets/vendor/plyr/gulpfile.js: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Gulp build script 3 | // ========================================================================== 4 | 5 | const gulp = require('gulp'); 6 | const HubRegistry = require('gulp-hub'); 7 | 8 | gulp.registry(new HubRegistry(['tasks/*.js'])); 9 | -------------------------------------------------------------------------------- /assets/vendor/plyr/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": ["@sampotts/eslint-config/es6"], 4 | "env": { 5 | "browser": true, 6 | "es6": true 7 | }, 8 | "globals": { 9 | "Plyr": false, 10 | "jQuery": false 11 | }, 12 | "rules": { 13 | "import/no-cycle": "warn" 14 | }, 15 | "parserOptions": { 16 | "sourceType": "module" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/plyr_mediapool.php: -------------------------------------------------------------------------------- 1 | getParams(); 12 | $file = $params['filename']; 13 | $player = new rex_plyr(); 14 | 15 | if ($player->checkMedia($file) || $player->checkAudio($file)) { 16 | return rex_plyr::outputMedia($file); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-redaxo.yml: -------------------------------------------------------------------------------- 1 | name: Publish release 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | 8 | jobs: 9 | redaxo_publish: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: FriendsOfREDAXO/installer-action@v1 14 | with: 15 | myredaxo-username: ${{ secrets.MYREDAXO_USERNAME }} 16 | myredaxo-api-key: ${{ secrets.MYREDAXO_API_KEY }} 17 | description: ${{ github.event.release.body }} 18 | 19 | -------------------------------------------------------------------------------- /boot.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | $plyr = rex_addon::get('plyr'); 12 | if (rex::isBackend() && is_object(rex::getUser())) { 13 | rex_view::addCssFile($plyr->getAssetsUrl('vendor/plyr/dist/plyr.css')); 14 | rex_view::addJsFile($plyr->getAssetsUrl('vendor/plyr/dist/plyr.min.js')); 15 | rex_view::addJsFile($plyr->getAssetsUrl('plyr_be_init.js')); 16 | rex_extension::register('MEDIA_DETAIL_SIDEBAR', 'plyr_mediapool::show_sidebar'); 17 | } 18 | -------------------------------------------------------------------------------- /assets/vendor/plyr/.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["stylelint-selector-bem-pattern"], 3 | "extends": ["stylelint-config-sass-guidelines", "stylelint-config-prettier"], 4 | "customSyntax": "postcss-scss", 5 | "rules": { 6 | "selector-class-pattern": null, 7 | "selector-no-qualifying-type": [ 8 | true, 9 | { 10 | "ignore": ["attribute", "class"] 11 | } 12 | ], 13 | "max-nesting-depth": 4, 14 | "plugin/selector-bem-pattern": { 15 | "preset": "bem", 16 | "componentName": "(([a-z0-9]+(?!-$)-?)+)", 17 | "componentSelectors": { 18 | "initial": "\\.{componentName}(((__|--)(([a-z0-9\\[\\]'=]+(?!-$)-?)+))+)?$" 19 | }, 20 | "ignoreSelectors": [".*\\.has-.*", ".*\\.is-.*"] 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /assets/plyr_be_init.js: -------------------------------------------------------------------------------- 1 | $(document).on('rex:ready',function() { 2 | const players = Plyr.setup('.rex-plyr', { 3 | youtube: { 4 | noCookie: true 5 | }, 6 | vimeo: { 7 | dnt: false 8 | }, 9 | iconUrl: '/assets/addons/plyr/vendor/plyr/dist/plyr.svg', 10 | blankVideo: '/assets/addons/plyr/vendor/plyr/dist/blank.mp4' 11 | }); 12 | if (document.querySelector('.rex-plyr')) { 13 | players.forEach(function (player) { 14 | player.on('play', function () { 15 | var others = players.filter(other => other != player) 16 | others.forEach(function (other) { 17 | other.pause(); 18 | }) 19 | }); 20 | }); 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /assets/plyr_init.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function () { 2 | const players = Plyr.setup('.rex-plyr', { 3 | youtube: { 4 | noCookie: true 5 | }, 6 | vimeo: { 7 | dnt: false 8 | }, 9 | iconUrl: '/assets/addons/plyr/vendor/plyr/dist/plyr.svg', 10 | blankVideo: '/assets/addons/plyr/vendor/plyr/dist/blank.mp4' 11 | }); 12 | if (document.querySelector('.rex-plyr')) { 13 | players.forEach(function (player) { 14 | player.on('play', function () { 15 | var others = players.filter(other => other != player) 16 | others.forEach(function (other) { 17 | other.pause(); 18 | }) 19 | }); 20 | }); 21 | } 22 | 23 | }); 24 | 25 | -------------------------------------------------------------------------------- /assets/vendor/plyr/cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2", 3 | "ignorePaths": ["package.json", "dist/*", "demo/node_modules/*"], 4 | "dictionaryDefinitions": [], 5 | "dictionaries": ["en-gb", "softwareTerms", "html", "css", "typescript"], 6 | "words": [ 7 | "autopause", 8 | "autoplay", 9 | "bote", 10 | "cfda", 11 | "classname", 12 | "digbmx", 13 | "fastly", 14 | "fullscreen", 15 | "gordita", 16 | "loadjs", 17 | "magazin", 18 | "menuitemradio", 19 | "noupe", 20 | "otransitionend", 21 | "playsinline", 22 | "plyr", 23 | "rutheneum", 24 | "seektime", 25 | "selz", 26 | "sparkk", 27 | "srclang", 28 | "strol", 29 | "stylelint", 30 | "unmute", 31 | "videospiele", 32 | "xywh" 33 | ], 34 | "ignoreWords": [], 35 | "import": [] 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Friends Of REDAXO 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/vendor/plyr/license.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Sam Potts 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /lib/rex_var_plyr.php: -------------------------------------------------------------------------------- 1 | 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | class rex_var_plyr extends rex_var 14 | { 15 | protected function getOutput() 16 | { 17 | $controls = $poster = null; 18 | $id = $this->getArg('id', 0, true); 19 | if (!in_array($this->getContext(), ['module', 'action']) || !is_numeric($id) || $id < 1 || $id > 20) { 20 | return false; 21 | } 22 | $value = $this->getContextData()->getValue('value' . $id); 23 | 24 | if ($this->hasArg('controls') && $this->getArg('controls')) { 25 | $controls = $this->getArg('controls'); 26 | } 27 | 28 | if ($this->hasArg('poster') && $this->getArg('poster')) { 29 | $poster = $this->getArg('poster'); 30 | } 31 | 32 | $out = ''; 33 | if ($value) { 34 | $out = rex_plyr::outputMedia($value, $controls, $poster); 35 | } 36 | // Reine Textausgaben müssen mit 'self::quote()' als String maskiert werden. 37 | return self::quote($out); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /fragments/consent.php: -------------------------------------------------------------------------------- 1 | type == 'youtube' ):?> 2 | 10 | 11 | type == 'vimeo' ):?> 12 | 20 | 21 | -------------------------------------------------------------------------------- /assets/plyr_playlist.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Create HTML playlist below video player 3 | * @param Plyr[] players 4 | * @param int player_id 5 | * @param string myPlaylist JSON playlist 6 | */ 7 | function loadPlaylist(players, player_id, myPlaylist) { 8 | $('
').insertAfter('#player-' + player_id); 9 | 10 | var playingclass = ""; 11 | var items = []; 12 | $.each(myPlaylist, function (id, val) { 13 | if (0 === id) { 14 | playingclass = "pls-playing"; 15 | } 16 | else { 17 | playingclass = ""; 18 | } 19 | 20 | items.push( 21 | '
  • ' + 22 | (val.poster ? ' ' : '') + 23 | val.title + (val.author ? " - " + val.author : "") + "
  • "); 24 | 25 | }); 26 | $('#playlist-' + player_id).html(items.join("")); 27 | 28 | setTimeout(function () {}, 600); 29 | 30 | $(document).on("click", "ul.plyr-playlist#playlist-"+ player_id +" li a", function (event) { 31 | event.preventDefault(); 32 | 33 | $("ul.plyr-playlist#playlist-"+ player_id +" li.pls-playing").removeClass("pls-playing"); 34 | $(this) 35 | .parent() 36 | .addClass("pls-playing"); 37 | 38 | var video_id = $(this).data("video-id"); 39 | // var video_type = $(this).data("type"); 40 | // var video_title = $(this).text(); 41 | 42 | var playlistID = $(this).parent().parent().attr('id'); 43 | players.forEach(function (instance) { 44 | if(('playlist-' + instance.config.plyrId) === playlistID) { 45 | instance.media.setAttribute('src', video_id); 46 | instance.play(); 47 | } 48 | }); 49 | 50 | $('#playlist-' + player_id).scrollTo(".pls-playing", 300); 51 | }); 52 | } 53 | 54 | /****** GC ScrollTo **********/ 55 | jQuery.fn.scrollTo = function (elem, speed) { 56 | jQuery(this).animate( 57 | { 58 | scrollTop: 59 | jQuery(this).scrollTop() - 60 | jQuery(this).offset().top + 61 | jQuery(elem).offset().top 62 | }, 63 | speed === undefined ? 1000 : speed 64 | ); 65 | return this; 66 | }; 67 | -------------------------------------------------------------------------------- /assets/youtube_vimeo_playlist.js: -------------------------------------------------------------------------------- 1 | function loadPlaylist(target, myPlaylist, id, listclass, limit) { 2 | var players = Plyr.setup(target); 3 | $("li.pls-playing").removeClass("pls-playing"); 4 | $(".plyr-playlist-wrapper").remove(); 5 | 6 | 7 | limit = limit - 1; 8 | 9 | 10 | if (myPlaylist) { 11 | 12 | PlyrPlaylist(".plyr-playlist", myPlaylist, limit, id, listclass); 13 | //return 14 | } 15 | 16 | function PlyrPlaylist(target, myPlaylist, limit, id, listclass) { 17 | $('
    ').insertAfter(id); 18 | 19 | 20 | var startwith = 0; // Maybe a playlist option to start with choosen video 21 | 22 | var playingclass = ""; 23 | var items = []; 24 | $.each(myPlaylist, function (id, val) { 25 | 26 | if (0 === id) playingclass = "pls-playing"; 27 | else playingclass = ""; 28 | 29 | 30 | items.push( 31 | '
  • ' + 32 | val.title + "" + val.author + "
  • "); 33 | 34 | if (id == limit) 35 | return false; 36 | 37 | }); 38 | $(target).html(items.join("")); 39 | 40 | 41 | 42 | players[0].on("ended", function (event) { 43 | var $next = $(".plyr-playlist .pls-playing") 44 | .next() 45 | .find("a") 46 | .trigger("click"); 47 | }); 48 | 49 | 50 | 51 | } 52 | 53 | $(document).on("click", "ul.plyr-playlist li a", function (event) { 54 | event.preventDefault(); 55 | $("li.pls-playing").removeClass("pls-playing"); 56 | $(this) 57 | .parent() 58 | .addClass("pls-playing"); 59 | var video_id = $(this).data("plyr-embed-id"); 60 | 61 | var video_type = $(this).data("plyr-provider"); 62 | var video_title = $(this).text(); 63 | players[0].source = { 64 | type: 'video', 65 | title: "video_title", 66 | sources: [{ provider: video_type, src: video_id, type: video_type }] 67 | }; 68 | 69 | players[0].on("ready", function (event) { 70 | players[0].play(); 71 | }); 72 | 73 | 74 | $(".plyr-playlist").scrollTo(".pls-playing", 300); 75 | 76 | }); 77 | 78 | players[0].on("ready", function (event) { 79 | 80 | 81 | }); 82 | 83 | } 84 | 85 | 86 | /****** GC ScrollTo **********/ 87 | jQuery.fn.scrollTo = function (elem, speed) { 88 | jQuery(this).animate( 89 | { 90 | scrollTop: 91 | jQuery(this).scrollTop() - 92 | jQuery(this).offset().top + 93 | jQuery(elem).offset().top 94 | }, 95 | speed === undefined ? 1000 : speed 96 | ); 97 | return this; 98 | }; 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /assets/vendor/plyr/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We welcome bug reports, feature requests and pull requests. If you want to help us out, please follow these guidelines, in order to avoid redundant work. 4 | 5 | ## Support 6 | 7 | Before asking questions, read our [documentation](https://github.com/sampotts/plyr) and [FAQ](https://github.com/sampotts/plyr/wiki/FAQ). 8 | 9 | If these doesn't answer your question 10 | 11 | - Use [Stack Overflow](https://stackoverflow.com/) for questions that doesn't directly involve Plyr. This includes for example how to use Javascript, CSS or HTML5 media in general, and how to use other frameworks, libraries and technology. 12 | - Use [our Slack](https://bit.ly/plyr-chat) if you need help using Plyr or have questions about Plyr. 13 | 14 | ## Commenting 15 | 16 | When commenting, keep a civil tone and stay on topic. Don't ask for [support](#support), or post "+1" or "I agree" type of comments. Use the emojis instead. 17 | 18 | Asking for the status on issues is discouraged. Unless someone has explicitly said in an issue that it's work in progress, most likely that means no one is working on it. We have a lot to do, and it may not be a top priority for us. 19 | 20 | We _may_ moderate discussions. We do this to avoid threads being "hijacked", to avoid confusion in case the content is misleading or outdated, and to avoid bothering people with github notifications. 21 | 22 | ## Creating issues 23 | 24 | Please follow the instructions in our issue templates. Don't use github issues to ask for [support](#support). 25 | 26 | ## Contributing features and documentation 27 | 28 | - If you want to add a feature or make critical changes, you may want to ensure that this is something we also want (so you don't waste your time). Ask us about this in the corresponding issue if there is one, or on [our Slack](https://bit.ly/plyr-chat) otherwise. 29 | 30 | - Fork Plyr, and create a new branch in your fork, based on the **develop** branch 31 | 32 | - To test locally, you can use the demo site. First make sure you have installed the dependencies with `npm install` or `yarn`. Run `gulp` to build and it will run a local web server for development and watch for any changes. 33 | 34 | ### Online one-click setup for contributing 35 | 36 | You can use Gitpod (a free online VS Code-like IDE) for contributing. With a single click it will launch a workspace and automatically: 37 | 38 | - clone the plyr repo. 39 | - install the dependencies with `yarn install` in root directory and "demo" directory. 40 | - run `gulp` in root directory to start the dev server. 41 | 42 | So that you can start straight away. 43 | 44 | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/) 45 | 46 | - Develop and test your modifications. 47 | 48 | - Preferably commit your changes as independent logical chunks, with meaningful messages. Make sure you do not commit unnecessary files or changes, such as the build output, or logging and breakpoints you added for testing. 49 | 50 | - If your modifications changes the documented behavior or add new features, document these changes in [README.md](README.md). 51 | 52 | - When finished, push the changes to your GitHub repository and send a pull request. Describe what your PR does. 53 | 54 | - If the Travis build fails, or if you get a code review with change requests, you can fix these by pushing new or rebased commits to the branch. 55 | -------------------------------------------------------------------------------- /assets/vendor/plyr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plyr", 3 | "version": "3.7.8", 4 | "description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player", 5 | "homepage": "https://plyr.io", 6 | "author": "Sam Potts ", 7 | "main": "dist/plyr.js", 8 | "types": "src/js/plyr.d.ts", 9 | "module": "dist/plyr.min.mjs", 10 | "jsnext:main": "dist/plyr.min.mjs", 11 | "browser": "dist/plyr.min.js", 12 | "sass": "src/sass/plyr.scss", 13 | "style": "dist/plyr.css", 14 | "keywords": [ 15 | "HTML5 Video", 16 | "HTML5 Audio", 17 | "Media Player", 18 | "DASH", 19 | "Shaka", 20 | "WordPress", 21 | "HLS" 22 | ], 23 | "license": "MIT", 24 | "repository": { 25 | "type": "git", 26 | "url": "git://github.com/sampotts/plyr.git" 27 | }, 28 | "bugs": { 29 | "url": "https://github.com/sampotts/plyr/issues" 30 | }, 31 | "browserslist": "> 1%", 32 | "devDependencies": { 33 | "@babel/core": "^7.20.2", 34 | "@babel/plugin-proposal-class-properties": "^7.18.6", 35 | "@babel/plugin-proposal-optional-chaining": "^7.18.9", 36 | "@babel/preset-env": "^7.20.2", 37 | "@sampotts/eslint-config": "1.1.7", 38 | "autoprefixer": "^10.4.13", 39 | "aws-sdk": "^2.1256.0", 40 | "babel-eslint": "^10.1.0", 41 | "browser-sync": "^2.27.10", 42 | "colorette": "2.0.19", 43 | "cspell": "^6.14.2", 44 | "cssnano": "^5.1.14", 45 | "del": "^6.1.1", 46 | "eslint": "^7.23.0", 47 | "fancy-log": "^2.0.0", 48 | "git-branch": "^2.0.1", 49 | "gulp": "^4.0.2", 50 | "gulp-awspublish": "^6.0.2", 51 | "gulp-better-rollup": "^4.0.1", 52 | "gulp-filter": "^7.0.0", 53 | "gulp-header": "^2.0.9", 54 | "gulp-hub": "^4.2.0", 55 | "gulp-if": "^3.0.0", 56 | "gulp-imagemin": "^7.1.0", 57 | "gulp-open": "^3.0.1", 58 | "gulp-plumber": "^1.2.1", 59 | "gulp-postcss": "^9.0.1", 60 | "gulp-rename": "^2.0.0", 61 | "gulp-replace": "^1.1.3", 62 | "gulp-sass": "^5.1.0", 63 | "gulp-size": "^4.0.1", 64 | "gulp-sourcemaps": "^3.0.0", 65 | "gulp-svgstore": "^9.0.0", 66 | "gulp-terser": "^2.1.0", 67 | "postcss": "^8.4.19", 68 | "postcss-custom-properties": "^12.1.9", 69 | "postcss-scss": "^4.0.5", 70 | "prettier-eslint": "^12.0.0", 71 | "prettier-stylelint": "^0.4.2", 72 | "remark-cli": "^11.0.0", 73 | "remark-validate-links": "^12.1.0", 74 | "rollup": "^3.3.0", 75 | "rollup-plugin-babel": "^4.4.0", 76 | "rollup-plugin-commonjs": "^10.1.0", 77 | "rollup-plugin-node-resolve": "^5.2.0", 78 | "sass": "^1.56.1", 79 | "stylelint": "^14.15.0", 80 | "stylelint-config-prettier": "^9.0.4", 81 | "stylelint-config-sass-guidelines": "^9.0.1", 82 | "stylelint-selector-bem-pattern": "^2.1.1" 83 | }, 84 | "dependencies": { 85 | "core-js": "^3.26.1", 86 | "custom-event-polyfill": "^1.0.7", 87 | "loadjs": "^4.2.0", 88 | "rangetouch": "^2.0.1", 89 | "url-polyfill": "^1.1.12" 90 | }, 91 | "scripts": { 92 | "build": "gulp build", 93 | "lint": "eslint src/js && npm run remark && stylelint **/*.scss", 94 | "lint:fix": "eslint --fix src/js && stylelint **/*.scss --fix", 95 | "remark": "remark -f --use 'validate-links=repository:\"sampotts/plyr\"' '{,!(node_modules),.?**/}*.md'", 96 | "deploy": "npm run lint && gulp version && gulp build && gulp deploy", 97 | "format": "prettier --write \"./{src,demo/src}/**/*.{js,scss}\"", 98 | "spellcheck": "cspell \"**/*.{js,md,scss,json}\" --no-must-find-files", 99 | "start": "gulp" 100 | } 101 | } -------------------------------------------------------------------------------- /assets/youtube_vimeo_playlist.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --plyr-color-main: rgba(65, 88, 102, 0.68); 3 | --plyr-video-background: #000; 4 | --plyr-control-icon-size: 20px; 5 | --plyr-video-control-background-hover: rgba(65, 88, 102, 0.68); 6 | --plyr-video-controls-background: transparent; 7 | } 8 | 9 | 10 | 11 | 12 | .plyr__video-wrapper, .plyr--video { 13 | background: #000; 14 | } 15 | 16 | 17 | 18 | .plyr__controls__item plyr__control {background: #000;} 19 | 20 | 21 | .player { 22 | z-index: 300; 23 | overflow: hidden; 24 | } 25 | 26 | /* Playlist */ 27 | 28 | /* scrollbar rules have to be separate, browsers not supporting this syntax will skip them when combined. */ 29 | 30 | .plyr-playlist-wrapper ul::-webkit-scrollbar { 31 | width: 6px; 32 | } 33 | 34 | 35 | .plyr-playlist .pls-playing, .plyr-playlist li a, .plyr-playlist-wrapper .plyr-playlist li a { 36 | cursor: pointer; 37 | } 38 | 39 | .plyr-playlist-wrapper ul::-webkit-scrollbar-track { 40 | background: rgba(0, 0, 0, 1); 41 | border-radius: 10px; 42 | -moz-border-radius: 10px; 43 | -webkit-border-radius: 10px; 44 | } 45 | 46 | .plyr-playlist-wrapper ul::-webkit-scrollbar-thumb { 47 | border-radius: 10px; 48 | -moz-border-radius: 10px; 49 | -webkit-border-radius: 10px; 50 | background: #fff; 51 | } 52 | 53 | .plyr-playlist-wrapper { 54 | position: relative; 55 | overflow: hidden; 56 | } 57 | 58 | .plyr-playlist-wrapper .plyr-playlist { 59 | user-select: none; 60 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 61 | position: relative; 62 | margin-top: 0; 63 | padding: 6px 4px; 64 | width: 100%; 65 | box-sizing: border-box; 66 | } 67 | 68 | .plyr-playlist-wrapper ul { 69 | padding: 0; 70 | margin: 0; 71 | height: 100%; 72 | overflow-y: auto; 73 | -webkit-overflow-scrolling: touch; 74 | } 75 | 76 | .plyr-playlist-wrapper ul li { 77 | /* border-bottom: 1px solid rgba(0, 0, 0, 0.05); */ 78 | } 79 | 80 | .plyr-playlist-wrapper .plyr-playlist li { 81 | list-style: none; 82 | padding: 0px; 83 | margin-bottom: 3px; 84 | 85 | } 86 | 87 | .plyr-playlist-wrapper .plyr-playlist li.pls-playing, .plyr-playlist-wrapper .plyr-playlist li:hover { 88 | color: white; 89 | background-color: rgba(255, 255, 255, 0.09); 90 | } 91 | 92 | .plyr-playlist-wrapper .plyr-playlist li.pls-playing a { 93 | color: #fff; 94 | background: #415866 ; 95 | 96 | } 97 | 98 | .plyr-playlist-wrapper .plyr-playlist li.pls-playing { 99 | background: transparent; 100 | 101 | } 102 | 103 | .plyr-playlist-wrapper .plyr-playlist li a { 104 | text-decoration: none; 105 | -webkit-transition:all 0.8s ease; 106 | -moz-transition:all 0.8s ease-in-out; 107 | -o-transition:all 0.8s ease-in-out; 108 | -ms-transition:all 0.8s ease-in-out; 109 | transition:all 0.8s ease-in-out; 110 | color: #444; 111 | display: block; 112 | padding: 15px 0; 113 | outline: none; 114 | padding: 10px; 115 | padding-left: 20px; 116 | vertical-align: middle; 117 | /* padding-bottom: 15px; */ 118 | } 119 | 120 | .plyr-playlist-wrapper .plyr-playlist li:last-child a { 121 | border-bottom: 0; 122 | } 123 | 124 | .plyr-playlist li a:hover, .plyr-playlist li a:focus, .plyr-playlist li a:active { 125 | color: #191919; 126 | color: #fff; 127 | background: #415866 ; 128 | } 129 | 130 | .plyr-miniposter { 131 | width: auto; 132 | height: 2em; 133 | -webkit-background-size: cover; 134 | background-size: cover; 135 | background-repeat: no-repeat; 136 | background-position: center center; 137 | float: left; 138 | margin-right: 10px; 139 | border-radius: 0; 140 | -moz-border-radius: 0; 141 | -webkit-border-radius: 0; 142 | } 143 | 144 | /*******************/ 145 | 146 | .plyr-type-playlist plyr-playlist a.plyr-playlist-item-remove { 147 | float: right; 148 | margin-right: 15px; 149 | background-color: transparent; 150 | } 151 | -------------------------------------------------------------------------------- /assets/vendor/plyr/dist/plyr.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/vendor/plyr/controls.md: -------------------------------------------------------------------------------- 1 | # Controls 2 | 3 | This is the markup that is rendered for the Plyr controls. You can use the default controls or provide a customized version of markup based on your needs. You can pass the following to the `controls` option: 4 | 5 | - `Array` of options (this builds the default controls based on your choices) 6 | - `Element` with the controls 7 | - `String` containing the desired HTML 8 | - `false` (or empty string or array) to disable all controls 9 | - `Function` that will be executed and should return one of the above 10 | 11 | ## Using default controls 12 | 13 | If you want to use the standard controls as they are, you don't need to pass any options. If you want to turn on off controls, here's the full list: 14 | 15 | ```javascript 16 | controls: [ 17 | 'play-large', // The large play button in the center 18 | 'restart', // Restart playback 19 | 'rewind', // Rewind by the seek time (default 10 seconds) 20 | 'play', // Play/pause playback 21 | 'fast-forward', // Fast forward by the seek time (default 10 seconds) 22 | 'progress', // The progress bar and scrubber for playback and buffering 23 | 'current-time', // The current time of playback 24 | 'duration', // The full duration of the media 25 | 'mute', // Toggle mute 26 | 'volume', // Volume control 27 | 'captions', // Toggle captions 28 | 'settings', // Settings menu 29 | 'pip', // Picture-in-picture (currently Safari only) 30 | 'airplay', // Airplay (currently Safari only) 31 | 'download', // Show a download button with a link to either the current source or a custom URL you specify in your options 32 | 'fullscreen', // Toggle fullscreen 33 | ]; 34 | ``` 35 | 36 | ### Internationalization using default controls 37 | 38 | You can provide an `i18n` object as one of your options when initializing the plugin which we be used when rendering the controls. 39 | 40 | #### Example 41 | 42 | ```javascript 43 | i18n: { 44 | restart: 'Restart', 45 | rewind: 'Rewind {seektime} secs', 46 | play: 'Play', 47 | pause: 'Pause', 48 | fastForward: 'Forward {seektime} secs', 49 | seek: 'Seek', 50 | played: 'Played', 51 | buffered: 'Buffered', 52 | currentTime: 'Current time', 53 | duration: 'Duration', 54 | volume: 'Volume', 55 | mute: 'Mute', 56 | unmute: 'Unmute', 57 | enableCaptions: 'Enable captions', 58 | disableCaptions: 'Disable captions', 59 | enterFullscreen: 'Enter fullscreen', 60 | exitFullscreen: 'Exit fullscreen', 61 | frameTitle: 'Player for {title}', 62 | captions: 'Captions', 63 | settings: 'Settings', 64 | speed: 'Speed', 65 | normal: 'Normal', 66 | quality: 'Quality', 67 | loop: 'Loop', 68 | start: 'Start', 69 | end: 'End', 70 | all: 'All', 71 | reset: 'Reset', 72 | disabled: 'Disabled', 73 | advertisement: 'Ad', 74 | } 75 | ``` 76 | 77 | Note: `{seektime}` will be replaced with your configured seek time or the default. For example "Forward {seektime} secs" would render as "Forward 10 secs". 78 | 79 | ## Using custom HTML 80 | 81 | You can specify the HTML as a `String` or your `Function` return for the controls using the `controls` option. 82 | 83 | The classes and data attributes used in your template should match the `selectors` option if you change any. 84 | 85 | You need to add several placeholders to your HTML template that are replaced when rendering: 86 | 87 | - `{id}` - the dynamically generated ID for the player (for form controls) 88 | - `{seektime}` - the seek time specified in options for fast forward and rewind 89 | - `{title}` - the title of your media, if specified 90 | 91 | ### Limitations 92 | 93 | - Currently the settings menus are not supported with custom controls HTML 94 | - AirPlay and PiP buttons can be added but you will have to manage feature detection 95 | 96 | ### Example 97 | 98 | Here's an example of custom controls markup (this is just all default controls shown). 99 | 100 | ```javascript 101 | const controls = ` 102 |
    103 | 107 | 111 | 117 | 121 |
    122 | 123 | % buffered 124 | 00:00 125 |
    126 |
    00:00
    127 |
    00:00
    128 | 134 |
    135 | 136 |
    137 | 143 | 149 |
    150 | `; 151 | 152 | // Setup the player 153 | const player = new Plyr('#player', { controls }); 154 | ``` 155 | -------------------------------------------------------------------------------- /lib/rex_plyr.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | /* add return types*/ 12 | class rex_plyr 13 | { 14 | /** 15 | * @param string $url 16 | * 17 | * @return string 18 | */ 19 | public static function checkUrl($url): string 20 | { 21 | if ($url) { 22 | if (false === filter_var($url, FILTER_VALIDATE_URL)) { 23 | } 24 | if (true === file_exists(rex_path::media($url))) { 25 | return rex_url::media($url); 26 | } 27 | 28 | }return $url; 29 | } 30 | 31 | /** 32 | * @param string $url 33 | * 34 | * @return bool 35 | */ 36 | public static function checkYoutube($url): bool 37 | { 38 | if (preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=|shorts/)|youtu\.be/)([^"&?/ ]{11})%i', $url)) { 39 | return true; 40 | } 41 | return false; 42 | } 43 | 44 | /** 45 | * @param string $url 46 | * 47 | * @return string 48 | */ 49 | public static function getYoutubeId($url): string 50 | { 51 | $youtubeID = ''; 52 | if (preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=|shorts/)|youtu\.be/)([^"&?/ ]{11})%i', $url, $match)) { 53 | $youtubeID = $match[1]; 54 | } 55 | return $youtubeID; 56 | } 57 | 58 | /** 59 | * @param string $url 60 | * 61 | * @return bool 62 | */ 63 | public static function checkMedia($url): bool 64 | { 65 | $media = rex_media::get($url); 66 | $checkPath = pathinfo($url); 67 | if ($media) { 68 | if ('mp4' == strtolower($checkPath['extension'])) { 69 | return true; 70 | } 71 | if ('mov' == strtolower($checkPath['extension'])) { 72 | return true; 73 | } 74 | if ('m4v' == strtolower($checkPath['extension'])) { 75 | return true; 76 | } 77 | } 78 | return false; 79 | } 80 | 81 | /** 82 | * @param string $url 83 | * 84 | * @return bool 85 | */ 86 | public static function checkVideo($url): bool 87 | { 88 | if (self::checkYoutube($url) || self::checkVimeo($url) || self::checkMedia($url) || self::checkExternalMp4($url)) { 89 | return true; 90 | } 91 | return false; 92 | } 93 | 94 | /** 95 | * Check if the provided audio URL corresponds to a supported audio format. 96 | * 97 | * @param string $url The URL of the audio file to check. 98 | * 99 | * @return string|bool If the audio format is supported, returns the audio format's extension (e.g., 'mp3', 'ogg', etc.). 100 | * If the audio format is not supported or the provided URL is invalid, returns false. 101 | */ 102 | public static function checkAudio($url): string | bool 103 | { 104 | // Get the audio object from the given URL 105 | $audio = rex_media::get($url); 106 | $checkPath = pathinfo($url); 107 | if ($audio) { 108 | $extension = strtolower($checkPath['extension']); 109 | $supportedFormats = ['mp3', 'ogg', 'wav', 'webm', 'm4a']; 110 | if (in_array($extension, $supportedFormats)) { 111 | return $extension; 112 | } 113 | } 114 | return false; 115 | } 116 | 117 | /** 118 | * @param string $url 119 | * 120 | * @return bool 121 | */ 122 | public static function checkVimeo($url): bool 123 | { 124 | if (preg_match('~(?:)?(?:

    .*

    )?~ix', $url)) { 125 | return true; 126 | } 127 | return false; 128 | } 129 | 130 | /** 131 | * @param string $url 132 | * 133 | * @return string 134 | */ 135 | public static function getVimeoId($url): string 136 | { 137 | $vimeoID = ''; 138 | if (preg_match('~(?:)?(?:

    .*

    )?~ix', $url, $match)) { 139 | $vimeoID = $match[2]; 140 | } 141 | return $vimeoID; 142 | } 143 | 144 | /** 145 | * checkExternalMp4. 146 | * 147 | * @param string $url 148 | * @return bool 149 | */ 150 | public static function checkExternalMp4($url): bool 151 | { 152 | if (true == filter_var($url, FILTER_VALIDATE_URL)) { 153 | if ($checkurl = get_headers($url, 1)) { 154 | if ('video/mp4' == $checkurl['Content-Type']) { 155 | return true; 156 | } 157 | } 158 | 159 | }return false; 160 | } 161 | 162 | /** 163 | * @param string $url 164 | * @param string $setup 165 | * @param string $poster 166 | * 167 | * @return string 168 | */ 169 | public static function outputMedia($url, $setup = null, $poster = null, $consent = null): string 170 | { 171 | $player = new self(); 172 | $link = $player->checkUrl($url); 173 | $consent_content = ''; 174 | $consent_suffix = ' '; 175 | $out = $nopreload = ''; 176 | 177 | if ($consent) { 178 | $consent_suffix = '_consent_'; 179 | $consent_content = $consent; 180 | } 181 | if ($setup) { 182 | $control_attr = explode(',', $setup); 183 | if ($control_attr && in_array('nopreload', $control_attr)) { 184 | $nopreload = ' preload="none"'; 185 | } 186 | $player_conf = json_encode($control_attr); 187 | $setup = ' data-plyr-config=\'{"controls":' . $player_conf . '}\''; 188 | $autoplay = ($control_attr && in_array('autoplay', $control_attr)) ? ' autoplay muted' : ''; 189 | $loop = ($control_attr && in_array('loop', $control_attr)) ? ' loop' : ''; 190 | $control_nojs = ''; 191 | if ($autoplay || $loop) { 192 | if ($autoplay && $loop) { 193 | $control_nojs = (count($control_attr) > 2) ? ' controls' : ''; 194 | } elseif (count($control_attr) > 1) { 195 | $control_nojs = ' controls'; 196 | } 197 | } 198 | } else { 199 | $setup = ''; 200 | $autoplay = ''; 201 | $loop = ''; 202 | $control_nojs = ''; 203 | } 204 | $provider = ''; 205 | $embed_id = ''; 206 | 207 | if (true == $player->checkYoutube($link)) { 208 | $provider = 'youtube'; 209 | $embed_id = $player->getYoutubeId($link); 210 | } 211 | 212 | if (true == $player->checkVimeo($link)) { 213 | $provider = 'vimeo'; 214 | $embed_id = $player->getVimeoId($link); 215 | } 216 | 217 | if ('' != $provider) { 218 | $out = '
    ' . $consent_content . '
    '; 219 | } 220 | 221 | if (false !== $player->checkMedia($url) || true === $player->checkExternalMp4($url)) { 222 | if ($poster) { 223 | $poster = ' data-poster="' . $poster . '"'; 224 | } else { 225 | $poster = ''; 226 | } 227 | $out = ' 228 | 231 | '; 232 | } 233 | 234 | $audioFormat = $player->checkAudio($url); 235 | 236 | if (false != $audioFormat) { 237 | $out = ' 238 | 241 | '; 242 | } 243 | 244 | return $out; 245 | } 246 | 247 | /** 248 | * consent_helper. 249 | * 250 | * @param string $url 251 | * @param string $return_when_empty 252 | */ 253 | public static function consent($url = '', $setup = null, $poster = null, $return_when_empty = ''): string 254 | { 255 | $consent = ''; 256 | if (self::checkVimeo($url)) { 257 | $fragment = new rex_fragment(); 258 | $fragment->setVar('url', $url, false); 259 | $fragment->setVar('type', 'vimeo', false); 260 | $consent = $fragment->parse('consent.php'); 261 | return self::outputMedia($url, $setup, $poster, $consent); 262 | } 263 | if (self::checkYoutube($url)) { 264 | $fragment = new rex_fragment(); 265 | $fragment->setVar('url', $url, false); 266 | $fragment->setVar('type', 'youtube', false); 267 | $consent = $fragment->parse('consent.php'); 268 | return self::outputMedia($url, $setup, $poster, $consent); 269 | } 270 | if ('cke5' == $return_when_empty) { 271 | return ''; 272 | } 273 | return self::outputMedia($url, $setup, $poster); 274 | } 275 | 276 | /** 277 | * cke_oembed_helper. 278 | */ 279 | public static function cke_oembed_helper($setup = null): void 280 | { 281 | rex_extension::register('OUTPUT_FILTER', static function ($ep) { 282 | $string = $ep->getSubject(); 283 | return preg_replace_callback('/<\/oembed>/is', static function ($video) { 284 | return self::consent($video[1], $setup = '', $poster = '', 'cke5'); 285 | }, $string); 286 | }, rex_extension::LATE); 287 | } 288 | 289 | /** 290 | * cke_oembed_helper. 291 | * 292 | * @return void 293 | */ 294 | public static function oembed_replace($string, $setup = null): string 295 | { 296 | return preg_replace_callback('/<\/oembed>/is', static function ($video) { 297 | return self::consent($video[1], $setup, $poster, 'cke5'); 298 | }, $string); 299 | } 300 | 301 | /** 302 | * @param array $media_filenames Array with video/mp4 audio/mp3 file names from media pool 303 | * @param string $setup 304 | * 305 | * @return string 306 | */ 307 | public static function outputMediaPlaylist($media_filenames, $setup = null) 308 | { 309 | $plyr = rex_addon::get('plyr'); 310 | $svg_url = $plyr->getAssetsUrl('vendor/plyr/dist/plyr.svg'); 311 | $blank_mp4 = $plyr->getAssetsUrl('vendor/plyr/dist/blank.mp4'); 312 | $plyr_id = random_int(0, getrandmax()); 313 | $out = '
    '; 314 | $out .= '
    '; 315 | $plyr_media = self::outputMedia($media_filenames[0], $setup); 316 | $out .= str_replace( 317 | 'class="rex-plyr"', 318 | 'class="rex-plyr" id="plyr-' . $plyr_id . '"', 319 | str_replace("data-plyr-config='{", 'data-plyr-config=\'{"plyrId":"' . $plyr_id . '",', $plyr_media) 320 | ); 321 | $out .= '
    '; 322 | $out .= '
    '; 323 | $out .= ''; 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # REDAXO-AddOn: Plyr 3 | 4 | 🚨 Die Entwicklung dieses AddOns wurde eingestellt und wurde daher archiviert. 5 | 6 | Das AddOn stellt den Video-/Audio-Player [Plyr](https://plyr.io) zur Verfügung. 7 | 8 | ![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/video/assets/mediapool.jpg) 9 | 10 | 11 | Es können lokale Audio-Dateien (mp3), Videos und Youtube- sowie Vimeo-Videos eingebunden werden. 12 | Wir haben uns bewusst gegen eine automatische Einbindung im Frontend entschieden um dem Entwickler alle Freiheiten zu lassen. 13 | 14 | ## AddOn Features 15 | - Statische PHP Methode zur Ausgabe des Videos 16 | - REX_PLYR[] Variable zur schnellen Ausgabe in einem Modul 17 | - Einbindung des Players im Backend 18 | - Plyr bindet sich in die Detailseite des Medienpools ein 19 | - Methoden zur Ermittlung des Videotyps 20 | - Methode zur Erstellung von Playlists 21 | - Controls können je Ausgabe definiert werden 22 | - JQuery wird für Playlists benötigt 23 | 24 | > Bei Medien aus dem Medienpool muss nur der Dateiname angegeben werden. Bei Youtube und Vimeo immer die vollständige URL. 25 | Diese Methode bietet sich an um evtl. mehrere Videos z.B. aus einer Datenbank oder Medialist zu verarbeiten. 26 | 27 | ## Ausgabe eines Mediums 28 | 29 | Die Ausgabe erfolgt über die Methode outputMedia(). 30 | 31 | Einzelmedium: 32 | 33 | ```php 34 | echo rex_plyr::outputMedia($fileOrUrl,$config,$poster); 35 | ``` 36 | 37 | oder über die REX_VALUE für Einzelmedien: 38 | 39 | `REX_PLYR[id=1 controls="play,progress"]` 40 | 41 | PlayLists werden wie folgt ausgegeben: 42 | 43 | `rex_plyr::outputMediaPlaylist($media_filenames,$setup)` 44 | 45 | 46 | 47 | ## Standard-Player 48 | 49 | ### Einbindung im Frontend 50 | 51 | Die nötigen Dateien findet man im Assets-Ordner. 52 | Eigene CSS und JS sollten nach Möglichkeit an anderer Stelle abgelegt werden um Probleme nach einem Update zu vermeiden. 53 | 54 | Plyr benötigt 2 JS-Dateien und eine CSS. In der `plyr_video.js` wird der Player initialisiert. 55 | 56 | #### CSS für Plyr 57 | 58 | ```html 59 | 60 | ``` 61 | 62 | #### JS für Plyr 63 | 64 | ```php 65 | 66 | 67 | ``` 68 | 69 | >Alle weiteren Infos zur Konfiguration der Skripte oder der Controls der Ausgaben, finden sich auf der GitHub-Site von [Plyr](https://plyr.io). 70 | 71 | 72 | ### Einfaches Modulbeispiel für lokale Videos mit Poster 73 | 74 | #### Eingabe 75 | 76 | ```php 77 |
    78 |
    79 | 80 |
    81 | REX_MEDIA[id=1 widget=1 types=mp4] 82 |
    83 |
    84 |
    85 | 86 |
    87 | REX_MEDIA[id=2 widget=1 types=jpg] 88 |
    89 |
    90 |
    91 | ``` 92 | 93 | ### Ausgabe 94 | 95 | ```php 96 | 104 | ``` 105 | 106 | 107 | 108 | ### Modul-Beispiel mit MFORM CustomLink für externe und lokale Videos 109 | 110 | Das CustomLink-Widget bietet sich an, weil die Redaktion damit lokale und externe Medien verlinken kann. 111 | 112 | #### Eingabe 113 | 114 | ```php 115 | // mform ab 7.0 116 | $mform = MForm::factory() 117 | ->addFieldsetArea('Video', MForm::factory() 118 | ->addCustomLinkField("1", array('label'=>'Medium', 'data-tel'=>'disable', 'data-mailto'=>'disable', 'data-formlink'=>'disable', 'data-intern'=>'disable')) 119 | ->addMediaField(1, array('label'=>'Image')) 120 | ); 121 | echo $mform->show(); 122 | ``` 123 | 124 | #### Ausgabe über `rex_plyr::outputMedia` 125 | 126 | ```php 127 | echo rex_plyr::outputMedia('REX_VALUE[1]','play-large,play,fullscreen,mute,volume,progress,airplay,pip,autoplay,loop,nopreload','/media/cover/REX_MEDIA[1]'); 128 | ``` 129 | > Beispiel mit allen Parametern, die nicht gewünschten Parameter bitte entfernen 130 | 131 | ## Playlist-Player 132 | 133 | ![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/video/assets/playlist.jpg) 134 | 135 | ### CSS für Playlist 136 | 137 | Falls nicht bereits schon eingebunden: 138 | 139 | ```html 140 | 141 | ``` 142 | und zusätzlich: 143 | ```html 144 | 145 | ``` 146 | 147 | ### JS für Playlists 148 | 149 | JS für Plyr Playlist lautet anders 150 | ```php 151 | 152 | 153 | ``` 154 | 155 | ### Modul-Eingabe Playlist 156 | 157 | ```php 158 | REX_MEDIALIST[id="1" type="mp3,mp4" widget="1"] 159 | ``` 160 | 161 | #### Modul-Ausgabe Playlist 162 | 163 | Die Ausgabe erfolgt über `rex_plyr::outputMediaPlaylist` 164 | 165 | Modul-Ausgabe 166 | 167 | ```php 168 | $media_filenames = preg_grep('/^\s*$/s', explode(",", REX_MEDIALIST[1]), PREG_GREP_INVERT); 169 | echo rex_plyr::outputMediaPlaylist($media_filenames,'play-large,play,progress,airplay,pip'); 170 | ``` 171 | 172 | ## Plyr und Consent-Abfragen für Youtube und Vimeo 173 | 174 | Das AddOn bietet Hilfs-Methoden zur Ausgabe von Consent-Meldungen an. 175 | 176 | ``` 177 | $video = rex_plyr::consent($url = '', $setup = null, $poster = null, $return_when_empty = '') 178 | ``` 179 | Prüft die Angegebene Url und gibt einen Consent Hinweis aus, wenn es sich um ein Vimeo- oder Youtube-Video handelt. 180 | Die Ausgabe erfolgt über das Fragment `consent.php`. Es können Parameter zur Konfiguration der Player mitgegeben werden. 181 | Wird für `$return_when_empty` als Wert `cke5` eingegeben wird bei nicht erfolgter Prüfung das originale oembed zurückgegeben. 182 | 183 | ``` 184 | $content = rex_plyr::oembed_replace(oembed_replace($string, $setup = null)) 185 | ``` 186 | Ersetzt sofern zutreffend, Youtube und Vimeo- OEMBED-Tags vom CKE5 durch Plyr-Code und setzt die Consentmeldungen. 187 | Es können Parameter zur Konfiguration der Player mitgegeben werden. 188 | 189 | ``` 190 | rex_plyr::cke_oembed_helper($setup = null); 191 | ``` 192 | Ruft einen Outputfilter auf der alle gefundenen CKE5-OEMBEDs in der Ausgabe ersetzt. 193 | 194 | Im Consent-Manager muss beim jeweiligen Cookie das passende Script eingesetzt werden. Die nachfolgenden functions sollten auch nach einem Ajax request ausgeführt werden. 195 | 196 | ### Vimeo Consent-Script 197 | 198 | ```js 199 | 224 | ``` 225 | 226 | ### Youtube Consent-Script 227 | 228 | ```js 229 | 252 | 253 | 254 | ``` 255 | 256 | ### CSS-Helferlein für Consent-Platzhalter 257 | 258 | Ermöglicht den Platzhalter im 16:9-Format darzustellen. 259 | 260 | ```css 261 | .aspect-ratio-16-9 { 262 | display: flow-root; 263 | position: relative; 264 | } 265 | 266 | .aspect-ratio-16-9::before { 267 | content: ''; 268 | float: left; 269 | padding-bottom: 56.25%; 270 | } 271 | ``` 272 | 273 | 274 | 275 | ## `REX_PLYR` 276 | 277 | REX_PLYR nimmt eine einfache REX_VAR an. 278 | z.B. `REX_VALUE[1]` aus der Moduleingabe wäre in der Ausgabe `REX_PLYR[1]` 279 | Es nimmt keine REX_MEDIA Daten an. Daher empfiehlt sich dafür als Eingabe Custom URL Widget aus mform. Damit kann man Medien und Urls einfach übergeben. 280 | 281 | Zur Ausgabe einzelner Medien steht auch eine REDAXO-Variable zur Verfügung. 282 | 283 | 284 | ```php 285 | REX_PLYR[1] 286 | ``` 287 | 288 | oder mit Konfiguration der Controls: 289 | 290 | ```php 291 | REX_PLYR[id=1 controls="play,progress"] 292 | ``` 293 | 294 | 295 | 296 | ## init.js Orientierungsänderung Beispiel: 297 | 298 | zur Änderung der Vollbildanzeige bei Orientierungsänderung des Geräts 299 | 300 | ```js 301 | document.addEventListener("DOMContentLoaded", function () { 302 | const players = Plyr.setup('.rex-plyr', { 303 | youtube: { 304 | noCookie: true 305 | }, 306 | iconUrl: '/assets/addons/plyr/vendor/plyr/dist/plyr.svg', 307 | fullscreen: { 308 | enabled: true, 309 | fallback: true, 310 | iosNative: false 311 | } 312 | }); 313 | }); 314 | 315 | const players = new Plyr('.rex-plyr'); 316 | players.on('play', event => { 317 | const instance = event.detail.plyr; 318 | 319 | screen.orientation.addEventListener("change", function () { 320 | if (screen.orientation.type = 'landscape-primary') { 321 | players.fullscreen.enter(); 322 | } 323 | if (screen.orientation.type = 'portrait-primary') { 324 | players.fullscreen.exit(); 325 | } 326 | }, false); 327 | 328 | window.addEventListener('orientationchange', function () { 329 | if (window.orientation & 2) { 330 | players.fullscreen.enter(); 331 | } else { 332 | players.fullscreen.exit(); 333 | } 334 | 335 | }); 336 | 337 | }); 338 | ``` 339 | 340 | ## youtube vimeo playlist 341 | 342 | Erlaubt das gemischte Abspielen von Youtube und Vimeo-Videos. 343 | 344 | Beipspiel für Bootstrap 4 345 | 346 | CSS 347 | 348 | ```html 349 | 350 | ``` 351 | und zusätzlich: 352 | ```html 353 | 354 | ``` 355 | 356 | 357 | JS 358 | ```php 359 | 360 | 361 | ``` 362 | 363 | 364 | 365 | 366 | - JQuery wird benötigt. 367 | 368 | 369 | ### Modul 370 | 371 | Eingabe 372 | 373 | ```php 374 | addFieldsetArea('Video-Liste', MForm::factory() 378 | ->addCustomLinkField("$id.0.1", ['label' => 'Link', 'data-media'=>'disable', 'data-mailto'=>'disable', 'data-intern'=>'disable','data-extern'=>'enable']) 379 | ->addTextField("$id.0.title", array('label'=>'titel')) 380 | ); 381 | echo MBlock::show($id, $mform->show(), array('min'=>1,'max'=>40)); 382 | ``` 383 | 384 | Ausgabe 385 | 386 | ```php 387 | 411 | 412 | 413 |
    414 |
    415 | 416 |
    417 |
    418 |
    419 |
    420 | 421 |
    422 |
    423 | 424 | 449 | ``` 450 | 451 | 452 | ## Methoden in der rex_plyr class 453 | 454 | `rex_plyr::outputMedia($url,$setup,$poster,$consent)` 455 | Erstellt einen Player annhand einer Mediendatei oder URL. 456 | 457 | `rex_plyr::outputMediaPlaylist($media_filenames,$setup)` 458 | Erstellt eine Playlist anhand des übergebenen Arrays 459 | 460 | `checkUrl($url)` 461 | Gibt sofern es sich um eine Mediapool-Datei handelt die URL zum Medium zurück. 462 | 463 | `checkYoutube($url)` 464 | Prüft ob es sich um eine Youtube-URL handelt 465 | 466 | `getYoutubeId($url)` 467 | Ermittelt die Youtube-ID eines Videos 468 | 469 | `checkVimeo($url)` 470 | Prüft ob es sich um eine Vimeo-URL handelt 471 | 472 | `getVimeoId($url)` 473 | Ermittelt die Vimeo-Id eines Videos 474 | 475 | `checkMedia($url)` 476 | Überprüft ob es sich um ein MP4-Video aus dem Medienpool handelt 477 | 478 | `checkExternalMp4($url)` 479 | Überprüft ob ein externes MP4-Video verlinkt ist. 480 | 481 | `checkVideo($url)` 482 | Überprüft ob es sich um eine Video-Datei / eine Video-Url handelt die plyr abspielen kann. 483 | 484 | `checkAudio($url)` 485 | Überprüft ob es sich um eine MP3-Audio-Datei aus dem Medienpool handelt 486 | 487 | ### Beispiel 488 | 489 | ```php 490 | $plyr = new rex_plyr(); 491 | $id = $plyr->checkMedia($url); 492 | ``` 493 | 494 | ## Tricks 495 | 496 | >Sobald ich ein Poster einblende und "nopreload" nicht(!) ausgewählt ist, wird in Safari kein Poster angezeigt. 497 | Lässt sich mit dem folgenden Fix beheben: 498 | 499 | ## Bugtracker 500 | 501 | Du hast einen Fehler gefunden oder ein nettes Feature parat? [Lege ein Issue an](https://github.com/FriendsOfREDAXO/video/issues). Bevor du ein neues Issue erstellst, suche bitte ob bereits eines mit deinem Anliegen existiert. 502 | 503 | ## Lizenz 504 | 505 | siehe [LICENSE.md](https://github.com/FriendsOfREDAXO/video/blob/master/LICENSE.md) 506 | 507 | Plyr steht unter MIT-Lizenz. Die Player bedienen sich jedoch teils unterschiedlicher Quellen, deren Lizenzen sich unterscheiden können. 508 | 509 | 510 | ## Autor 511 | 512 | **Friends Of REDAXO** 513 | 514 | * http://www.redaxo.org 515 | * https://github.com/FriendsOfREDAXO 516 | 517 | **Projekt-Lead** 518 | [Thomas Skerbis](https://github.com/skerbis) 519 | 520 | 521 | ## Credits: 522 | 523 | First Release: [Christian Gehrke](https://github.com/chrison94) 524 | PlayLists: [Tobias Krais](https://github.com/tobiaskrais) 525 | -------------------------------------------------------------------------------- /assets/vendor/plyr/dist/plyr.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";@keyframes plyr-progress{to{background-position:25px 0;background-position:var(--plyr-progress-loading-size,25px) 0}}@keyframes plyr-popup{0%{opacity:.5;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes plyr-fade-in{0%{opacity:0}to{opacity:1}}.plyr{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;align-items:center;direction:ltr;display:flex;flex-direction:column;font-family:inherit;font-family:var(--plyr-font-family,inherit);font-variant-numeric:tabular-nums;font-weight:400;font-weight:var(--plyr-font-weight-regular,400);line-height:1.7;line-height:var(--plyr-line-height,1.7);max-width:100%;min-width:200px;position:relative;text-shadow:none;transition:box-shadow .3s ease;z-index:0}.plyr audio,.plyr iframe,.plyr video{display:block;height:100%;width:100%}.plyr button{font:inherit;line-height:inherit;width:auto}.plyr:focus{outline:0}.plyr--full-ui{box-sizing:border-box}.plyr--full-ui *,.plyr--full-ui :after,.plyr--full-ui :before{box-sizing:inherit}.plyr--full-ui a,.plyr--full-ui button,.plyr--full-ui input,.plyr--full-ui label{touch-action:manipulation}.plyr__badge{background:#4a5464;background:var(--plyr-badge-background,#4a5464);border-radius:2px;border-radius:var(--plyr-badge-border-radius,2px);color:#fff;color:var(--plyr-badge-text-color,#fff);font-size:9px;font-size:var(--plyr-font-size-badge,9px);line-height:1;padding:3px 4px}.plyr--full-ui ::-webkit-media-text-track-container{display:none}.plyr__captions{animation:plyr-fade-in .3s ease;bottom:0;display:none;font-size:13px;font-size:var(--plyr-font-size-small,13px);left:0;padding:10px;padding:var(--plyr-control-spacing,10px);position:absolute;text-align:center;transition:transform .4s ease-in-out;width:100%}.plyr__captions span:empty{display:none}@media (min-width:480px){.plyr__captions{font-size:15px;font-size:var(--plyr-font-size-base,15px);padding:20px;padding:calc(var(--plyr-control-spacing, 10px)*2)}}@media (min-width:768px){.plyr__captions{font-size:18px;font-size:var(--plyr-font-size-large,18px)}}.plyr--captions-active .plyr__captions{display:block}.plyr:not(.plyr--hide-controls) .plyr__controls:not(:empty)~.plyr__captions{transform:translateY(-40px);transform:translateY(calc(var(--plyr-control-spacing, 10px)*-4))}.plyr__caption{background:#000c;background:var(--plyr-captions-background,#000c);border-radius:2px;-webkit-box-decoration-break:clone;box-decoration-break:clone;color:#fff;color:var(--plyr-captions-text-color,#fff);line-height:185%;padding:.2em .5em;white-space:pre-wrap}.plyr__caption div{display:inline}.plyr__control{background:#0000;border:0;border-radius:4px;border-radius:var(--plyr-control-radius,4px);color:inherit;cursor:pointer;flex-shrink:0;overflow:visible;padding:7px;padding:calc(var(--plyr-control-spacing, 10px)*.7);position:relative;transition:all .3s ease}.plyr__control svg{fill:currentColor;display:block;height:18px;height:var(--plyr-control-icon-size,18px);pointer-events:none;width:18px;width:var(--plyr-control-icon-size,18px)}.plyr__control:focus{outline:0}.plyr__control:focus-visible{outline:2px dashed #00b2ff;outline:2px dashed var(--plyr-focus-visible-color,var(--plyr-color-main,var(--plyr-color-main,#00b2ff)));outline-offset:2px}a.plyr__control{text-decoration:none}.plyr__control.plyr__control--pressed .icon--not-pressed,.plyr__control.plyr__control--pressed .label--not-pressed,.plyr__control:not(.plyr__control--pressed) .icon--pressed,.plyr__control:not(.plyr__control--pressed) .label--pressed,a.plyr__control:after,a.plyr__control:before{display:none}.plyr--full-ui ::-webkit-media-controls{display:none}.plyr__controls{align-items:center;display:flex;justify-content:flex-end;text-align:center}.plyr__controls .plyr__progress__container{flex:1;min-width:0}.plyr__controls .plyr__controls__item{margin-left:2.5px;margin-left:calc(var(--plyr-control-spacing, 10px)/4)}.plyr__controls .plyr__controls__item:first-child{margin-left:0;margin-right:auto}.plyr__controls .plyr__controls__item.plyr__progress__container{padding-left:2.5px;padding-left:calc(var(--plyr-control-spacing, 10px)/4)}.plyr__controls .plyr__controls__item.plyr__time{padding:0 5px;padding:0 calc(var(--plyr-control-spacing, 10px)/2)}.plyr__controls .plyr__controls__item.plyr__progress__container:first-child,.plyr__controls .plyr__controls__item.plyr__time+.plyr__time,.plyr__controls .plyr__controls__item.plyr__time:first-child{padding-left:0}.plyr [data-plyr=airplay],.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen],.plyr [data-plyr=pip],.plyr__controls:empty{display:none}.plyr--airplay-supported [data-plyr=airplay],.plyr--captions-enabled [data-plyr=captions],.plyr--fullscreen-enabled [data-plyr=fullscreen],.plyr--pip-supported [data-plyr=pip]{display:inline-block}.plyr__menu{display:flex;position:relative}.plyr__menu .plyr__control svg{transition:transform .3s ease}.plyr__menu .plyr__control[aria-expanded=true] svg{transform:rotate(90deg)}.plyr__menu .plyr__control[aria-expanded=true] .plyr__tooltip{display:none}.plyr__menu__container{animation:plyr-popup .2s ease;background:#ffffffe6;background:var(--plyr-menu-background,#ffffffe6);border-radius:8px;border-radius:var(--plyr-menu-radius,8px);bottom:100%;box-shadow:0 1px 2px #00000026;box-shadow:var(--plyr-menu-shadow,0 1px 2px #00000026);color:#4a5464;color:var(--plyr-menu-color,#4a5464);font-size:15px;font-size:var(--plyr-font-size-base,15px);margin-bottom:10px;position:absolute;right:-3px;text-align:left;white-space:nowrap;z-index:3}.plyr__menu__container>div{overflow:hidden;transition:height .35s cubic-bezier(.4,0,.2,1),width .35s cubic-bezier(.4,0,.2,1)}.plyr__menu__container:after{border:4px solid #0000;border-top-color:#ffffffe6;border:var(--plyr-menu-arrow-size,4px) solid #0000;border-top-color:var(--plyr-menu-background,#ffffffe6);content:"";height:0;position:absolute;right:14px;right:calc(var(--plyr-control-icon-size, 18px)/2 + var(--plyr-control-spacing, 10px)*.7 - var(--plyr-menu-arrow-size, 4px)/2);top:100%;width:0}.plyr__menu__container [role=menu]{padding:7px;padding:calc(var(--plyr-control-spacing, 10px)*.7)}.plyr__menu__container [role=menuitem],.plyr__menu__container [role=menuitemradio]{margin-top:2px}.plyr__menu__container [role=menuitem]:first-child,.plyr__menu__container [role=menuitemradio]:first-child{margin-top:0}.plyr__menu__container .plyr__control{align-items:center;color:#4a5464;color:var(--plyr-menu-color,#4a5464);display:flex;font-size:13px;font-size:var(--plyr-font-size-menu,var(--plyr-font-size-small,13px));padding:4.66667px 10.5px;padding:calc(var(--plyr-control-spacing, 10px)*.7/1.5) calc(var(--plyr-control-spacing, 10px)*.7*1.5);-webkit-user-select:none;user-select:none;width:100%}.plyr__menu__container .plyr__control>span{align-items:inherit;display:flex;width:100%}.plyr__menu__container .plyr__control:after{border:4px solid #0000;border:var(--plyr-menu-item-arrow-size,4px) solid #0000;content:"";position:absolute;top:50%;transform:translateY(-50%)}.plyr__menu__container .plyr__control--forward{padding-right:28px;padding-right:calc(var(--plyr-control-spacing, 10px)*.7*4)}.plyr__menu__container .plyr__control--forward:after{border-left-color:#728197;border-left-color:var(--plyr-menu-arrow-color,#728197);right:6.5px;right:calc(var(--plyr-control-spacing, 10px)*.7*1.5 - var(--plyr-menu-item-arrow-size, 4px))}.plyr__menu__container .plyr__control--forward:focus-visible:after,.plyr__menu__container .plyr__control--forward:hover:after{border-left-color:initial}.plyr__menu__container .plyr__control--back{font-weight:400;font-weight:var(--plyr-font-weight-regular,400);margin:7px;margin:calc(var(--plyr-control-spacing, 10px)*.7);margin-bottom:3.5px;margin-bottom:calc(var(--plyr-control-spacing, 10px)*.7/2);padding-left:28px;padding-left:calc(var(--plyr-control-spacing, 10px)*.7*4);position:relative;width:calc(100% - 14px);width:calc(100% - var(--plyr-control-spacing, 10px)*.7*2)}.plyr__menu__container .plyr__control--back:after{border-right-color:#728197;border-right-color:var(--plyr-menu-arrow-color,#728197);left:6.5px;left:calc(var(--plyr-control-spacing, 10px)*.7*1.5 - var(--plyr-menu-item-arrow-size, 4px))}.plyr__menu__container .plyr__control--back:before{background:#dcdfe5;background:var(--plyr-menu-back-border-color,#dcdfe5);box-shadow:0 1px 0 #fff;box-shadow:0 1px 0 var(--plyr-menu-back-border-shadow-color,#fff);content:"";height:1px;left:0;margin-top:3.5px;margin-top:calc(var(--plyr-control-spacing, 10px)*.7/2);overflow:hidden;position:absolute;right:0;top:100%}.plyr__menu__container .plyr__control--back:focus-visible:after,.plyr__menu__container .plyr__control--back:hover:after{border-right-color:initial}.plyr__menu__container .plyr__control[role=menuitemradio]{padding-left:7px;padding-left:calc(var(--plyr-control-spacing, 10px)*.7)}.plyr__menu__container .plyr__control[role=menuitemradio]:after,.plyr__menu__container .plyr__control[role=menuitemradio]:before{border-radius:100%}.plyr__menu__container .plyr__control[role=menuitemradio]:before{background:#0000001a;content:"";display:block;flex-shrink:0;height:16px;margin-right:10px;margin-right:var(--plyr-control-spacing,10px);transition:all .3s ease;width:16px}.plyr__menu__container .plyr__control[role=menuitemradio]:after{background:#fff;border:0;height:6px;left:12px;opacity:0;top:50%;transform:translateY(-50%) scale(0);transition:transform .3s ease,opacity .3s ease;width:6px}.plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]:before{background:#00b2ff;background:var(--plyr-control-toggle-checked-background,var(--plyr-color-main,var(--plyr-color-main,#00b2ff)))}.plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]:after{opacity:1;transform:translateY(-50%) scale(1)}.plyr__menu__container .plyr__control[role=menuitemradio]:focus-visible:before,.plyr__menu__container .plyr__control[role=menuitemradio]:hover:before{background:#23282f1a}.plyr__menu__container .plyr__menu__value{align-items:center;display:flex;margin-left:auto;margin-right:-5px;margin-right:calc(var(--plyr-control-spacing, 10px)*.7*-1 - -2px);overflow:hidden;padding-left:24.5px;padding-left:calc(var(--plyr-control-spacing, 10px)*.7*3.5);pointer-events:none}.plyr--full-ui input[type=range]{-webkit-appearance:none;appearance:none;background:#0000;border:0;border-radius:26px;border-radius:calc(var(--plyr-range-thumb-height, 13px)*2);color:#00b2ff;color:var(--plyr-range-fill-background,var(--plyr-color-main,var(--plyr-color-main,#00b2ff)));display:block;height:19px;height:calc(var(--plyr-range-thumb-active-shadow-width, 3px)*2 + var(--plyr-range-thumb-height, 13px));margin:0;min-width:0;padding:0;transition:box-shadow .3s ease;width:100%}.plyr--full-ui input[type=range]::-webkit-slider-runnable-track{background:#0000;background-image:linear-gradient(90deg,currentColor 0,#0000 0);background-image:linear-gradient(to right,currentColor var(--value,0),#0000 var(--value,0));border:0;border-radius:2.5px;border-radius:calc(var(--plyr-range-track-height, 5px)/2);height:5px;height:var(--plyr-range-track-height,5px);-webkit-transition:box-shadow .3s ease;transition:box-shadow .3s ease;-webkit-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background:#fff;background:var(--plyr-range-thumb-background,#fff);border:0;border-radius:100%;box-shadow:0 1px 1px #23282f26,0 0 0 1px #23282f33;box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px #23282f26,0 0 0 1px #23282f33);height:13px;height:var(--plyr-range-thumb-height,13px);margin-top:-4px;margin-top:calc((var(--plyr-range-thumb-height, 13px) - var(--plyr-range-track-height, 5px))/2*-1);position:relative;-webkit-transition:all .2s ease;transition:all .2s ease;width:13px;width:var(--plyr-range-thumb-height,13px)}.plyr--full-ui input[type=range]::-moz-range-track{background:#0000;border:0;border-radius:2.5px;border-radius:calc(var(--plyr-range-track-height, 5px)/2);height:5px;height:var(--plyr-range-track-height,5px);-moz-transition:box-shadow .3s ease;transition:box-shadow .3s ease;user-select:none}.plyr--full-ui input[type=range]::-moz-range-thumb{background:#fff;background:var(--plyr-range-thumb-background,#fff);border:0;border-radius:100%;box-shadow:0 1px 1px #23282f26,0 0 0 1px #23282f33;box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px #23282f26,0 0 0 1px #23282f33);height:13px;height:var(--plyr-range-thumb-height,13px);position:relative;-moz-transition:all .2s ease;transition:all .2s ease;width:13px;width:var(--plyr-range-thumb-height,13px)}.plyr--full-ui input[type=range]::-moz-range-progress{background:currentColor;border-radius:2.5px;border-radius:calc(var(--plyr-range-track-height, 5px)/2);height:5px;height:var(--plyr-range-track-height,5px)}.plyr--full-ui input[type=range]::-ms-track{color:#0000}.plyr--full-ui input[type=range]::-ms-fill-upper,.plyr--full-ui input[type=range]::-ms-track{background:#0000;border:0;border-radius:2.5px;border-radius:calc(var(--plyr-range-track-height, 5px)/2);height:5px;height:var(--plyr-range-track-height,5px);-ms-transition:box-shadow .3s ease;transition:box-shadow .3s ease;user-select:none}.plyr--full-ui input[type=range]::-ms-fill-lower{background:#0000;background:currentColor;border:0;border-radius:2.5px;border-radius:calc(var(--plyr-range-track-height, 5px)/2);height:5px;height:var(--plyr-range-track-height,5px);-ms-transition:box-shadow .3s ease;transition:box-shadow .3s ease;user-select:none}.plyr--full-ui input[type=range]::-ms-thumb{background:#fff;background:var(--plyr-range-thumb-background,#fff);border:0;border-radius:100%;box-shadow:0 1px 1px #23282f26,0 0 0 1px #23282f33;box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px #23282f26,0 0 0 1px #23282f33);height:13px;height:var(--plyr-range-thumb-height,13px);margin-top:0;position:relative;-ms-transition:all .2s ease;transition:all .2s ease;width:13px;width:var(--plyr-range-thumb-height,13px)}.plyr--full-ui input[type=range]::-ms-tooltip{display:none}.plyr--full-ui input[type=range]::-moz-focus-outer{border:0}.plyr--full-ui input[type=range]:focus{outline:0}.plyr--full-ui input[type=range]:focus-visible::-webkit-slider-runnable-track{outline:2px dashed #00b2ff;outline:2px dashed var(--plyr-focus-visible-color,var(--plyr-color-main,var(--plyr-color-main,#00b2ff)));outline-offset:2px}.plyr--full-ui input[type=range]:focus-visible::-moz-range-track{outline:2px dashed #00b2ff;outline:2px dashed var(--plyr-focus-visible-color,var(--plyr-color-main,var(--plyr-color-main,#00b2ff)));outline-offset:2px}.plyr--full-ui input[type=range]:focus-visible::-ms-track{outline:2px dashed #00b2ff;outline:2px dashed var(--plyr-focus-visible-color,var(--plyr-color-main,var(--plyr-color-main,#00b2ff)));outline-offset:2px}.plyr__poster{background-color:#000;background-color:var(--plyr-video-background,var(--plyr-video-background,#000));background-position:50% 50%;background-repeat:no-repeat;background-size:contain;height:100%;left:0;opacity:0;position:absolute;top:0;transition:opacity .2s ease;width:100%;z-index:1}.plyr--stopped.plyr__poster-enabled .plyr__poster{opacity:1}.plyr--youtube.plyr--paused.plyr__poster-enabled:not(.plyr--stopped) .plyr__poster{display:none}.plyr__time{font-size:13px;font-size:var(--plyr-font-size-time,var(--plyr-font-size-small,13px))}.plyr__time+.plyr__time:before{content:"⁄";margin-right:10px;margin-right:var(--plyr-control-spacing,10px)}@media (max-width:767px){.plyr__time+.plyr__time{display:none}}.plyr__tooltip{background:#fff;background:var(--plyr-tooltip-background,#fff);border-radius:5px;border-radius:var(--plyr-tooltip-radius,5px);bottom:100%;box-shadow:0 1px 2px #00000026;box-shadow:var(--plyr-tooltip-shadow,0 1px 2px #00000026);color:#4a5464;color:var(--plyr-tooltip-color,#4a5464);font-size:13px;font-size:var(--plyr-font-size-small,13px);font-weight:400;font-weight:var(--plyr-font-weight-regular,400);left:50%;line-height:1.3;margin-bottom:10px;margin-bottom:calc(var(--plyr-control-spacing, 10px)/2*2);opacity:0;padding:5px 7.5px;padding:calc(var(--plyr-control-spacing, 10px)/2) calc(var(--plyr-control-spacing, 10px)/2*1.5);pointer-events:none;position:absolute;transform:translate(-50%,10px) scale(.8);transform-origin:50% 100%;transition:transform .2s ease .1s,opacity .2s ease .1s;white-space:nowrap;z-index:2}.plyr__tooltip:before{border-left:4px solid #0000;border-left:var(--plyr-tooltip-arrow-size,4px) solid #0000;border-right:4px solid #0000;border-right:var(--plyr-tooltip-arrow-size,4px) solid #0000;border-top:4px solid #fff;border-top:var(--plyr-tooltip-arrow-size,4px) solid var(--plyr-tooltip-background,#fff);bottom:-4px;bottom:calc(var(--plyr-tooltip-arrow-size, 4px)*-1);content:"";height:0;left:50%;position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr .plyr__control:focus-visible .plyr__tooltip,.plyr .plyr__control:hover .plyr__tooltip,.plyr__tooltip--visible{opacity:1;transform:translate(-50%) scale(1)}.plyr .plyr__control:hover .plyr__tooltip{z-index:3}.plyr__controls>.plyr__control:first-child .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip{left:0;transform:translateY(10px) scale(.8);transform-origin:0 100%}.plyr__controls>.plyr__control:first-child .plyr__tooltip:before,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip:before{left:16px;left:calc(var(--plyr-control-icon-size, 18px)/2 + var(--plyr-control-spacing, 10px)*.7)}.plyr__controls>.plyr__control:last-child .plyr__tooltip{left:auto;right:0;transform:translateY(10px) scale(.8);transform-origin:100% 100%}.plyr__controls>.plyr__control:last-child .plyr__tooltip:before{left:auto;right:16px;right:calc(var(--plyr-control-icon-size, 18px)/2 + var(--plyr-control-spacing, 10px)*.7);transform:translateX(50%)}.plyr__controls>.plyr__control:first-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control:focus-visible .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control:hover .plyr__tooltip,.plyr__controls>.plyr__control:first-child:focus-visible .plyr__tooltip,.plyr__controls>.plyr__control:first-child:hover .plyr__tooltip,.plyr__controls>.plyr__control:last-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:last-child:focus-visible .plyr__tooltip,.plyr__controls>.plyr__control:last-child:hover .plyr__tooltip{transform:translate(0) scale(1)}.plyr__progress{left:6.5px;left:calc(var(--plyr-range-thumb-height, 13px)*.5);margin-right:13px;margin-right:var(--plyr-range-thumb-height,13px);position:relative}.plyr__progress input[type=range],.plyr__progress__buffer{margin-left:-6.5px;margin-left:calc(var(--plyr-range-thumb-height, 13px)*-.5);margin-right:-6.5px;margin-right:calc(var(--plyr-range-thumb-height, 13px)*-.5);width:calc(100% + 13px);width:calc(100% + var(--plyr-range-thumb-height, 13px))}.plyr__progress input[type=range]{position:relative;z-index:2}.plyr__progress .plyr__tooltip{left:0;max-width:120px;overflow-wrap:break-word}.plyr__progress__buffer{-webkit-appearance:none;background:#0000;border:0;border-radius:100px;height:5px;height:var(--plyr-range-track-height,5px);left:0;margin-top:-2.5px;margin-top:calc((var(--plyr-range-track-height, 5px)/2)*-1);padding:0;position:absolute;top:50%}.plyr__progress__buffer::-webkit-progress-bar{background:#0000}.plyr__progress__buffer::-webkit-progress-value{background:currentColor;border-radius:100px;min-width:5px;min-width:var(--plyr-range-track-height,5px);-webkit-transition:width .2s ease;transition:width .2s ease}.plyr__progress__buffer::-moz-progress-bar{background:currentColor;border-radius:100px;min-width:5px;min-width:var(--plyr-range-track-height,5px);-moz-transition:width .2s ease;transition:width .2s ease}.plyr__progress__buffer::-ms-fill{border-radius:100px;-ms-transition:width .2s ease;transition:width .2s ease}.plyr--loading .plyr__progress__buffer{animation:plyr-progress 1s linear infinite;background-image:linear-gradient(-45deg,#23282f99 25%,#0000 0,#0000 50%,#23282f99 0,#23282f99 75%,#0000 0,#0000);background-image:linear-gradient(-45deg,var(--plyr-progress-loading-background,#23282f99) 25%,#0000 25%,#0000 50%,var(--plyr-progress-loading-background,#23282f99) 50%,var(--plyr-progress-loading-background,#23282f99) 75%,#0000 75%,#0000);background-repeat:repeat-x;background-size:25px 25px;background-size:var(--plyr-progress-loading-size,25px) var(--plyr-progress-loading-size,25px);color:#0000}.plyr--video.plyr--loading .plyr__progress__buffer{background-color:#ffffff40;background-color:var(--plyr-video-progress-buffered-background,#ffffff40)}.plyr--audio.plyr--loading .plyr__progress__buffer{background-color:#c1c8d199;background-color:var(--plyr-audio-progress-buffered-background,#c1c8d199)}.plyr__progress__marker{background-color:#fff;background-color:var(--plyr-progress-marker-background,#fff);border-radius:1px;height:5px;height:var(--plyr-range-track-height,5px);position:absolute;top:50%;transform:translate(-50%,-50%);width:3px;width:var(--plyr-progress-marker-width,3px);z-index:3}.plyr__volume{align-items:center;display:flex;position:relative}.plyr__volume input[type=range]{margin-left:5px;margin-left:calc(var(--plyr-control-spacing, 10px)/2);margin-right:5px;margin-right:calc(var(--plyr-control-spacing, 10px)/2);max-width:90px;min-width:60px;position:relative;z-index:2}.plyr--audio{display:block}.plyr--audio .plyr__controls{background:#fff;background:var(--plyr-audio-controls-background,#fff);border-radius:inherit;color:#4a5464;color:var(--plyr-audio-control-color,#4a5464);padding:10px;padding:var(--plyr-control-spacing,10px)}.plyr--audio .plyr__control:focus-visible,.plyr--audio .plyr__control:hover,.plyr--audio .plyr__control[aria-expanded=true]{background:#00b2ff;background:var(--plyr-audio-control-background-hover,var(--plyr-color-main,var(--plyr-color-main,#00b2ff)));color:#fff;color:var(--plyr-audio-control-color-hover,#fff)}.plyr--full-ui.plyr--audio input[type=range]::-webkit-slider-runnable-track{background-color:#c1c8d199;background-color:var(--plyr-audio-range-track-background,var(--plyr-audio-progress-buffered-background,#c1c8d199))}.plyr--full-ui.plyr--audio input[type=range]::-moz-range-track{background-color:#c1c8d199;background-color:var(--plyr-audio-range-track-background,var(--plyr-audio-progress-buffered-background,#c1c8d199))}.plyr--full-ui.plyr--audio input[type=range]::-ms-track{background-color:#c1c8d199;background-color:var(--plyr-audio-range-track-background,var(--plyr-audio-progress-buffered-background,#c1c8d199))}.plyr--full-ui.plyr--audio input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px #23282f26,0 0 0 1px #23282f33,0 0 0 3px #23282f1a;box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px #23282f26,0 0 0 1px #23282f33),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,#23282f1a)}.plyr--full-ui.plyr--audio input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px #23282f26,0 0 0 1px #23282f33,0 0 0 3px #23282f1a;box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px #23282f26,0 0 0 1px #23282f33),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,#23282f1a)}.plyr--full-ui.plyr--audio input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px #23282f26,0 0 0 1px #23282f33,0 0 0 3px #23282f1a;box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px #23282f26,0 0 0 1px #23282f33),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,#23282f1a)}.plyr--audio .plyr__progress__buffer{color:#c1c8d199;color:var(--plyr-audio-progress-buffered-background,#c1c8d199)}.plyr--video{overflow:hidden}.plyr--video.plyr--menu-open{overflow:visible}.plyr__video-wrapper{background:#000;background:var(--plyr-video-background,var(--plyr-video-background,#000));border-radius:inherit;height:100%;margin:auto;overflow:hidden;position:relative;width:100%}.plyr__video-embed,.plyr__video-wrapper--fixed-ratio{aspect-ratio:16/9}@supports not (aspect-ratio:16/9){.plyr__video-embed,.plyr__video-wrapper--fixed-ratio{height:0;padding-bottom:56.25%;position:relative}}.plyr__video-embed iframe,.plyr__video-wrapper--fixed-ratio video{border:0;height:100%;left:0;position:absolute;top:0;width:100%}.plyr--full-ui .plyr__video-embed>.plyr__video-embed__container{padding-bottom:240%;position:relative;transform:translateY(-38.28125%)}.plyr--video .plyr__controls{background:linear-gradient(#0000,#000000bf);background:var(--plyr-video-controls-background,linear-gradient(#0000,#000000bf));border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;bottom:0;color:#fff;color:var(--plyr-video-control-color,#fff);left:0;padding:5px;padding:calc(var(--plyr-control-spacing, 10px)/2);padding-top:20px;padding-top:calc(var(--plyr-control-spacing, 10px)*2);position:absolute;right:0;transition:opacity .4s ease-in-out,transform .4s ease-in-out;z-index:3}@media (min-width:480px){.plyr--video .plyr__controls{padding:10px;padding:var(--plyr-control-spacing,10px);padding-top:35px;padding-top:calc(var(--plyr-control-spacing, 10px)*3.5)}}.plyr--video.plyr--hide-controls .plyr__controls{opacity:0;pointer-events:none;transform:translateY(100%)}.plyr--video .plyr__control:focus-visible,.plyr--video .plyr__control:hover,.plyr--video .plyr__control[aria-expanded=true]{background:#00b2ff;background:var(--plyr-video-control-background-hover,var(--plyr-color-main,var(--plyr-color-main,#00b2ff)));color:#fff;color:var(--plyr-video-control-color-hover,#fff)}.plyr__control--overlaid{background:#00b2ff;background:var(--plyr-video-control-background-hover,var(--plyr-color-main,var(--plyr-color-main,#00b2ff)));border:0;border-radius:100%;color:#fff;color:var(--plyr-video-control-color,#fff);display:none;left:50%;opacity:.9;padding:15px;padding:calc(var(--plyr-control-spacing, 10px)*1.5);position:absolute;top:50%;transform:translate(-50%,-50%);transition:.3s;z-index:2}.plyr__control--overlaid svg{left:2px;position:relative}.plyr__control--overlaid:focus,.plyr__control--overlaid:hover{opacity:1}.plyr--playing .plyr__control--overlaid{opacity:0;visibility:hidden}.plyr--full-ui.plyr--video .plyr__control--overlaid{display:block}.plyr--full-ui.plyr--video input[type=range]::-webkit-slider-runnable-track{background-color:#ffffff40;background-color:var(--plyr-video-range-track-background,var(--plyr-video-progress-buffered-background,#ffffff40))}.plyr--full-ui.plyr--video input[type=range]::-moz-range-track{background-color:#ffffff40;background-color:var(--plyr-video-range-track-background,var(--plyr-video-progress-buffered-background,#ffffff40))}.plyr--full-ui.plyr--video input[type=range]::-ms-track{background-color:#ffffff40;background-color:var(--plyr-video-range-track-background,var(--plyr-video-progress-buffered-background,#ffffff40))}.plyr--full-ui.plyr--video input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px #23282f26,0 0 0 1px #23282f33,0 0 0 3px #ffffff80;box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px #23282f26,0 0 0 1px #23282f33),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,#ffffff80)}.plyr--full-ui.plyr--video input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px #23282f26,0 0 0 1px #23282f33,0 0 0 3px #ffffff80;box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px #23282f26,0 0 0 1px #23282f33),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,#ffffff80)}.plyr--full-ui.plyr--video input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px #23282f26,0 0 0 1px #23282f33,0 0 0 3px #ffffff80;box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px #23282f26,0 0 0 1px #23282f33),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,#ffffff80)}.plyr--video .plyr__progress__buffer{color:#ffffff40;color:var(--plyr-video-progress-buffered-background,#ffffff40)}.plyr:fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:fullscreen video{height:100%}.plyr:fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:fullscreen .plyr__captions{font-size:21px;font-size:var(--plyr-font-size-xlarge,21px)}}.plyr--fullscreen-fallback{background:#000;border-radius:0!important;bottom:0;height:100%;left:0;margin:0;position:fixed;right:0;top:0;width:100%;z-index:10000000}.plyr--fullscreen-fallback video{height:100%}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen{display:block}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr--fullscreen-fallback.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr--fullscreen-fallback .plyr__captions{font-size:21px;font-size:var(--plyr-font-size-xlarge,21px)}}.plyr__ads{border-radius:inherit;bottom:0;cursor:pointer;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:-1}.plyr__ads>div,.plyr__ads>div iframe{height:100%;position:absolute;width:100%}.plyr__ads:after{background:#23282f;border-radius:2px;bottom:10px;bottom:var(--plyr-control-spacing,10px);color:#fff;content:attr(data-badge-text);font-size:11px;padding:2px 6px;pointer-events:none;position:absolute;right:10px;right:var(--plyr-control-spacing,10px);z-index:3}.plyr__ads:empty:after{display:none}.plyr__cues{background:currentColor;display:block;height:5px;height:var(--plyr-range-track-height,5px);left:0;opacity:.8;position:absolute;top:50%;transform:translateY(-50%);width:3px;z-index:3}.plyr__preview-thumb{background-color:#fff;background-color:var(--plyr-tooltip-background,#fff);border-radius:8px;border-radius:var(--plyr-menu-radius,8px);bottom:100%;box-shadow:0 1px 2px #00000026;box-shadow:var(--plyr-tooltip-shadow,0 1px 2px #00000026);margin-bottom:10px;margin-bottom:calc(var(--plyr-control-spacing, 10px)/2*2);opacity:0;padding:3px;pointer-events:none;position:absolute;transform:translateY(10px) scale(.8);transform-origin:50% 100%;transition:transform .2s ease .1s,opacity .2s ease .1s;z-index:2}.plyr__preview-thumb--is-shown{opacity:1;transform:translate(0) scale(1)}.plyr__preview-thumb:before{border-left:4px solid #0000;border-left:var(--plyr-tooltip-arrow-size,4px) solid #0000;border-right:4px solid #0000;border-right:var(--plyr-tooltip-arrow-size,4px) solid #0000;border-top:4px solid #fff;border-top:var(--plyr-tooltip-arrow-size,4px) solid var(--plyr-tooltip-background,#fff);bottom:-4px;bottom:calc(var(--plyr-tooltip-arrow-size, 4px)*-1);content:"";height:0;left:calc(50% + var(--preview-arrow-offset));position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr__preview-thumb__image-container{background:#c1c8d1;border-radius:7px;border-radius:calc(var(--plyr-menu-radius, 8px) - 1px);overflow:hidden;position:relative;z-index:0}.plyr__preview-thumb__image-container img,.plyr__preview-thumb__image-container:after{height:100%;left:0;position:absolute;top:0;width:100%}.plyr__preview-thumb__image-container:after{border-radius:inherit;box-shadow:inset 0 0 0 1px #00000026;content:"";pointer-events:none}.plyr__preview-thumb__image-container img{max-height:none;max-width:none}.plyr__preview-thumb__time-container{background:linear-gradient(#0000,#000000bf);background:var(--plyr-video-controls-background,linear-gradient(#0000,#000000bf));border-bottom-left-radius:7px;border-bottom-left-radius:calc(var(--plyr-menu-radius, 8px) - 1px);border-bottom-right-radius:7px;border-bottom-right-radius:calc(var(--plyr-menu-radius, 8px) - 1px);bottom:0;left:0;line-height:1.1;padding:20px 6px 6px;position:absolute;right:0;z-index:3}.plyr__preview-thumb__time-container span{color:#fff;font-size:13px;font-size:var(--plyr-font-size-time,var(--plyr-font-size-small,13px))}.plyr__preview-scrubbing{bottom:0;filter:blur(1px);height:100%;left:0;margin:auto;opacity:0;overflow:hidden;pointer-events:none;position:absolute;right:0;top:0;transition:opacity .3s ease;width:100%;z-index:1}.plyr__preview-scrubbing--is-shown{opacity:1}.plyr__preview-scrubbing img{height:100%;left:0;max-height:none;max-width:none;object-fit:contain;position:absolute;top:0;width:100%}.plyr--no-transition{transition:none!important}.plyr__sr-only{clip:rect(1px,1px,1px,1px);border:0!important;height:1px!important;overflow:hidden;padding:0!important;position:absolute!important;width:1px!important}.plyr [hidden]{display:none!important} -------------------------------------------------------------------------------- /assets/plyr_playlist.css: -------------------------------------------------------------------------------- 1 | @keyframes plyr-progress{to{background-position:25px 0;background-position:var(--plyr-progress-loading-size,25px) 0}}@keyframes plyr-popup{0%{opacity:.5;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes plyr-fade-in{from{opacity:0}to{opacity:1}}.plyr{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;align-items:center;direction:ltr;display:flex;flex-direction:column;font-family:inherit;font-family:var(--plyr-font-family,inherit);font-variant-numeric:tabular-nums;font-weight:400;font-weight:var(--plyr-font-weight-regular,400);height:100%;line-height:1.7;line-height:var(--plyr-line-height,1.7);max-width:100%;min-width:200px;position:relative;text-shadow:none;transition:box-shadow .3s ease;z-index:0}.plyr audio,.plyr iframe,.plyr video{display:block;height:100%;width:100%}.plyr button{font:inherit;line-height:inherit;width:auto}.plyr:focus{outline:0}.plyr--full-ui{box-sizing:border-box}.plyr--full-ui *,.plyr--full-ui ::after,.plyr--full-ui ::before{box-sizing:inherit}.plyr--full-ui a,.plyr--full-ui button,.plyr--full-ui input,.plyr--full-ui label{touch-action:manipulation}.plyr__badge{background:#4a5464;background:var(--plyr-badge-background,#4a5464);border-radius:2px;border-radius:var(--plyr-badge-border-radius,2px);color:#fff;color:var(--plyr-badge-text-color,#fff);font-size:9px;font-size:var(--plyr-font-size-badge,9px);line-height:1;padding:3px 4px}.plyr--full-ui ::-webkit-media-text-track-container{display:none}.plyr__captions{animation:plyr-fade-in .3s ease;bottom:0;display:none;font-size:13px;font-size:var(--plyr-font-size-small,13px);left:0;padding:10px;padding:var(--plyr-control-spacing,10px);position:absolute;text-align:center;transition:transform .4s ease-in-out;width:100%}.plyr__captions span:empty{display:none}@media (min-width:480px){.plyr__captions{font-size:15px;font-size:var(--plyr-font-size-base,15px);padding:calc(10px * 2);padding:calc(var(--plyr-control-spacing,10px) * 2)}}@media (min-width:768px){.plyr__captions{font-size:18px;font-size:var(--plyr-font-size-large,18px)}}.plyr--captions-active .plyr__captions{display:block}.plyr:not(.plyr--hide-controls) .plyr__controls:not(:empty)~.plyr__captions{transform:translateY(calc(10px * -4));transform:translateY(calc(var(--plyr-control-spacing,10px) * -4))}.plyr__caption{background:rgba(0,0,0,.8);background:var(--plyr-captions-background,rgba(0,0,0,.8));border-radius:2px;-webkit-box-decoration-break:clone;box-decoration-break:clone;color:#fff;color:var(--plyr-captions-text-color,#fff);line-height:185%;padding:.2em .5em;white-space:pre-wrap}.plyr__caption div{display:inline}.plyr__control{background:0 0;border:0;border-radius:3px;border-radius:var(--plyr-control-radius,3px);color:inherit;cursor:pointer;flex-shrink:0;overflow:visible;padding:calc(10px * .7);padding:calc(var(--plyr-control-spacing,10px) * .7);position:relative;transition:all .3s ease}.plyr__control svg{display:block;fill:currentColor;height:18px;height:var(--plyr-control-icon-size,18px);pointer-events:none;width:18px;width:var(--plyr-control-icon-size,18px)}.plyr__control:focus{outline:0}.plyr__control.plyr__tab-focus{outline-color:#00b3ff;outline-color:var(--plyr-tab-focus-color,var(--plyr-color-main,var(--plyr-color-main,#00b3ff)));outline-offset:2px;outline-style:dotted;outline-width:3px}a.plyr__control{text-decoration:none}a.plyr__control::after,a.plyr__control::before{display:none}.plyr__control.plyr__control--pressed .icon--not-pressed,.plyr__control.plyr__control--pressed .label--not-pressed,.plyr__control:not(.plyr__control--pressed) .icon--pressed,.plyr__control:not(.plyr__control--pressed) .label--pressed{display:none}.plyr--full-ui ::-webkit-media-controls{display:none}.plyr__controls{align-items:center;display:flex;justify-content:flex-end;text-align:center}.plyr__controls .plyr__progress__container{flex:1;min-width:0}.plyr__controls .plyr__controls__item{margin-left:calc(10px / 4);margin-left:calc(var(--plyr-control-spacing,10px)/ 4)}.plyr__controls .plyr__controls__item:first-child{margin-left:0;margin-right:auto}.plyr__controls .plyr__controls__item.plyr__progress__container{padding-left:calc(10px / 4);padding-left:calc(var(--plyr-control-spacing,10px)/ 4)}.plyr__controls .plyr__controls__item.plyr__time{padding:0 calc(10px / 2);padding:0 calc(var(--plyr-control-spacing,10px)/ 2)}.plyr__controls .plyr__controls__item.plyr__progress__container:first-child,.plyr__controls .plyr__controls__item.plyr__time+.plyr__time,.plyr__controls .plyr__controls__item.plyr__time:first-child{padding-left:0}.plyr__controls:empty{display:none}.plyr [data-plyr=airplay],.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen],.plyr [data-plyr=pip]{display:none}.plyr--airplay-supported [data-plyr=airplay],.plyr--captions-enabled [data-plyr=captions],.plyr--fullscreen-enabled [data-plyr=fullscreen],.plyr--pip-supported [data-plyr=pip]{display:inline-block}.plyr__menu{display:flex;position:relative}.plyr__menu .plyr__control svg{transition:transform .3s ease}.plyr__menu .plyr__control[aria-expanded=true] svg{transform:rotate(90deg)}.plyr__menu .plyr__control[aria-expanded=true] .plyr__tooltip{display:none}.plyr__menu__container{animation:plyr-popup .2s ease;background:rgba(255,255,255,.9);background:var(--plyr-menu-background,rgba(255,255,255,.9));border-radius:4px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);box-shadow:var(--plyr-menu-shadow,0 1px 2px rgba(0,0,0,.15));color:#4a5464;color:var(--plyr-menu-color,#4a5464);font-size:15px;font-size:var(--plyr-font-size-base,15px);margin-bottom:10px;position:absolute;right:-3px;text-align:left;white-space:nowrap;z-index:3}.plyr__menu__container>div{overflow:hidden;transition:height .35s cubic-bezier(.4,0,.2,1),width .35s cubic-bezier(.4,0,.2,1)}.plyr__menu__container::after{border:4px solid transparent;border:var(--plyr-menu-arrow-size,4px) solid transparent;border-top-color:rgba(255,255,255,.9);border-top-color:var(--plyr-menu-background,rgba(255,255,255,.9));content:'';height:0;position:absolute;right:calc(((18px / 2) + calc(10px * .7)) - (4px / 2));right:calc(((var(--plyr-control-icon-size,18px)/ 2) + calc(var(--plyr-control-spacing,10px) * .7)) - (var(--plyr-menu-arrow-size,4px)/ 2));top:100%;width:0}.plyr__menu__container [role=menu]{padding:calc(10px * .7);padding:calc(var(--plyr-control-spacing,10px) * .7)}.plyr__menu__container [role=menuitem],.plyr__menu__container [role=menuitemradio]{margin-top:2px}.plyr__menu__container [role=menuitem]:first-child,.plyr__menu__container [role=menuitemradio]:first-child{margin-top:0}.plyr__menu__container .plyr__control{align-items:center;color:#4a5464;color:var(--plyr-menu-color,#4a5464);display:flex;font-size:13px;font-size:var(--plyr-font-size-menu,var(--plyr-font-size-small,13px));padding-bottom:calc(calc(10px * .7)/ 1.5);padding-bottom:calc(calc(var(--plyr-control-spacing,10px) * .7)/ 1.5);padding-left:calc(calc(10px * .7) * 1.5);padding-left:calc(calc(var(--plyr-control-spacing,10px) * .7) * 1.5);padding-right:calc(calc(10px * .7) * 1.5);padding-right:calc(calc(var(--plyr-control-spacing,10px) * .7) * 1.5);padding-top:calc(calc(10px * .7)/ 1.5);padding-top:calc(calc(var(--plyr-control-spacing,10px) * .7)/ 1.5);-webkit-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr__menu__container .plyr__control>span{align-items:inherit;display:flex;width:100%}.plyr__menu__container .plyr__control::after{border:4px solid transparent;border:var(--plyr-menu-item-arrow-size,4px) solid transparent;content:'';position:absolute;top:50%;transform:translateY(-50%)}.plyr__menu__container .plyr__control--forward{padding-right:calc(calc(10px * .7) * 4);padding-right:calc(calc(var(--plyr-control-spacing,10px) * .7) * 4)}.plyr__menu__container .plyr__control--forward::after{border-left-color:#728197;border-left-color:var(--plyr-menu-arrow-color,#728197);right:calc((calc(10px * .7) * 1.5) - 4px);right:calc((calc(var(--plyr-control-spacing,10px) * .7) * 1.5) - var(--plyr-menu-item-arrow-size,4px))}.plyr__menu__container .plyr__control--forward.plyr__tab-focus::after,.plyr__menu__container .plyr__control--forward:hover::after{border-left-color:currentColor}.plyr__menu__container .plyr__control--back{font-weight:400;font-weight:var(--plyr-font-weight-regular,400);margin:calc(10px * .7);margin:calc(var(--plyr-control-spacing,10px) * .7);margin-bottom:calc(calc(10px * .7)/ 2);margin-bottom:calc(calc(var(--plyr-control-spacing,10px) * .7)/ 2);padding-left:calc(calc(10px * .7) * 4);padding-left:calc(calc(var(--plyr-control-spacing,10px) * .7) * 4);position:relative;width:calc(100% - (calc(10px * .7) * 2));width:calc(100% - (calc(var(--plyr-control-spacing,10px) * .7) * 2))}.plyr__menu__container .plyr__control--back::after{border-right-color:#728197;border-right-color:var(--plyr-menu-arrow-color,#728197);left:calc((calc(10px * .7) * 1.5) - 4px);left:calc((calc(var(--plyr-control-spacing,10px) * .7) * 1.5) - var(--plyr-menu-item-arrow-size,4px))}.plyr__menu__container .plyr__control--back::before{background:#dcdfe5;background:var(--plyr-menu-back-border-color,#dcdfe5);box-shadow:0 1px 0 #fff;box-shadow:0 1px 0 var(--plyr-menu-back-border-shadow-color,#fff);content:'';height:1px;left:0;margin-top:calc(calc(10px * .7)/ 2);margin-top:calc(calc(var(--plyr-control-spacing,10px) * .7)/ 2);overflow:hidden;position:absolute;right:0;top:100%}.plyr__menu__container .plyr__control--back.plyr__tab-focus::after,.plyr__menu__container .plyr__control--back:hover::after{border-right-color:currentColor}.plyr__menu__container .plyr__control[role=menuitemradio]{padding-left:calc(10px * .7);padding-left:calc(var(--plyr-control-spacing,10px) * .7)}.plyr__menu__container .plyr__control[role=menuitemradio]::after,.plyr__menu__container .plyr__control[role=menuitemradio]::before{border-radius:100%}.plyr__menu__container .plyr__control[role=menuitemradio]::before{background:rgba(0,0,0,.1);content:'';display:block;flex-shrink:0;height:16px;margin-right:10px;margin-right:var(--plyr-control-spacing,10px);transition:all .3s ease;width:16px}.plyr__menu__container .plyr__control[role=menuitemradio]::after{background:#fff;border:0;height:6px;left:12px;opacity:0;top:50%;transform:translateY(-50%) scale(0);transition:transform .3s ease,opacity .3s ease;width:6px}.plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]::before{background:#00b3ff;background:var(--plyr-control-toggle-checked-background,var(--plyr-color-main,var(--plyr-color-main,#00b3ff)))}.plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]::after{opacity:1;transform:translateY(-50%) scale(1)}.plyr__menu__container .plyr__control[role=menuitemradio].plyr__tab-focus::before,.plyr__menu__container .plyr__control[role=menuitemradio]:hover::before{background:rgba(35,40,47,.1)}.plyr__menu__container .plyr__menu__value{align-items:center;display:flex;margin-left:auto;margin-right:calc((calc(10px * .7) - 2) * -1);margin-right:calc((calc(var(--plyr-control-spacing,10px) * .7) - 2) * -1);overflow:hidden;padding-left:calc(calc(10px * .7) * 3.5);padding-left:calc(calc(var(--plyr-control-spacing,10px) * .7) * 3.5);pointer-events:none}.plyr--full-ui input[type=range]{-webkit-appearance:none;background:0 0;border:0;border-radius:calc(13px * 2);border-radius:calc(var(--plyr-range-thumb-height,13px) * 2);color:#00b3ff;color:var(--plyr-range-fill-background,var(--plyr-color-main,var(--plyr-color-main,#00b3ff)));display:block;height:calc((3px * 2) + 13px);height:calc((var(--plyr-range-thumb-active-shadow-width,3px) * 2) + var(--plyr-range-thumb-height,13px));margin:0;padding:0;transition:box-shadow .3s ease;width:55%}.plyr--full-ui input[type=range]::-webkit-slider-runnable-track{background:0 0;border:0;border-radius:calc(5px / 2);border-radius:calc(var(--plyr-range-track-height,5px)/ 2);height:5px;height:var(--plyr-range-track-height,5px);-webkit-transition:box-shadow .3s ease;transition:box-shadow .3s ease;-webkit-user-select:none;user-select:none;background-image:linear-gradient(to right,currentColor 0,transparent 0);background-image:linear-gradient(to right,currentColor var(--value,0),transparent var(--value,0))}.plyr--full-ui input[type=range]::-webkit-slider-thumb{background:#fff;background:var(--plyr-range-thumb-background,#fff);border:0;border-radius:100%;box-shadow:0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2);box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2));height:13px;height:var(--plyr-range-thumb-height,13px);position:relative;-webkit-transition:all .2s ease;transition:all .2s ease;width:13px;width:var(--plyr-range-thumb-height,13px);-webkit-appearance:none;margin-top:calc(((13px - 5px)/ 2) * -1);margin-top:calc(((var(--plyr-range-thumb-height,13px) - var(--plyr-range-track-height,5px))/ 2) * -1)}.plyr--full-ui input[type=range]::-moz-range-track{background:0 0;border:0;border-radius:calc(5px / 2);border-radius:calc(var(--plyr-range-track-height,5px)/ 2);height:5px;height:var(--plyr-range-track-height,5px);-moz-transition:box-shadow .3s ease;transition:box-shadow .3s ease;user-select:none}.plyr--full-ui input[type=range]::-moz-range-thumb{background:#fff;background:var(--plyr-range-thumb-background,#fff);border:0;border-radius:100%;box-shadow:0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2);box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2));height:13px;height:var(--plyr-range-thumb-height,13px);position:relative;-moz-transition:all .2s ease;transition:all .2s ease;width:13px;width:var(--plyr-range-thumb-height,13px)}.plyr--full-ui input[type=range]::-moz-range-progress{background:currentColor;border-radius:calc(5px / 2);border-radius:calc(var(--plyr-range-track-height,5px)/ 2);height:5px;height:var(--plyr-range-track-height,5px)}.plyr--full-ui input[type=range]::-ms-track{background:0 0;border:0;border-radius:calc(5px / 2);border-radius:calc(var(--plyr-range-track-height,5px)/ 2);height:5px;height:var(--plyr-range-track-height,5px);-ms-transition:box-shadow .3s ease;transition:box-shadow .3s ease;-ms-user-select:none;user-select:none;color:transparent}.plyr--full-ui input[type=range]::-ms-fill-upper{background:0 0;border:0;border-radius:calc(5px / 2);border-radius:calc(var(--plyr-range-track-height,5px)/ 2);height:5px;height:var(--plyr-range-track-height,5px);-ms-transition:box-shadow .3s ease;transition:box-shadow .3s ease;-ms-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-ms-fill-lower{background:0 0;border:0;border-radius:calc(5px / 2);border-radius:calc(var(--plyr-range-track-height,5px)/ 2);height:5px;height:var(--plyr-range-track-height,5px);-ms-transition:box-shadow .3s ease;transition:box-shadow .3s ease;-ms-user-select:none;user-select:none;background:currentColor}.plyr--full-ui input[type=range]::-ms-thumb{background:#fff;background:var(--plyr-range-thumb-background,#fff);border:0;border-radius:100%;box-shadow:0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2);box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2));height:13px;height:var(--plyr-range-thumb-height,13px);position:relative;-ms-transition:all .2s ease;transition:all .2s ease;width:13px;width:var(--plyr-range-thumb-height,13px);margin-top:0}.plyr--full-ui input[type=range]::-ms-tooltip{display:none}.plyr--full-ui input[type=range]:focus{outline:0}.plyr--full-ui input[type=range]::-moz-focus-outer{border:0}.plyr--full-ui input[type=range].plyr__tab-focus::-webkit-slider-runnable-track{outline-color:#00b3ff;outline-color:var(--plyr-tab-focus-color,var(--plyr-color-main,var(--plyr-color-main,#00b3ff)));outline-offset:2px;outline-style:dotted;outline-width:3px}.plyr--full-ui input[type=range].plyr__tab-focus::-moz-range-track{outline-color:#00b3ff;outline-color:var(--plyr-tab-focus-color,var(--plyr-color-main,var(--plyr-color-main,#00b3ff)));outline-offset:2px;outline-style:dotted;outline-width:3px}.plyr--full-ui input[type=range].plyr__tab-focus::-ms-track{outline-color:#00b3ff;outline-color:var(--plyr-tab-focus-color,var(--plyr-color-main,var(--plyr-color-main,#00b3ff)));outline-offset:2px;outline-style:dotted;outline-width:3px}.plyr__poster{background-color:#000;background-position:50% 50%;background-repeat:no-repeat;background-size:contain;height:100%;left:0;opacity:0;position:absolute;top:0;transition:opacity .2s ease;width:100%;z-index:1}.plyr--stopped.plyr__poster-enabled .plyr__poster{opacity:1}.plyr__time{font-size:13px;font-size:var(--plyr-font-size-time,var(--plyr-font-size-small,13px))}.plyr__time+.plyr__time::before{content:'\2044';margin-right:10px;margin-right:var(--plyr-control-spacing,10px)}@media (max-width:calc(768px - 1)){.plyr__time+.plyr__time{display:none}}.plyr__tooltip{background:rgba(255,255,255,.9);background:var(--plyr-tooltip-background,rgba(255,255,255,.9));border-radius:3px;border-radius:var(--plyr-tooltip-radius,3px);bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);box-shadow:var(--plyr-tooltip-shadow,0 1px 2px rgba(0,0,0,.15));color:#4a5464;color:var(--plyr-tooltip-color,#4a5464);font-size:13px;font-size:var(--plyr-font-size-small,13px);font-weight:400;font-weight:var(--plyr-font-weight-regular,400);left:50%;line-height:1.3;margin-bottom:calc(calc(10px / 2) * 2);margin-bottom:calc(calc(var(--plyr-control-spacing,10px)/ 2) * 2);opacity:0;padding:calc(10px / 2) calc(calc(10px / 2) * 1.5);padding:calc(var(--plyr-control-spacing,10px)/ 2) calc(calc(var(--plyr-control-spacing,10px)/ 2) * 1.5);pointer-events:none;position:absolute;transform:translate(-50%,10px) scale(.8);transform-origin:50% 100%;transition:transform .2s .1s ease,opacity .2s .1s ease;white-space:nowrap;z-index:2}.plyr__tooltip::before{border-left:4px solid transparent;border-left:var(--plyr-tooltip-arrow-size,4px) solid transparent;border-right:4px solid transparent;border-right:var(--plyr-tooltip-arrow-size,4px) solid transparent;border-top:4px solid rgba(255,255,255,.9);border-top:var(--plyr-tooltip-arrow-size,4px) solid var(--plyr-tooltip-background,rgba(255,255,255,.9));bottom:calc(4px * -1);bottom:calc(var(--plyr-tooltip-arrow-size,4px) * -1);content:'';height:0;left:50%;position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr .plyr__control.plyr__tab-focus .plyr__tooltip,.plyr .plyr__control:hover .plyr__tooltip,.plyr__tooltip--visible{opacity:1;transform:translate(-50%,0) scale(1)}.plyr .plyr__control:hover .plyr__tooltip{z-index:3}.plyr__controls>.plyr__control:first-child .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip{left:0;transform:translate(0,10px) scale(.8);transform-origin:0 100%}.plyr__controls>.plyr__control:first-child .plyr__tooltip::before,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip::before{left:calc((18px / 2) + calc(10px * .7));left:calc((var(--plyr-control-icon-size,18px)/ 2) + calc(var(--plyr-control-spacing,10px) * .7))}.plyr__controls>.plyr__control:last-child .plyr__tooltip{left:auto;right:0;transform:translate(0,10px) scale(.8);transform-origin:100% 100%}.plyr__controls>.plyr__control:last-child .plyr__tooltip::before{left:auto;right:calc((18px / 2) + calc(10px * .7));right:calc((var(--plyr-control-icon-size,18px)/ 2) + calc(var(--plyr-control-spacing,10px) * .7));transform:translateX(50%)}.plyr__controls>.plyr__control:first-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control:hover .plyr__tooltip,.plyr__controls>.plyr__control:first-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child:hover .plyr__tooltip,.plyr__controls>.plyr__control:last-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:last-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:last-child:hover .plyr__tooltip{transform:translate(0,0) scale(1)}.plyr__progress{left:calc(13px * .5);left:calc(var(--plyr-range-thumb-height,13px) * .5);margin-right:13px;margin-right:var(--plyr-range-thumb-height,13px);position:relative}.plyr__progress input[type=range],.plyr__progress__buffer{margin-left:calc(13px * -.5);margin-left:calc(var(--plyr-range-thumb-height,13px) * -.5);margin-right:calc(13px * -.5);margin-right:calc(var(--plyr-range-thumb-height,13px) * -.5);width:calc(100% + 13px);width:calc(100% + var(--plyr-range-thumb-height,13px))}.plyr__progress input[type=range]{position:relative;z-index:2}.plyr__progress .plyr__tooltip{font-size:13px;font-size:var(--plyr-font-size-time,var(--plyr-font-size-small,13px));left:0}.plyr__progress__buffer{-webkit-appearance:none;background:0 0;border:0;border-radius:100px;height:5px;height:var(--plyr-range-track-height,5px);left:0;margin-top:calc((5px / 2) * -1);margin-top:calc((var(--plyr-range-track-height,5px)/ 2) * -1);padding:0;position:absolute;top:50%}.plyr__progress__buffer::-webkit-progress-bar{background:0 0}.plyr__progress__buffer::-webkit-progress-value{background:currentColor;border-radius:100px;min-width:5px;min-width:var(--plyr-range-track-height,5px);-webkit-transition:width .2s ease;transition:width .2s ease}.plyr__progress__buffer::-moz-progress-bar{background:currentColor;border-radius:100px;min-width:5px;min-width:var(--plyr-range-track-height,5px);-moz-transition:width .2s ease;transition:width .2s ease}.plyr__progress__buffer::-ms-fill{border-radius:100px;-ms-transition:width .2s ease;transition:width .2s ease}.plyr--loading .plyr__progress__buffer{animation:plyr-progress 1s linear infinite;background-image:linear-gradient(-45deg,rgba(35,40,47,.6) 25%,transparent 25%,transparent 50%,rgba(35,40,47,.6) 50%,rgba(35,40,47,.6) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,var(--plyr-progress-loading-background,rgba(35,40,47,.6)) 25%,transparent 25%,transparent 50%,var(--plyr-progress-loading-background,rgba(35,40,47,.6)) 50%,var(--plyr-progress-loading-background,rgba(35,40,47,.6)) 75%,transparent 75%,transparent);background-repeat:repeat-x;background-size:25px 25px;background-size:var(--plyr-progress-loading-size,25px) var(--plyr-progress-loading-size,25px);color:transparent}.plyr--video.plyr--loading .plyr__progress__buffer{background-color:rgba(255,255,255,.25);background-color:var(--plyr-video-progress-buffered-background,rgba(255,255,255,.25))}.plyr--audio.plyr--loading .plyr__progress__buffer{background-color:rgba(193,200,209,.6);background-color:var(--plyr-audio-progress-buffered-background,rgba(193,200,209,.6))}.plyr__volume{align-items:center;display:flex;max-width:110px;min-width:80px;position:relative;width:20%}.plyr__volume input[type=range]{margin-left:calc(10px / 2);margin-left:calc(var(--plyr-control-spacing,10px)/ 2);margin-right:calc(10px / 2);margin-right:calc(var(--plyr-control-spacing,10px)/ 2);position:relative;z-index:2}.plyr--is-ios .plyr__volume{min-width:0;width:auto}.plyr--audio{display:block}.plyr--audio .plyr__controls{background:#fff;background:var(--plyr-audio-controls-background,#fff);border-radius:inherit;color:#4a5464;color:var(--plyr-audio-control-color,#4a5464);padding:10px;padding:var(--plyr-control-spacing,10px)}.plyr--audio .plyr__control.plyr__tab-focus,.plyr--audio .plyr__control:hover,.plyr--audio .plyr__control[aria-expanded=true]{background:#00b3ff;background:var(--plyr-audio-control-background-hover,var(--plyr-color-main,var(--plyr-color-main,#00b3ff)));color:#fff;color:var(--plyr-audio-control-color-hover,#fff)}.plyr--full-ui.plyr--audio input[type=range]::-webkit-slider-runnable-track{background-color:rgba(193,200,209,.6);background-color:var(--plyr-audio-range-track-background,var(--plyr-audio-progress-buffered-background,rgba(193,200,209,.6)))}.plyr--full-ui.plyr--audio input[type=range]::-moz-range-track{background-color:rgba(193,200,209,.6);background-color:var(--plyr-audio-range-track-background,var(--plyr-audio-progress-buffered-background,rgba(193,200,209,.6)))}.plyr--full-ui.plyr--audio input[type=range]::-ms-track{background-color:rgba(193,200,209,.6);background-color:var(--plyr-audio-range-track-background,var(--plyr-audio-progress-buffered-background,rgba(193,200,209,.6)))}.plyr--full-ui.plyr--audio input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2),0 0 0 3px rgba(35,40,47,.1);box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2)),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,rgba(35,40,47,.1))}.plyr--full-ui.plyr--audio input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2),0 0 0 3px rgba(35,40,47,.1);box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2)),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,rgba(35,40,47,.1))}.plyr--full-ui.plyr--audio input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2),0 0 0 3px rgba(35,40,47,.1);box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2)),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,rgba(35,40,47,.1))}.plyr--audio .plyr__progress__buffer{color:rgba(193,200,209,.6);color:var(--plyr-audio-progress-buffered-background,rgba(193,200,209,.6))}.plyr--video{background:#000;overflow:hidden}.plyr--video.plyr--menu-open{overflow:visible}.plyr__video-wrapper{background:#000;height:100%;margin:auto;overflow:hidden;position:relative;width:100%}.plyr__video-embed,.plyr__video-wrapper--fixed-ratio{height:0;padding-bottom:56.25%}.plyr__video-embed iframe,.plyr__video-wrapper--fixed-ratio video{border:0;left:0;position:absolute;top:0}.plyr--full-ui .plyr__video-embed>.plyr__video-embed__container{padding-bottom:240%;position:relative;transform:translateY(-38.28125%)}.plyr--video .plyr__controls{background:linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.75));background:var(--plyr-video-controls-background,linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.75)));border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;bottom:0;color:#fff;color:var(--plyr-video-control-color,#fff);left:0;padding:calc(10px / 2);padding:calc(var(--plyr-control-spacing,10px)/ 2);padding-top:calc(10px * 2);padding-top:calc(var(--plyr-control-spacing,10px) * 2);position:absolute;right:0;transition:opacity .4s ease-in-out,transform .4s ease-in-out;z-index:3}@media (min-width:480px){.plyr--video .plyr__controls{padding:10px;padding:var(--plyr-control-spacing,10px);padding-top:calc(10px * 3.5);padding-top:calc(var(--plyr-control-spacing,10px) * 3.5)}}.plyr--video.plyr--hide-controls .plyr__controls{opacity:0;pointer-events:none;transform:translateY(100%)}.plyr--video .plyr__control.plyr__tab-focus,.plyr--video .plyr__control:hover,.plyr--video .plyr__control[aria-expanded=true]{background:#00b3ff;background:var(--plyr-video-control-background-hover,var(--plyr-color-main,var(--plyr-color-main,#00b3ff)));color:#fff;color:var(--plyr-video-control-color-hover,#fff)}.plyr__control--overlaid{background:#00b3ff;background:var(--plyr-video-control-background-hover,var(--plyr-color-main,var(--plyr-color-main,#00b3ff)));border:0;border-radius:100%;color:#fff;color:var(--plyr-video-control-color,#fff);display:none;left:50%;opacity:.9;padding:calc(10px * 1.5);padding:calc(var(--plyr-control-spacing,10px) * 1.5);position:absolute;top:50%;transform:translate(-50%,-50%);transition:.3s;z-index:2}.plyr__control--overlaid svg{left:2px;position:relative}.plyr__control--overlaid:focus,.plyr__control--overlaid:hover{opacity:1}.plyr--playing .plyr__control--overlaid{opacity:0;visibility:hidden}.plyr--full-ui.plyr--video .plyr__control--overlaid{display:block}.plyr--full-ui.plyr--video input[type=range]::-webkit-slider-runnable-track{background-color:rgba(255,255,255,.25);background-color:var(--plyr-video-range-track-background,var(--plyr-video-progress-buffered-background,rgba(255,255,255,.25)))}.plyr--full-ui.plyr--video input[type=range]::-moz-range-track{background-color:rgba(255,255,255,.25);background-color:var(--plyr-video-range-track-background,var(--plyr-video-progress-buffered-background,rgba(255,255,255,.25)))}.plyr--full-ui.plyr--video input[type=range]::-ms-track{background-color:rgba(255,255,255,.25);background-color:var(--plyr-video-range-track-background,var(--plyr-video-progress-buffered-background,rgba(255,255,255,.25)))}.plyr--full-ui.plyr--video input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2),0 0 0 3px rgba(255,255,255,.5);box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2)),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,rgba(255,255,255,.5))}.plyr--full-ui.plyr--video input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2),0 0 0 3px rgba(255,255,255,.5);box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2)),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,rgba(255,255,255,.5))}.plyr--full-ui.plyr--video input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2),0 0 0 3px rgba(255,255,255,.5);box-shadow:var(--plyr-range-thumb-shadow,0 1px 1px rgba(35,40,47,.15),0 0 0 1px rgba(35,40,47,.2)),0 0 0 var(--plyr-range-thumb-active-shadow-width,3px) var(--plyr-audio-range-thumb-active-shadow-color,rgba(255,255,255,.5))}.plyr--video .plyr__progress__buffer{color:rgba(255,255,255,.25);color:var(--plyr-video-progress-buffered-background,rgba(255,255,255,.25))}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:fullscreen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;position:static}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;position:static}.plyr:fullscreen .plyr__video-wrapper{height:100%;position:static}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;position:relative}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;position:relative}.plyr:fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;position:relative}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}.plyr:fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px;font-size:var(--plyr-font-size-xlarge,21px)}.plyr:-ms-fullscreen .plyr__captions{font-size:21px;font-size:var(--plyr-font-size-xlarge,21px)}.plyr:fullscreen .plyr__captions{font-size:21px;font-size:var(--plyr-font-size-xlarge,21px)}}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;position:static}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;position:relative}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px;font-size:var(--plyr-font-size-xlarge,21px)}}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;position:static}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;position:relative}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-moz-full-screen .plyr__captions{font-size:21px;font-size:var(--plyr-font-size-xlarge,21px)}}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;position:static}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;position:relative}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-ms-fullscreen .plyr__captions{font-size:21px;font-size:var(--plyr-font-size-xlarge,21px)}}.plyr--fullscreen-fallback{background:#000;border-radius:0!important;height:100%;margin:0;width:100%;bottom:0;display:block;left:0;position:fixed;right:0;top:0;z-index:10000000}.plyr--fullscreen-fallback video{height:100%}.plyr--fullscreen-fallback .plyr__video-wrapper{height:100%;position:static}.plyr--fullscreen-fallback.plyr--vimeo .plyr__video-wrapper{height:0;position:relative}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen{display:block}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr--fullscreen-fallback.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr--fullscreen-fallback .plyr__captions{font-size:21px;font-size:var(--plyr-font-size-xlarge,21px)}}.plyr__ads{border-radius:inherit;bottom:0;cursor:pointer;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:-1}.plyr__ads>div,.plyr__ads>div iframe{height:100%;position:absolute;width:100%}.plyr__ads::after{background:#23282f;border-radius:2px;bottom:10px;bottom:var(--plyr-control-spacing,10px);color:#fff;content:attr(data-badge-text);font-size:11px;padding:2px 6px;pointer-events:none;position:absolute;right:10px;right:var(--plyr-control-spacing,10px);z-index:3}.plyr__ads::after:empty{display:none}.plyr__cues{background:currentColor;display:block;height:5px;height:var(--plyr-range-track-height,5px);left:0;margin:-var(--plyr-range-track-height,5px)/2 0 0;opacity:.8;position:absolute;top:50%;width:3px;z-index:3}.plyr__preview-thumb{background-color:rgba(255,255,255,.9);background-color:var(--plyr-tooltip-background,rgba(255,255,255,.9));border-radius:3px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);box-shadow:var(--plyr-tooltip-shadow,0 1px 2px rgba(0,0,0,.15));margin-bottom:calc(calc(10px / 2) * 2);margin-bottom:calc(calc(var(--plyr-control-spacing,10px)/ 2) * 2);opacity:0;padding:3px;padding:var(--plyr-tooltip-radius,3px);pointer-events:none;position:absolute;transform:translate(0,10px) scale(.8);transform-origin:50% 100%;transition:transform .2s .1s ease,opacity .2s .1s ease;z-index:2}.plyr__preview-thumb--is-shown{opacity:1;transform:translate(0,0) scale(1)}.plyr__preview-thumb::before{border-left:4px solid transparent;border-left:var(--plyr-tooltip-arrow-size,4px) solid transparent;border-right:4px solid transparent;border-right:var(--plyr-tooltip-arrow-size,4px) solid transparent;border-top:4px solid rgba(255,255,255,.9);border-top:var(--plyr-tooltip-arrow-size,4px) solid var(--plyr-tooltip-background,rgba(255,255,255,.9));bottom:calc(4px * -1);bottom:calc(var(--plyr-tooltip-arrow-size,4px) * -1);content:'';height:0;left:50%;position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr__preview-thumb__image-container{background:#c1c8d1;border-radius:calc(3px - 1px);border-radius:calc(var(--plyr-tooltip-radius,3px) - 1px);overflow:hidden;position:relative;z-index:0}.plyr__preview-thumb__image-container img{height:100%;left:0;max-height:none;max-width:none;position:absolute;top:0;width:100%}.plyr__preview-thumb__time-container{bottom:6px;left:0;position:absolute;right:0;white-space:nowrap;z-index:3}.plyr__preview-thumb__time-container span{background-color:rgba(0,0,0,.55);border-radius:calc(3px - 1px);border-radius:calc(var(--plyr-tooltip-radius,3px) - 1px);color:#fff;font-size:13px;font-size:var(--plyr-font-size-time,var(--plyr-font-size-small,13px));padding:3px 6px}.plyr__preview-scrubbing{bottom:0;filter:blur(1px);height:100%;left:0;margin:auto;opacity:0;overflow:hidden;pointer-events:none;position:absolute;right:0;top:0;transition:opacity .3s ease;width:100%;z-index:1}.plyr__preview-scrubbing--is-shown{opacity:1}.plyr__preview-scrubbing img{height:100%;left:0;max-height:none;max-width:none;object-fit:contain;position:absolute;top:0;width:100%}.plyr--no-transition{transition:none!important}.plyr__sr-only{clip:rect(1px,1px,1px,1px);overflow:hidden;border:0!important;height:1px!important;padding:0!important;position:absolute!important;width:1px!important}.plyr [hidden]{display:none!important} 2 | 3 | /* Playlist */ 4 | /* scrollbar rules have to be separate, browsers not supporting this syntax will skip them when combined. */ 5 | .plyr-playlist-wrapper ul::-webkit-scrollbar { 6 | width: 6px; 7 | } 8 | 9 | .plyr-playlist-wrapper ul::-webkit-scrollbar-track { 10 | background: rgba(0, 0, 0, 0.3); 11 | border-radius: 10px; 12 | -moz-border-radius: 10px; 13 | -webkit-border-radius: 10px; 14 | } 15 | 16 | .plyr-playlist-wrapper ul::-webkit-scrollbar-thumb { 17 | border-radius: 10px; 18 | -moz-border-radius: 10px; 19 | -webkit-border-radius: 10px; 20 | /* background: #fff; */ 21 | background: #3498db; 22 | } 23 | .plyr-playlist-wrapper { 24 | background: rgba(0, 0, 0, 0.8); 25 | position: relative; 26 | padding: 0.5em 0.5em 0.5em 0.25em; 27 | } 28 | .plyr-playlist-wrapper .plyr-playlist { 29 | user-select: none; 30 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 31 | /* position: absolute; 32 | right: 65px; 33 | bottom: 100%; */ 34 | position: relative; 35 | margin-top: 0; 36 | padding: 6px 4px; 37 | width: 100%; 38 | box-sizing: border-box; 39 | -moz-box-shadow: rgba(0, 0, 0, 0.2) 0px 6px 8px 0px inset; 40 | -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0px 6px 8px 0px inset; 41 | box-shadow: rgba(0, 0, 0, 0.2) 0px 6px 8px 0px inset; 42 | } 43 | 44 | .plyr-playlist-wrapper ul { 45 | padding: 0; 46 | margin: 0; 47 | max-height: 12em; 48 | overflow-y: scroll; 49 | -webkit-overflow-scrolling: touch; 50 | } 51 | 52 | .plyr-playlist-wrapper ul li { 53 | border-bottom: 1px solid rgba(0, 0, 0, 0.05); 54 | } 55 | 56 | .plyr-playlist-wrapper .plyr-playlist li { 57 | list-style: none; 58 | background-color: rgba(255, 255, 255, 0.03); 59 | padding: 0px; 60 | margin-bottom: 3px; 61 | font-size: 90%; 62 | } 63 | 64 | .plyr-playlist-wrapper .plyr-playlist li.pls-playing, 65 | .plyr-playlist-wrapper .plyr-playlist li:hover { 66 | color: #3498db; 67 | background-color: rgba(255, 255, 255, 0.09); 68 | } 69 | .plyr-playlist-wrapper .plyr-playlist li.pls-playing a { 70 | color: #3498db; 71 | } 72 | 73 | /* .plyr-playlist li:hover { 74 | background-color: rgba(255, 255, 255, 0.09); 75 | } */ 76 | 77 | .plyr-playlist-wrapper .plyr-playlist li a { 78 | text-decoration: none; 79 | font-family: arial; 80 | color: #c9c9c9; 81 | display: block; 82 | padding: 10px 0; 83 | outline: none; 84 | padding: 0.5em 0.25em 0.5em 0.75em; 85 | /*margin-right: 0.5em;*/ 86 | font-size: 90%; 87 | vertical-align: middle; 88 | padding-bottom: 10px; 89 | } 90 | 91 | .plyr-playlist-wrapper .plyr-playlist li:last-child a { 92 | border-bottom: 0; 93 | } 94 | 95 | .plyr-playlist li a:hover, 96 | .plyr-playlist li a:focus, 97 | .plyr-playlist li a:active { 98 | color: #04a9f3; 99 | /* color: #00c85f;*/ 100 | /* text-decoration: none; */ 101 | } 102 | 103 | .plyr-miniposter { 104 | width: auto; 105 | height: 22px; 106 | -webkit-background-size: cover; 107 | background-size: cover; 108 | background-repeat: no-repeat; 109 | background-position: center center; 110 | float: left; 111 | margin-right: 10px; 112 | border-radius: 0; 113 | -moz-border-radius: 0; 114 | -webkit-border-radius: 0; 115 | } 116 | 117 | /*******************/ 118 | 119 | .plyr-type-playlist plyr-playlist a.plyr-playlist-item-remove { 120 | float: right; 121 | margin-right: 15px; 122 | /*font-weight: bold;*/ 123 | background-color: transparent; 124 | } 125 | -------------------------------------------------------------------------------- /assets/vendor/plyr/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ### v3.7.8 4 | 5 | - Feat: Minor demo style tweaks 6 | - Fix: Minor style fixes related to backgrounds and border radii (🚨 Requires a SCSS/CSS update 🚨) 7 | 8 | ### v3.7.7 9 | 10 | - Fix (Accessibility): Don’t set tabindex on parent container 11 | - Fix (Accessibility): Add `role="timer"` to time elements 12 | - Fix (Accessibility): Leverage native `:focus-visible` in CSS, instead of a custom solution (🚨 Requires a SCSS/CSS update 🚨) 13 | 14 | ### v3.7.6 15 | 16 | - Fix: Revert postinstall script 17 | 18 | ### v3.7.5 19 | 20 | - Fix: Replace `pnpm` with `npm` in scripts to fix build issues 21 | 22 | ### v3.7.4 23 | 24 | - Fix: Fixed event key with space (thanks @royeden!) 25 | - Fix: Changing Vimeo function call from `setVolume` to `setMuted` to fix iOS issue (issue #2624) (thanks @HandreMelo and Andre Fernandes Cristofolini Melo!) 26 | - Fix: Call preview-thumbnails listeners() function on load (thanks @mogzol!) 27 | - Fix: Fullscreen improvements for iOS & iPadOS 28 | - Feat: Remove need for iOS-specific styling (please update [volume.scss](https://github.com/sampotts/plyr/blob/master/src/sass/components/volume.scss)) 29 | 30 | ### v3.7.3 31 | 32 | - Fix: force nowrap in progress tooltips (related: #2549) (thanks @raad-altaie!) 33 | - Feat(i18n): Make captions autodetect text direction (#2540) (thanks @ebraminio!) 34 | - Fix: fixed menu border radius bug (#2548) (thanks @raad-altaie!) 35 | - Chore: navigator.platform is deprecated (#2530) (thanks @stamat!) 36 | - Feat: Added configurable property to elements for re-use (#2489) (thanks @NoirHusky!) 37 | - Docs: Replace example video ID with one that still works (#2518) (thanks @luvejo!) 38 | - Fix: Improve accessibility on control buttons with aria-pressed (#2523) (thanks @emilkarl!) 39 | - Fix: Fix for calc() in newer Dart Sass versions (#2519) (thanks @ckhicks!) 40 | - Fix: simplify logic for isFunction assertion method 41 | - Chore: update types to include string for controls 42 | - Chore: upgrade packages 43 | - Chore: use `.node-version` instead of `.nvmrc` 44 | 45 | ### v3.7.2 46 | 47 | - Fix: Add `@babel/plugin-proposal-optional-chaining` to transform optional chaining in build output 48 | 49 | ### v3.7.1 50 | 51 | - Feat: Minor styling improvements to the preview thumbnails (🚨 Requires a SCSS/CSS update 🚨) 52 | - Fix: Fix invalid CSS @charset rule in Sass files (thanks @Hashen110!) 53 | - Chore: Replace deprecated KeyboardEvent `keyCode` references to use `key` instead (thanks @Hashen110!) 54 | - Various other code clean up and typo fixes (thanks @Hashen110!) 55 | 56 | ## v3.7.0 57 | 58 | - Feat: Add markers support (🚨 Requires a SCSS/CSS update 🚨) (thanks @ForeverSc and @fengshuo!) 59 | - Feat: Add support for MediaMetadata (thanks @Hashen110!) 60 | - Fix: Pass this context to captions.setup (fixes #2352) (thanks @WilliamMHerring, @willherring and @zenyr!) 61 | - Fix: Modify vimeo parseHash to use non-named capture groups (fixes #2396) (thanks @fekle!) 62 | - Fix: Replace deprecated String.prototype.substr() (thanks @CommanderRoot!) 63 | - Docs: Update speed option default to match the source (thanks @ozgurg!) 64 | - Docs: SASS → Sass (thanks @toastal!) 65 | 66 | ### v3.6.12 67 | 68 | - Fix: remove division logic from ads.scss (fixes #2370) 69 | 70 | ### v3.6.11 71 | 72 | - Fix: Replace `list.slash` added in 3.6.10 with `calc` 73 | - Chore: Package upgrades 74 | - Chore: Sass clean up 75 | - Chore: Improvements to style linting 76 | 77 | ### v3.6.10 78 | 79 | - Fix: Use `list.slash` instead of deprecated syntax 80 | - Chore: Clean up demo 81 | 82 | ### v3.6.9 83 | 84 | - Fix: Sass issue with division (thanks @ROL4ND909 and @le0pard) 85 | - Fix: Captions when switching sources (thanks @zexingguo) 86 | - Fix: Icons loading within iframes (thanks @ajgagnon) 87 | - Chore: Update TypeScript types (thanks @Jackie1210 and @AntLevin) 88 | - Fix: iOS fullscreen centering (thanks @hemratna) 89 | - Feat: Added getter and setter for preview thumbnails (thanks @Benny739) 90 | - Fix: Change fullscreen element to player rootnode (thanks @Walter van den Houten) 91 | - Fix: Fixed errors when Plyr instance is destroyed before constructor setTimeout() functions execute (thanks @emilis-ideait) 92 | - Fix: Invalid CSS selector syntax (thanks @BjornBrandewallNaviga) 93 | - Fix: Video height issues 94 | - Feat: Improve support for Vimeo private videos (thanks @Frosch) 95 | - Fix: YouTube duration issues (thanks @liesahead) 96 | 97 | ### v3.6.8 98 | 99 | - Typings: add FullscreenOptions.container to typing files (thanks @MeguminSama!) 100 | - Fix: added iPadOS detection to isIos util (thanks @Benny739!) 101 | - Fix: issues with Vimeo fullscreen 102 | 103 | ### v3.6.7 104 | 105 | - Fix: remove regression caused by optional chaining and nullish coalescing in check for `window.CSS` check for aspect-ratio (fixes #2174) 106 | 107 | ### v3.6.6 108 | 109 | - Improvements to how aspect ratio is handled. Use `aspect-ratio` CSS property instead of the legacy method (still used as fallback). Also automatically determined aspect ratios are rounded to the nearast standard ratio. This fixes issues with the YouTube embeds showing a 1-2px black bar. 110 | - Hide the YouTube poster image container when paused so that the controls underneath can be used. 111 | 112 | ### v3.6.5 113 | 114 | - Migrate color formatting to colorette (thanks @jorgebucaran) 115 | - Fix: issue with IE detection 116 | - Fix: missing styles for embeds 117 | - Fix: regression regarding poster image 118 | - Add all required props to vimeo iframe allow attribute - fixes #2151 (thanks @didrip) 119 | 120 | ### v3.6.4 121 | 122 | - Remove unnecessary calc from media query (thanks @naomiaz) 123 | - Enhance types (thanks @lunika) 124 | - Fix: Object.values for the providers must be used (thanks @syteknet-core) 125 | - Fix: Improve support inside iframes (thanks @ajgagnon) 126 | - Added --plyr-video-background for having control over the background of a video with alpha channel (webm) or a poster image with alpha channel (thanks @nepomuc) 127 | - Fix issue with not entering iosfullscreen of vimeo videos with playsinline=true (thanks @lordon and @Frosch) 128 | - fix: use new syntax for iframe allow attribute 129 | - chore: package updates 130 | - chore: add @babel/plugin-proposal-class-properties 131 | - fix: use bound arrow functions in classes 132 | 133 | ### v3.6.3 134 | 135 | - Fix volume when unmuting from volume 0 using YouTube (thanks @stephanefbouchard) 136 | - Add missing unit to calc in media query (thanks @vincentorback) 137 | - Assigning player's lastSeekTime on rewind/fast forward to prevent immediate controls hide on mobile (thanks @trafium) 138 | - Fix for volume control overflowing in Firefox (thanks @dirkjf) 139 | - Force fullscreen events to trigger on plyr element (media element in iOS) and not fullscreen container (thanks @theprojectsomething) 140 | - TypeScript types improvements (thanks @akuma06 & @iwatakeshi) 141 | - Dash demo link fixed (thanks @jonathanarbely) 142 | - Fix "A `ReferenceError: _classCallCheck is not defined` error has occurred." error (thanks @hex-ci) 143 | - Fix issue with CSS custom property check (thanks @syedhusain-appspace) 144 | - Fix for slow loading videos not autoplaying (thanks @DanielHuntleySBG) 145 | - Fix for network requests are not cancelled after the player is destroyed (thanks @DanielHuntleySBG) 146 | - Added option to disable custom controls for YouTube and Vimeo 147 | 148 | ### v3.6.2 149 | 150 | - Fixes for CSS Custom Property related errors in some build tools (thanks @Bashev) 151 | - Fixes for custom controls as element (thanks @taylorchu) 152 | - Added missing TypeScript interface for preview thumbnail options (thanks @taylorchu) 153 | 154 | ### v3.6.1 155 | 156 | - Safari bug fix 157 | 158 | ## v3.6.0 159 | 160 | - You can now easily change colors using CSS Custom Properties. See the [README](README.md#customizing-the-css). 161 | - Bug fix for Vimeo fullscreen. 162 | - Various typos (thanks @likev) 163 | - Preload TextTracks as per default video element (thanks @theprojectsomething) 164 | - Features/fullscreen container (thanks @theprojectsomething) 165 | - Ignore internal play promises (thanks @ydylla) 166 | - Ads plugin fixes to allow multiple VAST requests (thanks @Steejo) 167 | - Fix shadowroot (thanks @jnoordsij) 168 | - Add financial contributors for Open Collective (thanks @monkeywithacupcake) 169 | - Update the gitpod setup description to be more precise. (thanks @nisarhassan12) 170 | - Completely hide SVG icons to screen readers (thanks @LeBenLeBen) 171 | - Preview thumbnails via src:callback() (thanks @doublex) 172 | - Add missing Typescripts types and options (thanks @hug963) 173 | - Use number instead of string in TS quality definitions (thanks @mogzol) 174 | - Fix Vimeo playback rate (thanks @hug963) 175 | - Fix issue when controls config is string or element (thanks @CzBiX) 176 | - Simplify contributions by fully automating the dev setup with gitpod (thanks @nisarhassan12) 177 | 178 | ### v3.5.10 179 | 180 | - iOS volume display fix 181 | 182 | ### v3.5.9 183 | 184 | - Fix for regression with volume control width 185 | - Ensure poster image is not downloaded again for HTML5 videos 186 | 187 | ### v3.5.8 188 | 189 | - Added `flex-direction` property to fix some issues introduced in v3.5.7 when using custom CSS 190 | - Cleaned up the organization of some of the SCSS files (should not effect CSS output) 191 | - Added `referrerPolicy` option for Vimeo to prevent an issue present in the demo site 192 | - Remove all Vimeo controls for Pro & Premium accounts 193 | - Improve thumbnail size calculations when size is set per css (thanks @ydylla) 194 | - Add previewThumbnails source setter (thanks @ydylla) 195 | - More speed setting logic improvements 196 | 197 | ### v3.5.7 198 | 199 | - Typescript typings (thanks @ondratra) 200 | - `togglePlay` now also returns a `Promise` (thanks @azizhk) 201 | - Documentation improvements and typo fixes (thanks @ffpetrovic, @skerbis, @ayunami2000, @pjbaert, @MaxGiting, @0xflotus and @thatrobotdev) 202 | - Accessibility tweak for the play button (thanks @lunika) 203 | - Fix for ads configuration (thanks @SoftCreatR) 204 | - Fix handling listener return value (thanks @taion) 205 | - Added localization key for PIP (picture-in-picture) (thanks @lmislm) 206 | - Preserve viewBox attribute in SVG sprite symbols (thanks @bseib) 207 | - Fix being unable to unmute autoplayed video on iOS (thanks @sumanbh) 208 | - Fixed Plyr container not resizing responsively (thanks @shravan2x) 209 | - Change vimeo demo video (thanks @thatrobotdev) 210 | - Fix for `Uncaught RangeError: Maximum call stack size exceeded` (thanks @laukstein) 211 | - Improve fullscreen experience on some devices (thanks @savroff) 212 | - Improvements to buffering state for embedded players (thanks @doostinharrell) 213 | - Prevents IE11 with resetOnEnd option set to true to play video again (thanks @Felipe K. De Boni) 214 | - Fix for multiple poster image downloads (use the native poster only for HTML5 videos) 215 | - Various presentational fixes 216 | - Removed logic to hide/show volume controls based on audio track detection due to it's problematic nature. If you want to hide volume control, use the `controls` option to do so. 217 | - Fix preview thumbnail scrubbing not working on mobile touch devices (thanks @ydylla) 218 | - Add download attribute to download button (thanks @Code1110) 219 | - Trap keyboard focus only when fullscreen (thanks @k-jensen) 220 | - Improvements to speed options - you can now specify all options in the UI (YouTube and Vimeo only accept 0.5-2) (thanks @ydylla) 221 | - Improve/fix quality change state restoring (thanks @ydylla) 222 | 223 | _Note:_ This update contains CSS changes. 224 | 225 | ### v3.5.6 226 | 227 | - Another Edge fix (thanks Nick Hawk via Slack) 228 | 229 | ### v3.5.5 230 | 231 | - YouTube fix for when there are other embeds on the page (thanks @aFarkas) 232 | - Separated demo dependencies into their own package.json 233 | - Fix for Edge controls flexbox issue when resizing the player (thanks Nick Hawk via Slack) 234 | - More aspect ratio fixes 235 | 236 | ### v3.5.4 237 | 238 | - Added: Set download URL via new setter 239 | - Improvement: The order of the `controls` option now effects the order in the DOM - i.e. you can re-order the controls - Note: this may break any custom CSS you have setup. Please see the changes in the PR to the default Sass 240 | - Fixed issue with empty controls and preview thumbs 241 | - Fixed issue with setGutter call (from Sentry) 242 | - Fixed issue with initial selected speed not working 243 | - Added notes on `autoplay` config option and browser compatibility 244 | - Fixed issue with ads volume not matching current content volume 245 | - Fixed race condition where ads were loading during source change 246 | - Improvement: Automatic aspect ratio for YouTube is now supported, meaning all aspect ratios are set based on media content - Note: we're now using a different API to get YouTube video metadata so you may need to adjust any CSPs you have setup 247 | - Fix for menu in the Shadow DOM (thanks @emielbeinema) 248 | 249 | ### v3.5.3 250 | 251 | - Improved the usage of the `ratio` config option; it now works as expected and for all video types. The default has not changed, it is to dynamically, where possible (except YouTube where 16:9 is used) determine the ratio from the media source so this is not a breaking change. 252 | - Added new `ratio` getter and setter 253 | - Fix: Properly clear all timeouts on destroy 254 | - Fix: Allow absolute paths in preview thumbnails 255 | - Improvement: Allow optional hours and ms in VTT parser in preview thumbnails 256 | 257 | ### v3.5.2 258 | 259 | - Fixed issue where the preview thumbnail was present while scrubbing 260 | 261 | ### v3.5.1 262 | 263 | - Fixed build issues with babel and browserslist 264 | 265 | ## v3.5.0 266 | 267 | - Preview seek/scrubbing thumbnails (thanks @jamesoflol) 268 | - Fixes for proxy listeners (thanks @gurupras) 269 | - Fix for buffer progress transition on WebKit (thanks @samuelgozi) 270 | - Fix for error when mime type not specified (fixes #1274) 271 | - Support YouTube noCookie (thanks Omar Khatib) 272 | - Add Angular plugin reference (thanks @smnbbrv) 273 | - Use `Math.trunc` instead of `parseInt` (thanks @taion) 274 | - Many fixes for fullscreen in embedded players with non 16:9 screens or videos 275 | - Added 'force' fallback option for fullscreen 276 | - [RangeTouch](https://rangetouch.com) is now bundled with Plyr as a dependency to fix the scrubber on touch devices 277 | 278 | ### v3.4.8 279 | 280 | - Calling customized controls function with proper arguments (thanks @a60814billy) 281 | 282 | ### v3.4.7 283 | 284 | - Fix for Vimeo fullscreen with non native aspect ratios (fixes #854) 285 | 286 | ### v3.4.6 287 | 288 | - Added picture-in-picture support for Chrome 70+ 289 | - Fixed issue with versioning the SVG sprite in the gulp build script 290 | 291 | ### v3.4.5 292 | 293 | - Added download button option to download either current source or a custom URL you specify in options 294 | - Prevent immediate hiding of controls on mobile (thanks @jamesoflol) 295 | - Don't hide controls on focusout event (fixes #1122) (thanks @jamesoflol) 296 | - Fix HTML5 quality settings being incorrectly set in local storage (thanks @TechGuard) 297 | 298 | ### v3.4.4 299 | 300 | - Fixed issue with double binding for `click` and `touchstart` for `clickToPlay` option 301 | - Improved "faux" fullscreen on iPhone X/XS phones with notch 302 | - Babel 7 upgrade (which reduced the polyfilled build by ~10kb!) 303 | 304 | ### v3.4.3 305 | 306 | - Fixed issue with nodeList for custom playback controls 307 | 308 | ### v3.4.2 309 | 310 | - Fix play/pause button state 311 | 312 | ### v3.4.1 313 | 314 | - Bug fix for custom controls (fixes #1161) 315 | 316 | ## v3.4.0 317 | 318 | - Accessibility improvements (see #905) 319 | - Improvements to the way the controls work on iOS 320 | - Demo code clean up 321 | - YouTube quality selection removed due to their poor support for it. As a result, the `qualityrequested` event has been removed 322 | - Controls spacing improvements 323 | - Fix for pressed property missing with custom controls (Fixes #1062) 324 | - Fix #1153: Captions language fallback (thanks @friday) 325 | - Fix for setting pressed property of undefined (Fixes #1102) 326 | 327 | ### v3.3.23 328 | 329 | - Add support for YouTube's hl param (thanks @renaudleo) 330 | - Fix for captions positioning when no controls (thanks @friday and @mjfwebb) 331 | - Fix #1108: Make sure youtube.onReady doesn't run twice (thanks @friday) 332 | - Fix for WebKit repaint loop on the `` elements 333 | 334 | ### v3.3.22 335 | 336 | - Travis & CI improvements (thanks @friday) 337 | - Add navigator.languages fallback for iOS 9 (thanks @friday) 338 | 339 | ### v3.3.21 340 | 341 | - Hide currentTime and progress for streams (thanks @mimse) 342 | - Fixed condition check (thanks @mimse) 343 | - Handle undefined this.player.elements.buttons.play (thanks @klassicd) 344 | - Fix captions.toggle() if there is no toggle button (thanks @friday) 345 | 346 | ### v3.3.20 347 | 348 | - Fix for bug where controls wouldn't show on hover over YouTube video 349 | 350 | ### v3.3.19 351 | 352 | - Remove `pointer-events: none` on embed `