Work on video player to support dash and other features
Theatre Mode Captions Storyboards
This commit is contained in:
parent
70f53ad51a
commit
4dc8eab9b8
|
@ -2428,6 +2428,27 @@
|
|||
"fastq": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@silvermine/videojs-quality-selector": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@silvermine/videojs-quality-selector/-/videojs-quality-selector-1.2.3.tgz",
|
||||
"integrity": "sha512-votXSPzzydjZsBZT37589sTw31csgncWggaYPWKXTygCkzvc8V876iRNJiTykgaiZd/9qQn7pjwEJsOqnfp/pw==",
|
||||
"requires": {
|
||||
"class.extend": "0.9.1",
|
||||
"underscore": "1.9.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"class.extend": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/class.extend/-/class.extend-0.9.1.tgz",
|
||||
"integrity": "sha1-tO5BfGk3QKRKkqbWTxyVQGQbCXo="
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
|
||||
"integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
|
||||
|
@ -6977,6 +6998,11 @@
|
|||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-xml-parser": {
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.16.0.tgz",
|
||||
"integrity": "sha512-U+bpScacfgnfNfIKlWHDu4u6rtOaCyxhblOLJ8sZPkhsjgGqdZmVPBhdOyvdMGCDt8CsAv+cssOP3NzQptNt2w=="
|
||||
},
|
||||
"fastq": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz",
|
||||
|
@ -14478,11 +14504,110 @@
|
|||
"xhr": "2.4.0"
|
||||
}
|
||||
},
|
||||
"videojs-contrib-quality-levels": {
|
||||
"version": "2.0.9",
|
||||
"resolved": "https://registry.npmjs.org/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-2.0.9.tgz",
|
||||
"integrity": "sha512-HJeaJJQdSufi9Y5T7jlyyhkeq+mWPCog86q6ypoTi66boBMMJTo2abiOSHS9KaOGAJjH72gfvrjVY5FRdjlxYA==",
|
||||
"requires": {
|
||||
"global": "^4.3.2",
|
||||
"video.js": "^6 || ^7"
|
||||
}
|
||||
},
|
||||
"videojs-font": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-3.2.0.tgz",
|
||||
"integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA=="
|
||||
},
|
||||
"videojs-frankly-ttml": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/videojs-frankly-ttml/-/videojs-frankly-ttml-1.0.1.tgz",
|
||||
"integrity": "sha512-lmpTQA7q47V5S2ILpNhHbqOyWBebPGb3OGpTMXzUP1HkhA1ZdGSaBFLUG+manE9ZlONLu8FsoqrEFQoobCR4zA==",
|
||||
"requires": {
|
||||
"video.js": "^5.8.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"global": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/global/-/global-4.3.0.tgz",
|
||||
"integrity": "sha1-737EvurVebRU9evV5/MD21T0Kis=",
|
||||
"requires": {
|
||||
"min-document": "^2.6.1",
|
||||
"process": "~0.5.1"
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
|
||||
"integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8="
|
||||
},
|
||||
"video.js": {
|
||||
"version": "5.20.5",
|
||||
"resolved": "https://registry.npmjs.org/video.js/-/video.js-5.20.5.tgz",
|
||||
"integrity": "sha1-RFza4gS85Fl4LYajGyWjKv1tjv8=",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.9.2",
|
||||
"global": "4.3.0",
|
||||
"safe-json-parse": "4.0.0",
|
||||
"tsml": "1.0.1",
|
||||
"videojs-font": "2.0.0",
|
||||
"videojs-ie8": "1.1.2",
|
||||
"videojs-swf": "5.4.1",
|
||||
"videojs-vtt.js": "0.12.6",
|
||||
"xhr": "2.2.2"
|
||||
}
|
||||
},
|
||||
"videojs-font": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-2.0.0.tgz",
|
||||
"integrity": "sha1-r3Rh751LleAzS/+3iy8v8DZKkDQ="
|
||||
},
|
||||
"videojs-vtt.js": {
|
||||
"version": "0.12.6",
|
||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.12.6.tgz",
|
||||
"integrity": "sha512-XFXeGBQiljnElMhwCcZst0RDbZn2n8LU7ZScXryd3a00OaZsHAjdZu/7/RdSr7Z1jHphd45FnOvOQkGK4YrWCQ==",
|
||||
"requires": {
|
||||
"global": "^4.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"global": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||
"requires": {
|
||||
"min-document": "^2.19.0",
|
||||
"process": "^0.11.10"
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
"integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
|
||||
}
|
||||
}
|
||||
},
|
||||
"xhr": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/xhr/-/xhr-2.2.2.tgz",
|
||||
"integrity": "sha1-LuclcYafhobUFVmp6ihsGJcUNf8=",
|
||||
"requires": {
|
||||
"global": "~4.3.0",
|
||||
"is-function": "^1.0.1",
|
||||
"parse-headers": "^2.0.0",
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"videojs-http-source-selector": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/videojs-http-source-selector/-/videojs-http-source-selector-1.1.6.tgz",
|
||||
"integrity": "sha512-6b5MmKTT2cVnrjtdNj4z1VO91udbXkZkTYA6LlD8WN2aHlG2rqFTmtMab4NK4nlkkkbRnm3c2q2IddL3jffLmg==",
|
||||
"requires": {
|
||||
"global": "^4.3.2",
|
||||
"video.js": "^7.0.0",
|
||||
"videojs-contrib-quality-levels": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"videojs-ie8": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/videojs-ie8/-/videojs-ie8-1.1.2.tgz",
|
||||
|
@ -14576,6 +14701,16 @@
|
|||
"resolved": "https://registry.npmjs.org/videojs-swf/-/videojs-swf-5.4.1.tgz",
|
||||
"integrity": "sha1-IHfvccdJ8seCPvSbq65N0qywj4c="
|
||||
},
|
||||
"videojs-vtt-thumbnails": {
|
||||
"version": "0.0.13",
|
||||
"resolved": "https://registry.npmjs.org/videojs-vtt-thumbnails/-/videojs-vtt-thumbnails-0.0.13.tgz",
|
||||
"integrity": "sha512-7VGcpTRF+ppIss/NiZcDkVOE02k/GoMltxUumQ2jaTpR1ZieYTM+dPopmTXubLxOgUP3F71uTLMZVnWEtiHjVA==",
|
||||
"requires": {
|
||||
"global": "^4.3.2",
|
||||
"request": "^2.83.0",
|
||||
"video.js": "^5.19.2 || ^6.6.0 || ^7.2.0"
|
||||
}
|
||||
},
|
||||
"videojs-vtt.js": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.14.1.tgz",
|
||||
|
@ -15661,6 +15796,14 @@
|
|||
"node-fetch": "^2.6.0"
|
||||
}
|
||||
},
|
||||
"yt-xml2srt": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yt-xml2srt/-/yt-xml2srt-1.1.0.tgz",
|
||||
"integrity": "sha512-6JseclPTdiPEuXZ+cwiYl1xtqYDsyGfJqQfVSWmPXWT3bVEdAYPDXspMqQPRRXHdYEGaMD/oBz2mWMhXanKeOA==",
|
||||
"requires": {
|
||||
"fast-xml-parser": "^3.16.0"
|
||||
}
|
||||
},
|
||||
"ytdl-core": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-1.0.7.tgz",
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"@fortawesome/fontawesome-svg-core": "^1.2.27",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.12.1",
|
||||
"@fortawesome/vue-fontawesome": "^0.1.9",
|
||||
"@silvermine/videojs-quality-selector": "^1.2.3",
|
||||
"autolinker": "^3.11.1",
|
||||
"bulma-pro": "^0.1.8",
|
||||
"dateformat": "^3.0.3",
|
||||
|
@ -22,7 +23,10 @@
|
|||
"nedb": "^1.8.0",
|
||||
"opml-to-json": "0.0.3",
|
||||
"video.js": "^7.6.6",
|
||||
"videojs-contrib-quality-levels": "^2.0.9",
|
||||
"videojs-http-source-selector": "^1.1.6",
|
||||
"videojs-replay": "^1.1.0",
|
||||
"videojs-vtt-thumbnails": "0.0.13",
|
||||
"vue": "^2.6.11",
|
||||
"vue-electron": "^1.0.6",
|
||||
"vue-router": "^3.1.5",
|
||||
|
@ -32,6 +36,7 @@
|
|||
"youtube-comments-fetch": "^1.0.1",
|
||||
"youtube-comments-task": "^1.3.14",
|
||||
"youtube-suggest": "^1.1.0",
|
||||
"yt-xml2srt": "^1.1.0",
|
||||
"ytdl-core": "^1.0.7",
|
||||
"ytpl": "^0.1.20",
|
||||
"ytsr": "^0.1.10"
|
||||
|
|
|
@ -5,4 +5,5 @@
|
|||
|
||||
.ftVideoPlayer {
|
||||
width: 85%;
|
||||
max-height: 50vh;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ import FtCard from '../ft-card/ft-card.vue'
|
|||
// I haven't decided which video player I want to use
|
||||
// Need to expirement with both of them to see which one will work best.
|
||||
import videojs from 'video.js'
|
||||
import qualitySelector from '@silvermine/videojs-quality-selector'
|
||||
import 'videojs-vtt-thumbnails'
|
||||
import 'videojs-contrib-quality-levels'
|
||||
import 'videojs-http-source-selector'
|
||||
// import mediaelement from 'mediaelement'
|
||||
|
||||
export default Vue.extend({
|
||||
|
@ -12,21 +16,60 @@ export default Vue.extend({
|
|||
'ft-card': FtCard
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
sourceList: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
dashSrc: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
hlsSrc: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
captionList: {
|
||||
type: Array,
|
||||
default: () => { return [] }
|
||||
},
|
||||
src: {
|
||||
storyboardSrc: {
|
||||
type: String,
|
||||
required: true
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
id: '',
|
||||
player: null,
|
||||
useDash: false,
|
||||
useHls: false,
|
||||
activeSourceList: [],
|
||||
dataSetup: {
|
||||
aspectRatio: '16:9',
|
||||
nativeTextTracks: false,
|
||||
plugins: {},
|
||||
controlBar: {
|
||||
children: [
|
||||
'playToggle',
|
||||
'volumePanel',
|
||||
'currentTimeDisplay',
|
||||
'timeDivider',
|
||||
'durationDisplay',
|
||||
'progressControl',
|
||||
'liveDisplay',
|
||||
'seekToLive',
|
||||
'remainingTimeDisplay',
|
||||
'customControlSpacer',
|
||||
'playbackRateMenuButton',
|
||||
'chaptersButton',
|
||||
'descriptionsButton',
|
||||
'subsCapsButton',
|
||||
'audioTrackButton',
|
||||
'QualitySelector',
|
||||
'pictureInPictureToggle',
|
||||
'fullscreenToggle'
|
||||
]
|
||||
},
|
||||
playbackRates: [
|
||||
0.25,
|
||||
0.5,
|
||||
|
@ -47,21 +90,79 @@ export default Vue.extend({
|
|||
computed: {
|
||||
listType: function () {
|
||||
return this.$store.getters.getListType
|
||||
},
|
||||
|
||||
videoFormatPreference: function () {
|
||||
return this.$store.getters.getVideoFormatPreference
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.id = this._uid
|
||||
setTimeout(this.initializePlayer, 100)
|
||||
|
||||
this.determineFormatType()
|
||||
},
|
||||
methods: {
|
||||
initializePlayer: function () {
|
||||
console.log(this.id)
|
||||
const videoPlayer = document.getElementById(this.id)
|
||||
console.log(videoPlayer)
|
||||
if (videoPlayer !== null) {
|
||||
this.player = videojs(videoPlayer)
|
||||
console.log(videojs.players)
|
||||
if (!this.useDash && !this.useHls) {
|
||||
qualitySelector(videojs, { showQualitySelectionLabelInControlBar: true })
|
||||
}
|
||||
|
||||
this.player = videojs(videoPlayer)
|
||||
|
||||
this.player.vttThumbnails({
|
||||
src: this.storyboardSrc
|
||||
})
|
||||
|
||||
if (this.useDash) {
|
||||
this.dataSetup.plugins.httpSourceSelector = {
|
||||
default: 'auto'
|
||||
}
|
||||
|
||||
this.player.httpSourceSelector()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
determineFormatType: function () {
|
||||
if (this.hlsSrc === null && this.dashSrc !== null && this.videoFormatPreference === 'dash') {
|
||||
this.enableDashFormat()
|
||||
} else {
|
||||
this.enableLegacyFormat()
|
||||
}
|
||||
},
|
||||
|
||||
enableDashFormat: function () {
|
||||
if (this.dashSrc === null) {
|
||||
console.log('No dash format available.')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('using dash format')
|
||||
|
||||
this.useDash = true
|
||||
this.useHls = false
|
||||
this.activeSourceList = this.dashSrc
|
||||
|
||||
console.log(this.activeSourceList)
|
||||
|
||||
setTimeout(this.initializePlayer, 1000)
|
||||
},
|
||||
|
||||
enableLegacyFormat: function () {
|
||||
if (this.sourceList.length === 0) {
|
||||
console.log('No sources available')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('using legacy format')
|
||||
|
||||
this.useDash = false
|
||||
this.useHls = false
|
||||
this.activeSourceList = this.sourceList
|
||||
|
||||
setTimeout(this.initializePlayer, 100)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -3,15 +3,25 @@
|
|||
<video
|
||||
:id="id"
|
||||
class="ftVideoPlayer video-js vjs-default-skin"
|
||||
width="800"
|
||||
height="600"
|
||||
controls
|
||||
preload="auto"
|
||||
:data-setup="JSON.stringify(dataSetup)"
|
||||
>
|
||||
<source
|
||||
:src="src"
|
||||
type="video/mp4"
|
||||
v-for="(source, index) in activeSourceList"
|
||||
:key="index + '_source'"
|
||||
:src="source.url"
|
||||
:type="source.type || source.mimeType"
|
||||
:label="source.qualityLabel"
|
||||
/>
|
||||
<track
|
||||
v-for="(caption, index) in captionList"
|
||||
:key="index + '_caption'"
|
||||
kind="subtitles"
|
||||
:src="caption.baseUrl || caption.url"
|
||||
:srclang="caption.languageCode"
|
||||
:label="caption.label || caption.name.simpleText"
|
||||
:type="caption.type"
|
||||
>
|
||||
</video>
|
||||
</div>
|
||||
|
|
|
@ -8,11 +8,22 @@
|
|||
color: var(--title-color);
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.comment {
|
||||
padding: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hideComments {
|
||||
font-size: 13px;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
color: var(--title-color);
|
||||
}
|
||||
|
||||
.commentThumbnail {
|
||||
float: left;
|
||||
width: 60px;
|
||||
|
@ -47,7 +58,7 @@
|
|||
|
||||
.commentMoreReplies {
|
||||
font-size: 11px;
|
||||
margin-left: 110px;
|
||||
margin-left: 120px;
|
||||
margin-top: -25px;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
|
|
|
@ -18,6 +18,7 @@ export default Vue.extend({
|
|||
data: function () {
|
||||
return {
|
||||
isLoading: false,
|
||||
showComments: false,
|
||||
nextPageToken: null,
|
||||
commentData: []
|
||||
}
|
||||
|
@ -87,6 +88,7 @@ export default Vue.extend({
|
|||
this.commentData = this.commentData.concat(commentData)
|
||||
this.nextPageToken = p.nextPageToken
|
||||
this.isLoading = false
|
||||
this.showComments = true
|
||||
})
|
||||
},
|
||||
|
||||
|
@ -127,6 +129,7 @@ export default Vue.extend({
|
|||
this.commentData = this.commentData.concat(commentData)
|
||||
this.nextPageToken = response.continuation
|
||||
this.isLoading = false
|
||||
this.showComments = true
|
||||
}).catch((xhr) => {
|
||||
console.log('found an error')
|
||||
console.log(xhr)
|
||||
|
|
|
@ -10,13 +10,26 @@
|
|||
>
|
||||
Click to view comments
|
||||
</h4>
|
||||
<h4
|
||||
v-if="commentData.length > 0 && !isLoading && !showComments"
|
||||
class="getCommentsTitle"
|
||||
@click="showComments = true"
|
||||
>
|
||||
Click to view comments
|
||||
</h4>
|
||||
<h3
|
||||
v-if="commentData.length > 0 && !isLoading"
|
||||
v-if="commentData.length > 0 && !isLoading && showComments"
|
||||
>
|
||||
Comments
|
||||
<span
|
||||
class="hideComments"
|
||||
@click="showComments = false"
|
||||
>
|
||||
Hide Comments
|
||||
</span>
|
||||
</h3>
|
||||
<div
|
||||
v-if="commentData.length > 0"
|
||||
v-if="commentData.length > 0 && showComments"
|
||||
>
|
||||
<div
|
||||
v-for="(comment, index) in commentData"
|
||||
|
@ -87,8 +100,15 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="showComments && !isLoading"
|
||||
>
|
||||
<h3 class="center">
|
||||
There are no comments available for this video.
|
||||
</h3>
|
||||
</div>
|
||||
<h4
|
||||
v-if="commentData.length > 0 && !isLoading"
|
||||
v-if="commentData.length > 0 && !isLoading && showComments"
|
||||
class="getMoreComments"
|
||||
@click="getCommentData"
|
||||
>
|
||||
|
|
|
@ -83,7 +83,14 @@
|
|||
position: absolute;
|
||||
right: 15px;
|
||||
top: 20px;
|
||||
width: 350px;
|
||||
width: 550px;
|
||||
}
|
||||
|
||||
.theatreModeButton {
|
||||
height: 30px;
|
||||
line-height: 10px;
|
||||
position: relative;
|
||||
bottom: 5px;
|
||||
}
|
||||
|
||||
.formatTypeDropdown {
|
||||
|
@ -93,3 +100,13 @@
|
|||
.shareDropdown {
|
||||
width: 175px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1700px) {
|
||||
.theatreModeButton {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.videoOptions {
|
||||
width: 350px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
/>
|
||||
</div>
|
||||
<ft-flex-box class="videoOptions">
|
||||
<ft-button
|
||||
label="Toggle Theatre Mode"
|
||||
class="theatreModeButton"
|
||||
@click="$emit('theatreMode')"
|
||||
/>
|
||||
<ft-list-dropdown
|
||||
:title="formatTypeLabel"
|
||||
:label-names="formatTypeNames"
|
||||
|
|
|
@ -14,6 +14,7 @@ const state = {
|
|||
useClickBaitRemover: true,
|
||||
clickBaitRemoverPreference: '',
|
||||
backendFallback: true,
|
||||
videoFormatPreference: 'dash',
|
||||
autoplay: true,
|
||||
useTor: false,
|
||||
history: true,
|
||||
|
@ -61,6 +62,10 @@ const getters = {
|
|||
|
||||
getClickBaitRemoverPreference: () => {
|
||||
return state.clickBaitRemoverPreference
|
||||
},
|
||||
|
||||
getVideoFormatPreference: () => {
|
||||
return state.videoFormatPreference
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -890,7 +890,7 @@ body.vjs-full-window {
|
|||
position: absolute;
|
||||
top: -3.4em;
|
||||
visibility: hidden;
|
||||
z-index: 1;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.video-js .vjs-progress-holder:focus .vjs-time-tooltip {
|
||||
|
@ -1292,7 +1292,7 @@ video::-webkit-media-text-track-display {
|
|||
.vjs-playback-rate > .vjs-menu-button,
|
||||
.vjs-playback-rate .vjs-playback-rate-value {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: 30%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -1301,7 +1301,6 @@ video::-webkit-media-text-track-display {
|
|||
.vjs-playback-rate .vjs-playback-rate-value {
|
||||
pointer-events: none;
|
||||
font-size: 1.2em;
|
||||
line-height: 2.8;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
@ -1895,7 +1894,7 @@ video::-webkit-media-text-track-display {
|
|||
background-color: transparent;
|
||||
width: 5.5em;
|
||||
left: 1.5em;
|
||||
padding-bottom: .5em
|
||||
padding-bottom: .5em;
|
||||
}
|
||||
|
||||
.video-js .vjs-menu-button-popup .vjs-menu .vjs-menu-item,.video-js .vjs-menu-button-popup .vjs-menu .vjs-menu-title {
|
||||
|
@ -1943,3 +1942,42 @@ video::-webkit-media-text-track-display {
|
|||
.video-js .vjs-load-progress {
|
||||
background: rgba(255,255,255,0.3);
|
||||
}
|
||||
|
||||
.vjs-quality-selector .vjs-menu-button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.vjs-quality-selector .vjs-quality-selector-icon {
|
||||
font-family: 'VideoJS';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.vjs-quality-selector .vjs-quality-selector-icon:before {
|
||||
content: '\f110';
|
||||
}
|
||||
|
||||
.vjs-quality-changing .vjs-big-play-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.vjs-quality-changing .vjs-control-bar {
|
||||
display: flex;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.video-js .vjs-vtt-thumbnails {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.video-js .vjs-vtt-thumbnail-display {
|
||||
position: absolute;
|
||||
transition: transform .1s, opacity .2s;
|
||||
bottom: 20px;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 0 7px rgba(0,0,0,.6);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.theatreWatchVideo {
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
width: 85%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.videoPlayer {
|
||||
width: calc(65% + 30px);
|
||||
float: left;
|
||||
|
@ -13,6 +20,13 @@
|
|||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.theatrePlayer {
|
||||
width: calc(85% + 30px);
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.watchVideoRecommendations {
|
||||
width: 27%;
|
||||
max-width: 425px;
|
||||
|
@ -23,6 +37,14 @@
|
|||
right: 10px;
|
||||
}
|
||||
|
||||
.theatreRecommendations {
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
width: 85%;
|
||||
max-width: none;
|
||||
position: static;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1700px) {
|
||||
.watchVideo {
|
||||
float: none;
|
||||
|
|
|
@ -24,9 +24,11 @@ export default Vue.extend({
|
|||
return {
|
||||
isLoading: false,
|
||||
firstLoad: true,
|
||||
useTheatreMode: true,
|
||||
showDashPlayer: true,
|
||||
showLegacyPlayer: false,
|
||||
showYouTubeNoCookieEmbed: false,
|
||||
proxyVideos: false,
|
||||
videoId: '',
|
||||
videoTitle: '',
|
||||
videoDescription: '',
|
||||
|
@ -39,9 +41,10 @@ export default Vue.extend({
|
|||
channelId: '',
|
||||
channelSubscriptionCountText: '',
|
||||
videoPublished: 0,
|
||||
videoUrl360p: '',
|
||||
videoUrl720p: '',
|
||||
videoStoryboardSrc: '',
|
||||
audioUrl: '',
|
||||
videoSourceList: [],
|
||||
captionSourceList: [],
|
||||
recommendedVideos: []
|
||||
}
|
||||
},
|
||||
|
@ -64,6 +67,14 @@ export default Vue.extend({
|
|||
|
||||
youtubeNoCookieEmbeddedFrame: function () {
|
||||
return `<iframe width='560' height='315' src='https://www.youtube-nocookie.com/embed/${this.videoId}?rel=0' frameborder='0' allow='autoplay; encrypted-media' allowfullscreen></iframe>`
|
||||
},
|
||||
|
||||
dashSrc: function () {
|
||||
return {
|
||||
url: `${this.invidiousInstance}/api/manifest/dash/${this.videoId}.mpd`,
|
||||
type: 'application/dash+xml',
|
||||
label: 'Dash'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -85,6 +96,11 @@ export default Vue.extend({
|
|||
},
|
||||
mounted: function () {
|
||||
this.videoId = this.$route.params.id
|
||||
this.videoStoryboardSrc = `${this.invidiousInstance}/api/v1/storyboards/${this.videoId}?height=90`
|
||||
|
||||
if (this.proxyVideos) {
|
||||
this.dashSrc = this.dashSrc + '?local=true'
|
||||
}
|
||||
|
||||
switch (this.backendPreference) {
|
||||
case 'local':
|
||||
|
@ -96,6 +112,10 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
toggleTheatreMode: function () {
|
||||
this.useTheatreMode = !this.useTheatreMode
|
||||
},
|
||||
|
||||
getVideoInformationLocal: function () {
|
||||
if (this.firstLoad) {
|
||||
this.isLoading = true
|
||||
|
@ -112,8 +132,45 @@ export default Vue.extend({
|
|||
this.videoPublished = result.published
|
||||
this.videoDescription = result.player_response.videoDetails.shortDescription
|
||||
this.recommendedVideos = result.related_videos
|
||||
this.videoSourceList = result.player_response.streamingData.formats
|
||||
|
||||
this.videoUrl720p = result.player_response.streamingData.formats[1].url
|
||||
// The response provides a storyboard, however it returns a 403 error.
|
||||
// Uncomment this line if that ever changes.
|
||||
// this.videoStoryboardSrc = result.player_response.storyboards.playerStoryboardSpecRenderer.spec
|
||||
|
||||
this.captionSourceList = result.player_response.captions.playerCaptionsTracklistRenderer.captionTracks
|
||||
this.captionSourceList = this.captionSourceList.map((caption) => {
|
||||
caption.baseUrl = `${this.invidiousInstance}/api/v1/captions/${this.videoId}?label=${encodeURI(caption.name.simpleText)}`
|
||||
|
||||
return caption
|
||||
})
|
||||
|
||||
// TODO: The response returns the captions of the video, however they're returned
|
||||
// in XML / TTML. I haven't found a way to properly convert this for use.
|
||||
// There may be another URL that we can use to grab an appropriate format as well.
|
||||
// Video.js requires that the captions are returned in .vtt format. The below code
|
||||
// Converts it to .srt which may work, but I can't get the player to accept the data.
|
||||
|
||||
// this.captionSourceList = this.captionSourceList.map((caption) => {
|
||||
// caption.type = 'application/ttml+xml'
|
||||
// caption.dataSource = 'local'
|
||||
//
|
||||
// $.get(caption.baseUrl, (response) => {
|
||||
// console.log('response')
|
||||
// console.log(response)
|
||||
// console.log()
|
||||
// xml2srt.Parse(new XMLSerializer().serializeToString(response))
|
||||
// .then(srt => {
|
||||
// caption.track = srt
|
||||
// }).catch(err => console.log(`Error while converting XML to SRT : ${err}`))
|
||||
// }).fail((xhr, textStatus, error) => {
|
||||
// console.log(xhr)
|
||||
// console.log(textStatus)
|
||||
// console.log(error)
|
||||
// })
|
||||
//
|
||||
// return caption
|
||||
// })
|
||||
|
||||
this.isLoading = false
|
||||
}).catch((err) => {
|
||||
|
@ -147,8 +204,13 @@ export default Vue.extend({
|
|||
this.videoPublished = result.published * 1000
|
||||
this.videoDescriptionHtml = result.descriptionHtml
|
||||
this.recommendedVideos = result.recommendedVideos
|
||||
|
||||
this.videoUrl720p = result.formatStreams[0].url
|
||||
this.videoSourceList = result.formatStreams.reverse()
|
||||
this.captionSourceList = result.captions.map((caption) => {
|
||||
caption.url = this.invidiousInstance + caption.url
|
||||
caption.type = ''
|
||||
caption.dataSource = 'invidious'
|
||||
return caption
|
||||
})
|
||||
|
||||
this.isLoading = false
|
||||
}).catch((err) => {
|
||||
|
|
|
@ -6,8 +6,12 @@
|
|||
/>
|
||||
<ft-video-player
|
||||
v-if="!isLoading"
|
||||
:src="videoUrl720p"
|
||||
:dash-src="dashSrc"
|
||||
:source-list="videoSourceList"
|
||||
:caption-list="captionSourceList"
|
||||
:storyboard-src="videoStoryboardSrc"
|
||||
class="videoPlayer"
|
||||
:class="{ theatrePlayer: useTheatreMode }"
|
||||
/>
|
||||
<watch-video-info
|
||||
v-if="!isLoading"
|
||||
|
@ -20,7 +24,9 @@
|
|||
:like-count="videoLikeCount"
|
||||
:dislike-count="videoDislikeCount"
|
||||
:view-count="videoViewCount"
|
||||
@theatreMode="toggleTheatreMode"
|
||||
class="watchVideo"
|
||||
:class="{ theatreWatchVideo: useTheatreMode }"
|
||||
/>
|
||||
<watch-video-description
|
||||
v-if="!isLoading"
|
||||
|
@ -28,16 +34,19 @@
|
|||
:description="videoDescription"
|
||||
:description-html="videoDescriptionHtml"
|
||||
class="watchVideo"
|
||||
:class="{ theatreWatchVideo: useTheatreMode }"
|
||||
/>
|
||||
<watch-video-comments
|
||||
v-if="!isLoading"
|
||||
:id="videoId"
|
||||
class="watchVideo"
|
||||
:class="{ theatreWatchVideo: useTheatreMode }"
|
||||
/>
|
||||
<watch-video-recommendations
|
||||
v-if="!isLoading"
|
||||
:data="recommendedVideos"
|
||||
class="watchVideoRecommendations"
|
||||
:class="{ theatreRecommendations: useTheatreMode }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue