From 65ce47a7d1d6e3b0671bb1d305c9cbb90461fc60 Mon Sep 17 00:00:00 2001 From: infiinte-persistence Date: Thu, 14 Jan 2021 15:15:26 +0800 Subject: [PATCH] Add Chromecast support on Google Chrome. --- package.json | 1 + .../viewers/videoViewer/internal/videojs.jsx | 54 ++++++++++++++++++- yarn.lock | 23 ++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0b339177f..c0b1d3bbb 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "@reach/utils": "^0.12.1", "@sentry/browser": "^5.12.1", "@sentry/webpack-plugin": "^1.10.0", + "@silvermine/videojs-chromecast": "^1.2.2", "@types/three": "^0.93.1", "adm-zip": "^0.4.13", "async-exit-hook": "^2.0.1", diff --git a/ui/component/viewers/videoViewer/internal/videojs.jsx b/ui/component/viewers/videoViewer/internal/videojs.jsx index 80f97f096..d3c4eb602 100644 --- a/ui/component/viewers/videoViewer/internal/videojs.jsx +++ b/ui/component/viewers/videoViewer/internal/videojs.jsx @@ -12,6 +12,11 @@ import qualitySelector from 'videojs-hls-quality-selector'; import qualityLevels from 'videojs-contrib-quality-levels'; import isUserTyping from 'util/detect-typing'; +// @if TARGET='web' +import '@silvermine/videojs-chromecast/dist/silvermine-videojs-chromecast.css'; +require('@silvermine/videojs-chromecast')(videojs); +// @endif + const isDev = process.env.NODE_ENV !== 'production'; export type Player = { @@ -33,6 +38,7 @@ export type Player = { userActive: (?boolean) => boolean, overlay: any => void, mobileUi: any => void, + chromecast: any => void, controlBar: { addChild: (string, any) => void, }, @@ -146,6 +152,49 @@ class LbryVolumeBarClass extends videojs.getComponent(VIDEOJS_VOLUME_BAR_CLASS) } } +// **************************************************************************** +// Chromecast +// **************************************************************************** + +class ChromecastWrapper { + /** + * Actions that need to happen before initializing 'videojs'. + */ + static preInit(videojs, options, title) { + const additionalOptions = { + // @if TARGET='web' + techOrder: ['chromecast', 'html5'], + chromecast: { + requestTitleFn: function(src) { + return ''; + }, + }, + // @endif + }; + + return videojs.mergeOptions(options, additionalOptions); + } + + /** + * Actions that need to happen after initializing 'videojs' + */ + static postInit(player) { + // @if TARGET='web' + // --- Start plugin --- + player.chromecast(); + // --- Init cast framework --- + const existingChromecastScript = document.getElementById('chromecastApi'); + if (!existingChromecastScript) { + const script = document.createElement('script'); + script.src = 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1'; + script.id = 'chromecastApi'; + // $FlowFixMe + document.body.appendChild(script); + } + // @endif + } +} + // **************************************************************************** // VideoJs // **************************************************************************** @@ -159,7 +208,7 @@ export default React.memo(function VideoJs(props: Props) { let player: ?Player; const containerRef = useRef(); - const videoJsOptions = { + let videoJsOptions = { ...VIDEO_JS_OPTIONS, sources: [ { @@ -334,6 +383,8 @@ export default React.memo(function VideoJs(props: Props) { videoJsOptions.sources[0].type = 'application/x-mpegURL'; } + videoJsOptions = ChromecastWrapper.preInit(videojs, videoJsOptions); + player = videojs(el, videoJsOptions, () => { if (player) { player.one('play', onInitialPlay); @@ -342,6 +393,7 @@ export default React.memo(function VideoJs(props: Props) { player.on('ended', onEnded); LbryVolumeBarClass.replaceExisting(player); player.mobileUi(); // Inits mobile version. No-op if Desktop. + ChromecastWrapper.postInit(player); onPlayerReady(player); } diff --git a/yarn.lock b/yarn.lock index 7fdcb1670..bed930476 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2040,6 +2040,15 @@ dependencies: "@sentry/cli" "^1.49.0" +"@silvermine/videojs-chromecast@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@silvermine/videojs-chromecast/-/videojs-chromecast-1.2.2.tgz#da679e50b856be8d1586bc7df9cb85466a2f2f6b" + integrity sha512-4EpUm4Zf21yWbloJXEbvmWBM468onj8lk12cp+W1RsH3YNm3hIx7/y4w5QnA/TLCQ4gUpxMTwFYrgE/ejr9Gmw== + dependencies: + class.extend "0.9.1" + underscore "1.9.1" + webcomponents.js "git+https://git@github.com/webcomponents/webcomponentsjs.git#v0.7.24" + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -3557,6 +3566,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +class.extend@0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/class.extend/-/class.extend-0.9.1.tgz#b4ee417c693740a44a92a6d64f1c9540641b097a" + integrity sha1-tO5BfGk3QKRKkqbWTxyVQGQbCXo= + classnames@^2.2.5: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" @@ -11671,6 +11685,11 @@ undefsafe@^2.0.2: dependencies: debug "^2.2.0" +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + underscore@>1.4.4: version "1.9.2" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.2.tgz#0c8d6f536d6f378a5af264a72f7bec50feb7cf2f" @@ -12220,6 +12239,10 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +"webcomponents.js@git+https://git@github.com/webcomponents/webcomponentsjs.git#v0.7.24": + version "0.7.24" + resolved "git+https://git@github.com/webcomponents/webcomponentsjs.git#8a2e40557b177e2cca0def2553f84c8269c8f93e" + webpack-bundle-analyzer@^3.1.0: version "3.6.1" resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.6.1.tgz#bdb637c2304424f2fbff9a950c7be42a839ae73b"