Add Download links to videos
This commit is contained in:
parent
5d63bb7f01
commit
5cb71a48f2
|
@ -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'
|
||||||
|
|
|
@ -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')"
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue