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: {
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'

View File

@ -67,6 +67,16 @@
theme="secondary"
@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
v-if="!isUpcoming"
:title="$t('Change Format.Change Video Formats')"

View File

@ -69,6 +69,7 @@ export default Vue.extend({
audioSourceList: [],
captionSourceList: [],
recommendedVideos: [],
downloadLinks: [],
watchingPlaylist: false,
playlistId: '',
playNextTimeout: null
@ -138,6 +139,7 @@ export default Vue.extend({
this.activeFormat = this.defaultVideoFormat
this.videoStoryboardSrc = ''
this.captionSourceList = []
this.downloadLinks = []
this.checkIfPlaylist()
@ -311,6 +313,27 @@ export default Vue.extend({
this.videoLengthSeconds = parseInt(result.videoDetails.lengthSeconds)
if (result.player_response.streamingData !== undefined) {
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 {
// 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) => {

View File

@ -75,6 +75,7 @@
:view-count="videoViewCount"
:get-timestamp="getTimestamp"
:is-upcoming="isUpcoming"
:download-links="downloadLinks"
class="watchVideo"
:class="{ theatreWatchVideo: useTheatreMode }"
@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
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