Merge pull request #78 from GilgusMaximus/Storyboards
Local Storyboard extraction and VTT File Generation
This commit is contained in:
commit
2f939182dc
|
@ -230,9 +230,9 @@ export default Vue.extend({
|
||||||
this.player.volume(this.volume)
|
this.player.volume(this.volume)
|
||||||
this.player.playbackRate(this.defaultPlayback)
|
this.player.playbackRate(this.defaultPlayback)
|
||||||
|
|
||||||
// this.player.vttThumbnails({
|
this.player.vttThumbnails({
|
||||||
// src: this.storyboardSrc
|
src: this.videoStoryboardSrc
|
||||||
// })
|
})
|
||||||
|
|
||||||
if (this.useDash) {
|
if (this.useDash) {
|
||||||
this.dataSetup.plugins.httpSourceSelector = {
|
this.dataSetup.plugins.httpSourceSelector = {
|
||||||
|
|
|
@ -291,9 +291,29 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The response provides a storyboard, however it returns a 403 error.
|
const templateUrl = result.player_response.storyboards.playerStoryboardSpecRenderer.spec
|
||||||
// Uncomment this line if that ever changes.
|
const storyboards = templateUrl.split('|')
|
||||||
// this.videoStoryboardSrc = result.player_response.storyboards.playerStoryboardSpecRenderer.spec
|
const storyboardArray = []
|
||||||
|
// Second storyboard: L1/M0 - Third storyboard: L2/M0 - Fourth: L3/M0
|
||||||
|
|
||||||
|
const baseUrl = storyboards.shift()
|
||||||
|
// remove the first link because it does not work
|
||||||
|
storyboards.splice(0, 1)
|
||||||
|
storyboards.forEach((storyboard, i) => {
|
||||||
|
const [width, height, count, sWidth, sHeight, interval, _, sigh] = storyboard.split('#')
|
||||||
|
storyboardArray.push({
|
||||||
|
url: baseUrl.replace('$L', i + 1).replace('$N', 'M0').replace(/<\/?sub>/g, '') + '&sigh=' + sigh,
|
||||||
|
width: Number(width), // Width of one sub image
|
||||||
|
height: Number(height), // Height of one sub image
|
||||||
|
sWidth: Number(sWidth), // Number of images vertically (if full)
|
||||||
|
sHeight: Number(sHeight), // Number of images horizontally (if full)
|
||||||
|
count: Number(count), // Number of images total
|
||||||
|
interval: Number(interval) // How long one image is used
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// TODO MAKE A VARIABLE WHICH CAN CHOOSE BETWEEN STROYBOARD ARRAY ELEMENTS
|
||||||
|
const vttFile = this.buildVTTFileLocally(storyboardArray[1])
|
||||||
|
this.videoStoryboardSrc = vttFile
|
||||||
|
|
||||||
this.captionSourceList =
|
this.captionSourceList =
|
||||||
result.player_response.captions &&
|
result.player_response.captions &&
|
||||||
|
@ -348,6 +368,62 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
padNumberWithLeadingZeros: function(number, length) {
|
||||||
|
let numberString = number.toString()
|
||||||
|
while (numberString.length < length) {
|
||||||
|
numberString = '0' + numberString
|
||||||
|
}
|
||||||
|
return numberString
|
||||||
|
},
|
||||||
|
|
||||||
|
buildVTTFileLocally: function(Storyboard) {
|
||||||
|
let vttString = 'WEBVTT\n\n'
|
||||||
|
// how many images are in one image
|
||||||
|
const numberOfSubImagesPerImage = Storyboard.sWidth * Storyboard.sHeight
|
||||||
|
// the number of storyboard images
|
||||||
|
const numberOfImages = Math.ceil(Storyboard.count / numberOfSubImagesPerImage)
|
||||||
|
const intervalInSeconds = Storyboard.interval / 1000
|
||||||
|
let currentUrl = Storyboard.url
|
||||||
|
let startHours = 0
|
||||||
|
let startMinutes = 0
|
||||||
|
let startSeconds = 0
|
||||||
|
let endHours = 0
|
||||||
|
let endMinutes = 0
|
||||||
|
let endSeconds = intervalInSeconds
|
||||||
|
for (let i = 0; i < numberOfImages; i++) {
|
||||||
|
let xCoord = 0
|
||||||
|
let yCoord = 0
|
||||||
|
for (let j = 0; j < numberOfSubImagesPerImage; j++) {
|
||||||
|
// add the timestamp information
|
||||||
|
vttString += `${this.padNumberWithLeadingZeros(startHours, 2)}:${this.padNumberWithLeadingZeros(startMinutes, 2)}:${this.padNumberWithLeadingZeros(startSeconds, 2)}.000 --> ${this.padNumberWithLeadingZeros(endHours, 2)}:${this.padNumberWithLeadingZeros(endMinutes, 2)}:${this.padNumberWithLeadingZeros(endSeconds, 2)}.000\n`
|
||||||
|
// add the current image url as well as the x, y, width, height information
|
||||||
|
vttString += currentUrl + `#xywh=${xCoord},${yCoord},${Storyboard.width},${Storyboard.height}\n\n`
|
||||||
|
// update the variables
|
||||||
|
startHours = endHours
|
||||||
|
startMinutes = endMinutes
|
||||||
|
startSeconds = endSeconds
|
||||||
|
endSeconds += intervalInSeconds
|
||||||
|
if (endSeconds >= 60) {
|
||||||
|
endSeconds -= 60
|
||||||
|
endMinutes += 1
|
||||||
|
}
|
||||||
|
if (endMinutes >= 60) {
|
||||||
|
endMinutes -= 60
|
||||||
|
endHours += 1
|
||||||
|
}
|
||||||
|
// x coordinate can only be smaller than the width of one subimage * the number of subimages per row
|
||||||
|
xCoord = (xCoord + Storyboard.width) % (Storyboard.width * Storyboard.sWidth)
|
||||||
|
// only if the x coordinate is , so in a new row, we have to update the y coordinate
|
||||||
|
if (xCoord === 0) {
|
||||||
|
yCoord += Storyboard.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// make sure that there is no value like M0 or M1 in the parameters that gets replaced
|
||||||
|
currentUrl = currentUrl.replace('M' + i.toString() + '.jpg', 'M' + (i + 1).toString() + '.jpg')
|
||||||
|
}
|
||||||
|
return vttString
|
||||||
|
},
|
||||||
|
|
||||||
getVideoInformationInvidious: function() {
|
getVideoInformationInvidious: function() {
|
||||||
if (this.firstLoad) {
|
if (this.firstLoad) {
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
|
|
|
@ -106,6 +106,7 @@ Settings:
|
||||||
Fallback to Non-Preferred Backend on Failure: Falle zu nicht-präferiertem System bei Fehlschlag zurück
|
Fallback to Non-Preferred Backend on Failure: Falle zu nicht-präferiertem System bei Fehlschlag zurück
|
||||||
Enable Search Suggestions: Aktiviere Suchvorschläge
|
Enable Search Suggestions: Aktiviere Suchvorschläge
|
||||||
Default Landing Page: Standardseite
|
Default Landing Page: Standardseite
|
||||||
|
|
||||||
Locale Preference: Locale Preference
|
Locale Preference: Locale Preference
|
||||||
Preferred API Backend:
|
Preferred API Backend:
|
||||||
Preferred API Backend: Präferiertes API System
|
Preferred API Backend: Präferiertes API System
|
||||||
|
|
Loading…
Reference in New Issue