Add Download links to videos

This commit is contained in:
Preston 2020-10-08 15:01:46 -04:00
parent 5d63bb7f01
commit 5cb71a48f2
5 changed files with 88 additions and 6 deletions

View File

@ -66,6 +66,10 @@ export default Vue.extend({
isUpcoming: { isUpcoming: {
type: Boolean, type: Boolean,
required: true required: true
},
downloadLinks: {
type: Array,
required: true
} }
}, },
data: function () { data: function () {
@ -99,6 +103,26 @@ export default Vue.extend({
return this.$store.getters.getHideRecommendedVideos 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 () { formatTypeNames: function () {
return [ return [
this.$t('Change Format.Use Dash Formats').toUpperCase(), this.$t('Change Format.Use Dash Formats').toUpperCase(),
@ -153,12 +177,6 @@ export default Vue.extend({
const dateSplit = date.toDateString().split(' ') const dateSplit = date.toDateString().split(' ')
const localeDateString = `Video.Published.${dateSplit[1]}` const localeDateString = `Video.Published.${dateSplit[1]}`
return `${this.$t(localeDateString)} ${dateSplit[2]}, ${dateSplit[3]}` return `${this.$t(localeDateString)} ${dateSplit[2]}, ${dateSplit[3]}`
},
hideVideoLikesAndDislikes: function () {
return this.$store.getters.getHideVideoLikesAndDislikes
},
hideVideoViews: function () {
return this.$store.getters.getHideVideoViews
} }
}, },
methods: { methods: {
@ -252,6 +270,11 @@ export default Vue.extend({
} }
}, },
handleDownloadLink: function (url) {
const shell = require('electron').shell
shell.openExternal(url)
},
...mapActions([ ...mapActions([
'showToast', 'showToast',
'updateProfile' 'updateProfile'

View File

@ -67,6 +67,16 @@
theme="secondary" theme="secondary"
@click="$emit('theatre-mode')" @click="$emit('theatre-mode')"
/> />
<ft-icon-button
v-if="!isUpcoming && downloadLinks.length > 0"
:title="$t('Video.Download Video')"
class="option"
theme="secondary"
icon="download"
:dropdown-names="downloadLinkNames"
:dropdown-values="downloadLinkValues"
@click="handleDownloadLink"
/>
<ft-icon-button <ft-icon-button
v-if="!isUpcoming" v-if="!isUpcoming"
:title="$t('Change Format.Change Video Formats')" :title="$t('Change Format.Change Video Formats')"

View File

@ -69,6 +69,7 @@ export default Vue.extend({
audioSourceList: [], audioSourceList: [],
captionSourceList: [], captionSourceList: [],
recommendedVideos: [], recommendedVideos: [],
downloadLinks: [],
watchingPlaylist: false, watchingPlaylist: false,
playlistId: '', playlistId: '',
playNextTimeout: null playNextTimeout: null
@ -138,6 +139,7 @@ export default Vue.extend({
this.activeFormat = this.defaultVideoFormat this.activeFormat = this.defaultVideoFormat
this.videoStoryboardSrc = '' this.videoStoryboardSrc = ''
this.captionSourceList = [] this.captionSourceList = []
this.downloadLinks = []
this.checkIfPlaylist() this.checkIfPlaylist()
@ -311,6 +313,27 @@ export default Vue.extend({
this.videoLengthSeconds = parseInt(result.videoDetails.lengthSeconds) this.videoLengthSeconds = parseInt(result.videoDetails.lengthSeconds)
if (result.player_response.streamingData !== undefined) { if (result.player_response.streamingData !== undefined) {
this.videoSourceList = result.player_response.streamingData.formats.reverse() this.videoSourceList = result.player_response.streamingData.formats.reverse()
this.downloadLinks = result.formats.map((format) => {
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 { } else {
// video might be region locked or something else. This leads to no formats being available // video might be region locked or something else. This leads to no formats being available
this.showToast({ this.showToast({
@ -488,6 +511,28 @@ export default Vue.extend({
this.videoLengthSeconds = result.lengthSeconds this.videoLengthSeconds = result.lengthSeconds
this.videoSourceList = result.formatStreams.reverse() 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) => { this.audioSourceList = result.adaptiveFormats.filter((format) => {
return format.type.includes('audio') return format.type.includes('audio')
}).map((format) => { }).map((format) => {

View File

@ -75,6 +75,7 @@
:view-count="videoViewCount" :view-count="videoViewCount"
:get-timestamp="getTimestamp" :get-timestamp="getTimestamp"
:is-upcoming="isUpcoming" :is-upcoming="isUpcoming"
:download-links="downloadLinks"
class="watchVideo" class="watchVideo"
:class="{ theatreWatchVideo: useTheatreMode }" :class="{ theatreWatchVideo: useTheatreMode }"
@theatre-mode="toggleTheatreMode" @theatre-mode="toggleTheatreMode"

View File

@ -408,6 +408,9 @@ Video:
'Live Chat is currently not supported with the Invidious API. A direct connection to YouTube is required.': Live '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 Chat is currently not supported with the Invidious API. A direct connection to
YouTube is required. YouTube is required.
Download Video: Download Video
video only: video only
audio only: audio only
Audio: Audio:
Low: Low Low: Low
Medium: Medium Medium: Medium