diff options
| author | Omar Roth <omarroth@protonmail.com> | 2019-05-02 14:20:19 -0500 |
|---|---|---|
| committer | Omar Roth <omarroth@protonmail.com> | 2019-05-02 14:36:32 -0500 |
| commit | 6d92775ab546969230366b5bddbe51d36f73e7c7 (patch) | |
| tree | d35430170d535d7e0dd5454e6edce3471837b75f /src | |
| parent | 1a9360ca754e684947df566ad8d3c6f0deec8664 (diff) | |
| download | invidious-6d92775ab546969230366b5bddbe51d36f73e7c7.tar.gz invidious-6d92775ab546969230366b5bddbe51d36f73e7c7.tar.bz2 invidious-6d92775ab546969230366b5bddbe51d36f73e7c7.zip | |
Add video previews
Diffstat (limited to 'src')
| -rw-r--r-- | src/invidious.cr | 89 | ||||
| -rw-r--r-- | src/invidious/videos.cr | 7 | ||||
| -rw-r--r-- | src/invidious/views/components/player.ecr | 4 | ||||
| -rw-r--r-- | src/invidious/views/components/player_sources.ecr | 2 | ||||
| -rw-r--r-- | src/invidious/views/licenses.ecr | 14 |
5 files changed, 112 insertions, 4 deletions
diff --git a/src/invidious.cr b/src/invidious.cr index 1d2e63b2..1399c124 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -3053,6 +3053,86 @@ get "/api/v1/stats" do |env| statistics.to_json end +# YouTube provides "storyboards", which are sprites containing of x * y +# preview thumbnails for individual scenes in a video. +# See https://support.jwplayer.com/articles/how-to-add-preview-thumbnails +get "/api/v1/storyboards/:id" do |env| + locale = LOCALES[env.get("preferences").as(Preferences).locale]? + + env.response.content_type = "application/json" + + id = env.params.url["id"] + region = env.params.query["region"]? + + client = make_client(YT_URL) + begin + video = get_video(id, PG_DB, proxies, region: region) + rescue ex : VideoRedirect + next env.redirect "/api/v1/storyboards/#{ex.message}" + rescue ex + env.response.status_code = 500 + next + end + + storyboards = video.storyboards + + width = env.params.query["width"]? + height = env.params.query["height"]? + + if !width && !height + response = JSON.build do |json| + json.object do + json.field "storyboards" do + generate_storyboards(json, id, storyboards, config, Kemal.config) + end + end + end + + next response + end + + env.response.content_type = "text/vtt" + + storyboard = storyboards.select { |storyboard| width == "#{storyboard[:width]}" || height == "#{storyboard[:height]}" } + + if storyboard.empty? + env.response.status_code = 404 + next + else + storyboard = storyboard[0] + end + + webvtt = <<-END_VTT + WEBVTT + + + END_VTT + + start_time = 0.milliseconds + end_time = storyboard[:interval].milliseconds + + storyboard[:storyboard_count].times do |i| + host_url = make_host_url(config, Kemal.config) + url = storyboard[:url].gsub("$M", i).gsub("https://i9.ytimg.com", host_url) + + storyboard[:storyboard_height].times do |j| + storyboard[:storyboard_width].times do |k| + webvtt += <<-END_CUE + #{start_time}.000 --> #{end_time}.000 + #{url}#xywh=#{storyboard[:width] * k},#{storyboard[:height] * j},#{storyboard[:width]},#{storyboard[:height]} + + + END_CUE + + start_time += storyboard[:interval].milliseconds + end_time += storyboard[:interval].milliseconds + end + end + end + + webvtt +end + get "/api/v1/captions/:id" do |env| locale = LOCALES[env.get("preferences").as(Preferences).locale]? @@ -3145,7 +3225,7 @@ get "/api/v1/captions/:id" do |env| text = "<v #{md["name"]}>#{md["text"]}</v>" end - webvtt = webvtt + <<-END_CUE + webvtt += <<-END_CUE #{start_time} --> #{end_time} #{text} @@ -5054,6 +5134,13 @@ get "/ggpht/*" do |env| end end +options "/sb/:id/:storyboard/:index" do |env| + env.response.headers.delete("Content-Type") + env.response.headers["Access-Control-Allow-Origin"] = "*" + env.response.headers["Access-Control-Allow-Methods"] = "GET, OPTIONS" + env.response.headers["Access-Control-Allow-Headers"] = "Content-Type, Range" +end + get "/sb/:id/:storyboard/:index" do |env| id = env.params.url["id"] storyboard = env.params.url["storyboard"] diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index 755ee4d7..9a199fad 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -281,7 +281,7 @@ struct Video generate_thumbnails(json, self.id, config, kemal_config) end json.field "storyboards" do - generate_storyboards(json, self.storyboards, config, kemal_config) + generate_storyboards(json, self.id, self.storyboards, config, kemal_config) end description_html, description = html_to_content(self.description) @@ -1348,11 +1348,12 @@ def generate_thumbnails(json, id, config, kemal_config) end end -def generate_storyboards(json, storyboards, config, kemal_config) +def generate_storyboards(json, id, storyboards, config, kemal_config) json.array do storyboards.each do |storyboard| json.object do - json.field "url", storyboard[:url] + json.field "url", "/api/v1/storyboards/#{id}?width=#{storyboard[:width]}&height=#{storyboard[:height]}" + json.field "templateUrl", storyboard[:url] json.field "width", storyboard[:width] json.field "height", storyboard[:height] json.field "count", storyboard[:count] diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index 6ad70033..3afa2af8 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -217,6 +217,10 @@ if (bpb) { player.httpSourceSelector(); <% end %> +player.vttThumbnails({ + src: 'api/v1/storyboards/<%= video.id %>?height=90' +}); + <% if !params.listen && params.annotations %> var video_container = document.getElementById('player'); let xhr = new XMLHttpRequest(); diff --git a/src/invidious/views/components/player_sources.ecr b/src/invidious/views/components/player_sources.ecr index f446248e..2fbd41b0 100644 --- a/src/invidious/views/components/player_sources.ecr +++ b/src/invidious/views/components/player_sources.ecr @@ -2,12 +2,14 @@ <link rel="stylesheet" href="/css/videojs-http-source-selector.css"> <link rel="stylesheet" href="/css/videojs.markers.min.css"> <link rel="stylesheet" href="/css/videojs-share.css"> +<link rel="stylesheet" href="/css/videojs-vtt-thumbnails.css"> <script src="/js/video.min.js"></script> <script src="/js/videojs-contrib-quality-levels.min.js"></script> <script src="/js/videojs-http-source-selector.min.js"></script> <script src="/js/videojs.hotkeys.min.js"></script> <script src="/js/videojs-markers.min.js"></script> <script src="/js/videojs-share.min.js"></script> +<script src="/js/videojs-vtt-thumbnails.min.js"></script> <% if params.annotations %> <link rel="stylesheet" href="/css/videojs-youtube-annotations.min.css"> diff --git a/src/invidious/views/licenses.ecr b/src/invidious/views/licenses.ecr index bab7762a..8561dee9 100644 --- a/src/invidious/views/licenses.ecr +++ b/src/invidious/views/licenses.ecr @@ -95,6 +95,20 @@ <tr> <td> + <a href="/js/videojs-vtt-thumbnails.min.js">videojs-vtt-thumbnails.min.js</a> + </td> + + <td> + <a href="http://www.jclark.com/xml/copying.txt">Expat</a> + </td> + + <td> + <a href="https://github.com/chrisboustead/videojs-vtt-thumbnails"><%= translate(locale, "source") %></a> + </td> + </tr> + + <tr> + <td> <a href="/js/videojs-youtube-annotations.min.js">videojs-youtube-annotations.min.js</a> </td> |
