├── .browserslistrc ├── .editorconfig ├── .eslintrc.json ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .jsdoc ├── .markdownlint-cli2.cjs ├── .npmignore ├── .nvmrc ├── .nycrc.json ├── .stylelintrc.yml ├── CHANGELOG.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── commitlint.config.js ├── docs └── demo │ └── index.html ├── package-lock.json ├── package.json ├── src ├── .eslintrc.json ├── images │ ├── ic_cast_black_24dp.png │ ├── ic_cast_blue_24dp.png │ ├── ic_cast_connected_black_24dp.png │ ├── ic_cast_connected_blue_24dp.png │ ├── ic_cast_connected_grey_24dp.png │ ├── ic_cast_connected_white_24dp.png │ ├── ic_cast_grey_24dp.png │ └── ic_cast_white_24dp.png ├── js │ ├── chromecast │ │ └── ChromecastSessionManager.js │ ├── components │ │ └── ChromecastButton.js │ ├── enableChromecast.js │ ├── index.js │ ├── preloadWebComponents.js │ ├── standalone.js │ └── tech │ │ ├── ChromecastTech.js │ │ └── ChromecastTechUI.js └── scss │ ├── _chromecastButton.scss │ ├── _tech.scss │ └── videojs-chromecast.scss └── tests ├── .eslintrc.json ├── ChromcastButton.test.js ├── ChromcastTech.test.js └── Placeholder.test.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | ./node_modules/@silvermine/standardization/browserslist/.browserslistrc-broad-support -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | ./node_modules/@silvermine/standardization/.editorconfig -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "extends": "@silvermine/eslint-config/node" 4 | 5 | } 6 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [ push, pull_request ] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | outputs: 9 | nvmrc: ${{ steps.makeNodeVersionOutput.outputs.nvmrc }} 10 | steps: 11 | - 12 | uses: actions/checkout@v4 13 | with: 14 | fetch-depth: 0 # Fetch all history 15 | - 16 | uses: actions/setup-node@v4 17 | with: 18 | node-version-file: '.nvmrc' 19 | - 20 | name: Put NVM version in output 21 | id: makeNodeVersionOutput 22 | run: echo "nvmrc=$(cat .nvmrc)" >> "$GITHUB_OUTPUT" 23 | - run: npm ci 24 | - run: npm run check-node-version 25 | - run: npm run standards 26 | - run: npm run build 27 | - 28 | name: Check for uncommitted changes # Done after dependency install and build to ensure code isn't compromised 29 | run: if [ -n "$(git status --porcelain)" ]; then echo 'There are uncommitted changes.'; exit 1; fi 30 | test: 31 | needs: [ build ] 32 | runs-on: ubuntu-latest 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | node-version: [ 16, '${{ needs.build.outputs.nvmrc }}', 'lts/*', 'latest' ] 37 | steps: 38 | - 39 | uses: actions/checkout@v4 40 | with: 41 | fetch-depth: 0 # Fetch all history 42 | - 43 | name: Use Node.js ${{ matrix.node-version }} 44 | uses: actions/setup-node@v4 45 | with: 46 | node-version: ${{ matrix.node-version }} 47 | - run: npm ci # Reinstall the dependencies to ensure they install with the current version of node 48 | - run: npm run standards 49 | - run: npm run build # Ensure building is possible with this version of node 50 | - run: npm test 51 | - 52 | name: Coveralls 53 | uses: coverallsapp/github-action@v2 54 | with: 55 | parallel: true 56 | flag-name: ${{ matrix.node-version }} 57 | finish: 58 | needs: [ test ] 59 | runs-on: ubuntu-latest 60 | steps: 61 | - 62 | name: Close parallel build 63 | uses: coverallsapp/github-action@v2 64 | with: 65 | parallel-finished: true 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # build directory 12 | dist 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | .nyc_output 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # node-waf configuration 22 | .lock-wscript 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/Release 26 | 27 | # Dependency directory 28 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 29 | node_modules 30 | 31 | # IDE 32 | **/.idea 33 | 34 | # VIM 35 | .*.sw? 36 | 37 | # OS 38 | .DS_Store 39 | .tmp 40 | -------------------------------------------------------------------------------- /.jsdoc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ "plugins/markdown" ] 3 | } 4 | -------------------------------------------------------------------------------- /.markdownlint-cli2.cjs: -------------------------------------------------------------------------------- 1 | node_modules/@silvermine/standardization/.markdownlint-cli2.shared.cjs -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .eslintrc.json 2 | .travis.yml 3 | .npmignore 4 | Gruntfile.js 5 | tests/** 6 | .nyc_output 7 | coverage 8 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v20.12.2 2 | -------------------------------------------------------------------------------- /.nycrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "src/**/*.js" 4 | ], 5 | "extension": [ 6 | ".js" 7 | ], 8 | "reporter": [ 9 | "text-summary", 10 | "html", 11 | "lcov" 12 | ], 13 | "instrument": true, 14 | "sourceMap": true, 15 | "all": true 16 | } 17 | -------------------------------------------------------------------------------- /.stylelintrc.yml: -------------------------------------------------------------------------------- 1 | extends: ./node_modules/@silvermine/standardization/.stylelintrc.yml 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [our coding standards][commit-messages] for commit guidelines. 5 | 6 | ## [1.5.0](https://github.com/silvermine/videojs-chromecast/compare/v1.4.1...v1.5.0) (2023-11-07) 7 | 8 | 9 | ### Features 10 | 11 | * Allow modifying the load request ([#123](https://github.com/silvermine/videojs-chromecast/issues/123), [#141](https://github.com/silvermine/videojs-chromecast/issues/141)) ([7cee052](https://github.com/silvermine/videojs-chromecast/commit/7cee052dcd5473448f882d67bb5bc9d8e9a1763c)) 12 | 13 | 14 | ### Bug Fixes 15 | 16 | * Clear the close session timeout after new source starts playing ([4a8eb31](https://github.com/silvermine/videojs-chromecast/commit/4a8eb31faa241235c54c1f8dec897571360e7f19)) 17 | 18 | 19 | ### [1.4.1](https://github.com/silvermine/videojs-chromecast/compare/v1.4.0...v1.4.1) (2023-03-21) 20 | 21 | 22 | ### Bug Fixes 23 | 24 | * remove deprecated `.extend` method ([994b5b9](https://github.com/silvermine/videojs-chromecast/commit/994b5b9ae6df89f657e2ff4a920056826094b54f)), closes [#152](https://github.com/silvermine/videojs-chromecast/issues/152) [#147](https://github.com/silvermine/videojs-chromecast/issues/147) 25 | 26 | 27 | ## [1.4.0](https://github.com/silvermine/videojs-chromecast/compare/v1.3.4...v1.4.0) (2023-03-21) 28 | 29 | 30 | ### Features 31 | 32 | * Add optional "Cast" label to button component ([220c362](https://github.com/silvermine/videojs-chromecast/commit/220c36247c9ac992b757b97257e24e665ac3feb5)) 33 | * Change label to "Disconnect Cast" when connected ([a7f495b](https://github.com/silvermine/videojs-chromecast/commit/a7f495b78d8472322079a75a834440fd20858b3c)) 34 | * Set image on cast device if the video has a poster ([902464c](https://github.com/silvermine/videojs-chromecast/commit/902464cecf468c554fb062bd93d09bae9e303922)) 35 | 36 | 37 | ### Bug Fixes 38 | 39 | * Chromecast button with label styling breaking on cast/disconnect ([2a181de](https://github.com/silvermine/videojs-chromecast/commit/2a181dea847927050b57453f9474a2f47028fdca)) 40 | 41 | 42 | [commit-messages]: https://github.com/silvermine/silvermine-info/blob/master/commit-history.md#commit-messages 43 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Jeremy Thomerson 3 | * Licensed under the MIT license. 4 | */ 5 | 'use strict'; 6 | 7 | var path = require('path'), 8 | getCodeVersion = require('silvermine-serverless-utils/src/get-code-version'), 9 | join = path.join.bind(path), 10 | sass = require('sass'); 11 | 12 | module.exports = function(grunt) { 13 | 14 | var DEBUG = !!grunt.option('debug'), 15 | config; 16 | 17 | config = { 18 | js: { 19 | all: [ 'Gruntfile.js', 'src/**/*.js', 'tests/**/*.js' ], 20 | browserMainFile: join('src', 'js', 'standalone.js'), 21 | }, 22 | 23 | sass: { 24 | all: [ '**/*.scss', '!**/node_modules/**/*' ], 25 | main: join('src', 'scss', 'videojs-chromecast.scss'), 26 | }, 27 | 28 | images: { 29 | base: join('src', 'images'), 30 | }, 31 | 32 | dist: { 33 | base: join(__dirname, 'dist'), 34 | }, 35 | }; 36 | 37 | config.dist.js = { 38 | bundle: join(config.dist.base, 'silvermine-videojs-chromecast.js'), 39 | minified: join(config.dist.base, 'silvermine-videojs-chromecast.min.js'), 40 | }; 41 | 42 | config.dist.css = { 43 | base: config.dist.base, 44 | main: join(config.dist.base, 'silvermine-videojs-chromecast.css'), 45 | }; 46 | 47 | config.dist.images = join(config.dist.base, 'images'); 48 | 49 | grunt.initConfig({ 50 | 51 | pkg: grunt.file.readJSON('package.json'), 52 | versionInfo: getCodeVersion.both(), 53 | config: config, 54 | 55 | clean: { 56 | build: [ config.dist.base ], 57 | }, 58 | 59 | copy: { 60 | images: { 61 | files: [ 62 | { 63 | expand: true, 64 | cwd: config.images.base, 65 | src: '**/*', 66 | dest: config.dist.images, 67 | }, 68 | ], 69 | }, 70 | }, 71 | 72 | browserify: { 73 | main: { 74 | src: config.js.browserMainFile, 75 | dest: config.dist.js.bundle, 76 | options: { 77 | transform: [ 78 | [ 79 | 'babelify', 80 | { 81 | presets: [ 82 | [ 83 | '@babel/preset-env', 84 | { 85 | debug: DEBUG, 86 | useBuiltIns: 'usage', 87 | shippedProposals: true, 88 | corejs: 3, 89 | }, 90 | ], 91 | ], 92 | }, 93 | ], 94 | ], 95 | }, 96 | }, 97 | }, 98 | 99 | uglify: { 100 | main: { 101 | files: { 102 | '<%= config.dist.js.minified %>': config.dist.js.bundle, 103 | }, 104 | options: { 105 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> <%= versionInfo %> */\n', 106 | sourceMap: DEBUG, 107 | sourceMapIncludeSources: DEBUG, 108 | mangle: !DEBUG, 109 | // Disable the `merge_vars` option in the compression phase. 110 | // `merge_vars` aggressively reuses variable names, which can lead to 111 | // unexpected behavior or runtime errors in certain cases. 112 | compress: DEBUG ? false : { merge_vars: false }, // eslint-disable-line camelcase 113 | beautify: DEBUG, 114 | }, 115 | }, 116 | }, 117 | 118 | sass: { 119 | main: { 120 | files: [ 121 | { 122 | src: config.sass.main, 123 | dest: config.dist.css.main, 124 | ext: '.css', 125 | extDot: 'first', 126 | }, 127 | ], 128 | }, 129 | options: { 130 | implementation: sass, 131 | sourceMap: DEBUG, 132 | indentWidth: 3, 133 | outputStyle: DEBUG ? 'expanded' : 'compressed', 134 | sourceComments: DEBUG, 135 | }, 136 | }, 137 | 138 | postcss: { 139 | options: { 140 | map: DEBUG, 141 | processors: [ 142 | require('autoprefixer')(), // eslint-disable-line global-require 143 | ], 144 | }, 145 | styles: { 146 | src: config.dist.css.main, 147 | }, 148 | }, 149 | 150 | watch: { 151 | grunt: { 152 | files: [ 'Gruntfile.js' ], 153 | tasks: [ 'build' ], 154 | }, 155 | 156 | js: { 157 | files: [ 'src/**/*.js' ], 158 | tasks: [ 'build-js' ], 159 | }, 160 | 161 | css: { 162 | files: [ 'src/**/*.scss' ], 163 | tasks: [ 'build-css' ], 164 | }, 165 | }, 166 | 167 | }); 168 | 169 | grunt.loadNpmTasks('grunt-contrib-clean'); 170 | grunt.loadNpmTasks('grunt-contrib-uglify'); 171 | grunt.loadNpmTasks('grunt-browserify'); 172 | grunt.loadNpmTasks('grunt-contrib-copy'); 173 | grunt.loadNpmTasks('grunt-contrib-watch'); 174 | grunt.loadNpmTasks('grunt-sass'); 175 | grunt.loadNpmTasks('grunt-postcss'); 176 | 177 | grunt.registerTask('build-js', [ 'browserify', 'uglify' ]); 178 | grunt.registerTask('build-css', [ 'sass', 'postcss:styles' ]); 179 | grunt.registerTask('build', [ 'build-js', 'build-css', 'copy:images' ]); 180 | grunt.registerTask('develop', [ 'build', 'watch' ]); 181 | grunt.registerTask('default', [ 'build' ]); 182 | 183 | }; 184 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2017 Jeremy Thomerson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8 | of the Software, and to permit persons to whom the Software is furnished to do 9 | so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Silvermine VideoJS Chromecast Plugin 2 | 3 | 4 | [![Build Status](https://travis-ci.org/silvermine/videojs-chromecast.svg?branch=master)](https://travis-ci.org/silvermine/videojs-chromecast) 5 | [![Coverage Status](https://coveralls.io/repos/github/silvermine/videojs-chromecast/badge.svg?branch=master)](https://coveralls.io/github/silvermine/videojs-chromecast?branch=master) 6 | [![Dependency Status](https://david-dm.org/silvermine/videojs-chromecast.svg)](https://david-dm.org/silvermine/videojs-chromecast) 7 | [![Dev Dependency Status](https://david-dm.org/silvermine/videojs-chromecast/dev-status.svg)](https://david-dm.org/silvermine/videojs-chromecast#info=devDependencies&view=table) 8 | 9 | 10 | 11 | ## What is it? 12 | 13 | A plugin for [videojs](http://videojs.com/) versions 6+ that adds a button to the control 14 | bar which will cast videos to a Chromecast. 15 | 16 | 17 | ## How do I use it? 18 | 19 | The `@silvermine/videojs-chromecast` plugin includes 3 types of assets: JavaScript, CSS, 20 | and images. 21 | 22 | You can either build the plugin locally and use the assets that are output from the build 23 | process directly, or you can install the plugin as an NPM module, include the 24 | JavaScript and SCSS source in your project using a Common-JS module loader and SASS build 25 | process, and copy the images from the image source folder to your project. 26 | 27 | Note that regardless of whether you are using this plugin via the pre-built JS or as a 28 | module, the Chromecast framework will need to be included after the plugin. For example: 29 | 30 | ```html 31 | 32 | 33 | 34 | ``` 35 | 36 | ### Building the plugin locally 37 | 38 | 1. Either clone this repository or install the `@silvermine/videojs-chromecast` module 39 | using `npm install @silvermine/videojs-chromecast`. 40 | 2. Ensure that `@silvermine/videojs-chromecast`'s `devDependencies` are installed by 41 | running `npm install` from within the `videojs-chromecast` folder. 42 | 3. Run `grunt build` to build and copy the JavaScript, CSS and image files to the 43 | `videojs-chromecast/dist` folder. 44 | 4. Copy the plugin's files from the `dist` folder into your project as needed. 45 | 5. Ensure that the images in the `dist/images` folder are accessible at `./images/`, 46 | relative to where the plugin's CSS is located. If, for example, your CSS is located 47 | at `https://example.com/plugins/silvermine-videojs-chromecast.css`, then the 48 | plugin's images should be located at `https://example.com/plugins/images/`. 49 | 6. Follow the steps in the "Configuration" section below. 50 | 51 | Note: when adding the plugin's JavaScript to your web page, include the 52 | `silvermine-videojs-chromecast.min.js` JavaScript file in your HTML *after* loading 53 | Video.js. The plugin's built JavaScript file expects there to be a reference to Video.js 54 | at `window.videojs` and will throw an error if it does not exist. 55 | 56 | ### Initialization options 57 | 58 | * **`preloadWebComponents`** (default: `false`) - The Chromecast framework relies on 59 | the `webcomponents.js` polyfill when a browser does not have 60 | `document.registerElement` in order to create the `` custom 61 | component (which is not used by this plugin). If you are using jQuery, this polyfill 62 | must be loaded and initialized before jQuery is initialized. Unfortunately, the 63 | Chromecast framework loads the `webcomponents.js` polyfill via a dynamically created 64 | ` 105 | 106 | ``` 107 | 108 | ### Configuration 109 | 110 | Once the plugin has been loaded and registered, configure it and add it to your Video.js 111 | player using Video.js' plugin configuration option (see the section under the heading 112 | "Setting up a Plugin" on [Video.js' plugin documentation page][videojs-docs]. 113 | 114 | **Important: In addition to defining plugin configuration, you are required to define the 115 | player's `techOrder` option, setting `'chromecast'` as the first Tech in the list.** Below 116 | is an example of the minimum required configuration for the Chromecast plugin to function: 117 | 118 | ```js 119 | var options; 120 | 121 | options = { 122 | controls: true, 123 | techOrder: [ 'chromecast', 'html5' ], // You may have more Tech, such as Flash or HLS 124 | plugins: { 125 | chromecast: {} 126 | } 127 | }; 128 | 129 | videojs(document.getElementById('myVideoElement'), options); 130 | ``` 131 | 132 | Please note that even if you choose not to use any of the configuration options, you must 133 | either provide a `chromecast` entry in the `plugins` option for Video.js to initialize the 134 | plugin for you: 135 | 136 | ```js 137 | options = { 138 | plugins: { 139 | chromecast: {} 140 | } 141 | }; 142 | ``` 143 | 144 | or you must initialize the plugin manually: 145 | 146 | ```js 147 | var player = videojs(document.getElementById('myVideoElement')); 148 | 149 | player.chromecast(); // initializes the Chromecast plugin 150 | ``` 151 | 152 | #### Configuration options 153 | 154 | ##### Plugin configuration 155 | 156 | * **`plugins.chromecast.receiverAppID`** - the string ID of a custom [Chromecast 157 | receiver app][cast-receiver] to use. Defaults to the [default Media Receiver 158 | ID][def-cast-id]. 159 | * **`plugins.chromecast.addButtonToControlBar`** - a `boolean` flag that tells the 160 | plugin whether or not it should automatically add the Chromecast button to the 161 | Video.js player's control bar component. Defaults to `true`. 162 | * **`plugins.chromecast.buttonPositionIndex`** - a zero-based number specifying the 163 | index of the Chromecast button among the control bar's child components (if 164 | `addButtonToControlBar` is set to `true`). By default the Chromecast Button is added 165 | as the last child of the control bar. A value less than 0 puts the button at the 166 | specified position from the end of the control bar. Note that it's likely not all 167 | child components of the control bar are visible. 168 | * **`plugins.chromecast.addCastLabelToButton`** (default: `false`) - by default, the 169 | Chromecast button component will display only an icon. Setting `addCastLabelToButton` 170 | to `true` will display a label titled `"Cast"` alongside the default icon. 171 | 172 | ##### Chromecast Tech configuration 173 | 174 | * **`chromecast.requestTitleFn`** - a function that this plugin calls when it needs a 175 | string that will be the title shown in the UI that is shown when a Chromecast session 176 | is active and connected. When the this plugin calls the `requestTitleFn`, it passes 177 | it the [current `source` object][player-source] and expects a string in return. If 178 | nothing is returned or if this option is not defined, no title will be shown. 179 | * **`chromecast.requestSubtitleFn`** - a function that this plugin calls when it needs 180 | a string that will be the sub-title shown in the UI that is shown when a Chromecast 181 | session is active and connected. When the this plugin calls the `requestSubtitleFn`, 182 | it passes it the [current `source` object][player-source] and expects a string in 183 | return. If nothing is returned or if this option is not defined, no sub-title will be 184 | shown. 185 | * **`chromecast.requestCustomDataFn`** - a function that this plugin calls when it 186 | needs an object that contains custom information necessary for a Chromecast receiver 187 | app when a session is active and connected. When the this plugin calls the 188 | `requestCustomDataFn`, it passes it the [current `source` object][player-source] and 189 | expects an object in return. If nothing is returned or if this option is not defined, 190 | no custom data will be sent. This option is intended to be used with a [custom 191 | receiver][custom-receiver] application to extend its default capabilities. 192 | * **`chromecast.modifyLoadRequestFn`** - a function that this plugin calls before doing 193 | the request to [load media][chromecast-load-media]. The function gets called with 194 | the [LoadRequest][chromecast-load-request] object as argument and expects it in 195 | return. 196 | 197 | Here is an example configuration object that makes full use of all required and optional 198 | configuration: 199 | 200 | ```js 201 | var titles, subtitles, customData, options; 202 | 203 | titles = { 204 | 'https://example.com/videos/video-1.mp4': 'Example Title', 205 | 'https://example.com/videos/video-2.mp4': 'Example Title2', 206 | }; 207 | 208 | subtitles = { 209 | 'https://example.com/videos/video-1.mp4': 'Subtitle', 210 | 'https://example.com/videos/video-2.mp4': 'Subtitle2', 211 | }; 212 | 213 | customData = { 214 | 'https://example.com/videos/video-1.mp4': { 'customColor': '#0099ee' }, 215 | 'https://example.com/videos/video-2.mp4': { 'customColor': '#000080' }, 216 | }; 217 | 218 | options = { 219 | // Must specify the 'chromecast' Tech first 220 | techOrder: [ 'chromecast', 'html5' ], // Required 221 | // Configuration for the Chromecast Tech 222 | chromecast: { 223 | requestTitleFn: function(source) { // Not required 224 | return titles[source.url]; 225 | }, 226 | requestSubtitleFn: function(source) { // Not required 227 | return subtitles[source.url]; 228 | }, 229 | requestCustomDataFn: function(source) { // Not required 230 | return customData[source.url]; 231 | }, 232 | modifyLoadRequestFn: function (loadRequest) { // HLS support 233 | loadRequest.media.hlsSegmentFormat = 'fmp4'; 234 | loadRequest.media.hlsVideoSegmentFormat = 'fmp4'; 235 | return loadRequest; 236 | } 237 | }, 238 | plugins: { 239 | chromecast: { 240 | receiverAppID: '1234' // Not required 241 | addButtonToControlBar: false, // Defaults to true 242 | }, 243 | } 244 | }; 245 | ``` 246 | 247 | ##### Localization 248 | 249 | The `ChromecastButton` component has two translated strings: "Open Chromecast menu" and 250 | "Cast". 251 | 252 | * The "Open Chromecast menu" string appears in both of the standard places for Button 253 | component accessibility text: inside the `.vjs-control-text` span and as the 254 | `