From 5cb71a48f252f9c5f8aca9ea184bc80880aae5d4 Mon Sep 17 00:00:00 2001 From: Preston Date: Thu, 8 Oct 2020 15:01:46 -0400 Subject: [PATCH] Add Download links to videos --- .../watch-video-info/watch-video-info.js | 35 ++++++++++++--- .../watch-video-info/watch-video-info.vue | 10 +++++ src/renderer/views/Watch/Watch.js | 45 +++++++++++++++++++ src/renderer/views/Watch/Watch.vue | 1 + static/locales/en-US.yaml | 3 ++ 5 files changed, 88 insertions(+), 6 deletions(-) diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js index 1fedb560..192236ba 100644 --- a/src/renderer/components/watch-video-info/watch-video-info.js +++ b/src/renderer/components/watch-video-info/watch-video-info.js @@ -66,6 +66,10 @@ export default Vue.extend({ isUpcoming: { type: Boolean, required: true + }, + downloadLinks: { + type: Array, + required: true } }, data: function () { @@ -99,6 +103,26 @@ export default Vue.extend({ return this.$store.getters.getHideRecommendedVideos }, + hideVideoLikesAndDislikes: function () { + return this.$store.getters.getHideVideoLikesAndDislikes + }, + + hideVideoViews: function () { + return this.$store.getters.getHideVideoViews + }, + + downloadLinkNames: function () { + return this.downloadLinks.map((download) => { + return download.label + }) + }, + + downloadLinkValues: function () { + return this.downloadLinks.map((download) => { + return download.url + }) + }, + formatTypeNames: function () { return [ this.$t('Change Format.Use Dash Formats').toUpperCase(), @@ -153,12 +177,6 @@ export default Vue.extend({ const dateSplit = date.toDateString().split(' ') const localeDateString = `Video.Published.${dateSplit[1]}` return `${this.$t(localeDateString)} ${dateSplit[2]}, ${dateSplit[3]}` - }, - hideVideoLikesAndDislikes: function () { - return this.$store.getters.getHideVideoLikesAndDislikes - }, - hideVideoViews: function () { - return this.$store.getters.getHideVideoViews } }, methods: { @@ -252,6 +270,11 @@ export default Vue.extend({ } }, + handleDownloadLink: function (url) { + const shell = require('electron').shell + shell.openExternal(url) + }, + ...mapActions([ 'showToast', 'updateProfile' diff --git a/src/renderer/components/watch-video-info/watch-video-info.vue b/src/renderer/components/watch-video-info/watch-video-info.vue index 13ac8630..15af04c8 100644 --- a/src/renderer/components/watch-video-info/watch-video-info.vue +++ b/src/renderer/components/watch-video-info/watch-video-info.vue @@ -67,6 +67,16 @@ theme="secondary" @click="$emit('theatre-mode')" /> + { + const qualityLabel = format.qualityLabel || format.bitrate + const itag = format.itag + const fps = format.fps ? (format.fps + 'fps') : 'kbps' + const type = format.mimeType.match(/.*;/)[0].replace(';', '') + let label = `${qualityLabel} ${fps} - ${type}` + + if (itag !== 18 && itag !== 22) { + if (type.includes('video')) { + label += ` ${this.$t('Video.video only')}` + } else { + label += ` ${this.$t('Video.audio only')}` + } + } + const object = { + url: format.url, + label: label + } + + return object + }) } else { // video might be region locked or something else. This leads to no formats being available this.showToast({ @@ -488,6 +511,28 @@ export default Vue.extend({ this.videoLengthSeconds = result.lengthSeconds this.videoSourceList = result.formatStreams.reverse() + this.downloadLinks = result.adaptiveFormats.concat(this.videoSourceList).map((format) => { + const qualityLabel = format.qualityLabel || format.bitrate + const itag = parseInt(format.itag) + const fps = format.fps ? (format.fps + 'fps') : 'kbps' + const type = format.type.match(/.*;/)[0].replace(';', '') + let label = `${qualityLabel} ${fps} - ${type}` + + if (itag !== 18 && itag !== 22) { + if (type.includes('video')) { + label += ` ${this.$t('Video.video only')}` + } else { + label += ` ${this.$t('Video.audio only')}` + } + } + const object = { + url: format.url, + label: label + } + + return object + }).reverse() + this.audioSourceList = result.adaptiveFormats.filter((format) => { return format.type.includes('audio') }).map((format) => { diff --git a/src/renderer/views/Watch/Watch.vue b/src/renderer/views/Watch/Watch.vue index 767935a0..e75a5799 100644 --- a/src/renderer/views/Watch/Watch.vue +++ b/src/renderer/views/Watch/Watch.vue @@ -75,6 +75,7 @@ :view-count="videoViewCount" :get-timestamp="getTimestamp" :is-upcoming="isUpcoming" + :download-links="downloadLinks" class="watchVideo" :class="{ theatreWatchVideo: useTheatreMode }" @theatre-mode="toggleTheatreMode" diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index 3cab2bdc..d3522c70 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -408,6 +408,9 @@ Video: 'Live Chat is currently not supported with the Invidious API. A direct connection to YouTube is required.': Live Chat is currently not supported with the Invidious API. A direct connection to YouTube is required. + Download Video: Download Video + video only: video only + audio only: audio only Audio: Low: Low Medium: Medium