Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Videos: Use start time and end time for clips #4264

Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/invidious/routes/api/v1/videos.cr
Expand Up @@ -363,4 +363,47 @@ module Invidious::Routes::API::V1::Videos
end
end
end

def self.clips(env)
locale = env.get("preferences").as(Preferences).locale

env.response.content_type = "application/json"

clip_id = env.params.url["id"]
region = env.params.query["region"]?
proxy = {"1", "true"}.any? &.== env.params.query["local"]?

response = YoutubeAPI.resolve_url("https://www.youtube.com/clip/#{clip_id}")
return error_json(400, "Invalid clip ID") if response["error"]?

video_id = response.dig?("endpoint", "watchEndpoint", "videoId").try &.as_s
return error_json(400, "Invalid clip ID") if video_id.nil?

start_time = nil
end_time = nil
clip_title = nil

if params = response.dig?("endpoint", "watchEndpoint", "params").try &.as_s
start_time, end_time, clip_title = parse_clip_parameters(params)
end

begin
video = get_video(video_id, region: region)
rescue ex : NotFoundException
return error_json(404, ex)
rescue ex
return error_json(500, ex)
end

return JSON.build do |json|
json.object do
json.field "startTime", start_time
json.field "endTime", end_time
ChunkyProgrammer marked this conversation as resolved.
Show resolved Hide resolved
json.field "clipTitle", clip_title
json.field "video" do
Invidious::JSONify::APIv1.video(video, json, locale: locale, proxy: proxy)
end
end
end
end
end
6 changes: 6 additions & 0 deletions src/invidious/routes/watch.cr
Expand Up @@ -275,6 +275,12 @@ module Invidious::Routes::Watch
return error_template(400, "Invalid clip ID") if response["error"]?

if video_id = response.dig?("endpoint", "watchEndpoint", "videoId")
if params = response.dig?("endpoint", "watchEndpoint", "params").try &.as_s
start_time, end_time, _ = parse_clip_parameters(params)
env.params.query["start"] = start_time.to_s
env.params.query["end"] = end_time.to_s
SamantazFox marked this conversation as resolved.
Show resolved Hide resolved
end

return env.redirect "/watch?v=#{video_id}&#{env.params.query}"
else
return error_template(404, "The requested clip doesn't exist")
Expand Down
1 change: 1 addition & 0 deletions src/invidious/routing.cr
Expand Up @@ -235,6 +235,7 @@ module Invidious::Routing
get "/api/v1/captions/:id", {{namespace}}::Videos, :captions
get "/api/v1/annotations/:id", {{namespace}}::Videos, :annotations
get "/api/v1/comments/:id", {{namespace}}::Videos, :comments
get "/api/v1/clips/:id", {{namespace}}::Videos, :clips

# Feeds
get "/api/v1/trending", {{namespace}}::Feeds, :trending
Expand Down
20 changes: 20 additions & 0 deletions src/invidious/videos/clip.cr
@@ -0,0 +1,20 @@
require "json"

# returns start_time, end_time and clip_title
def parse_clip_parameters(params) : {Float64, Float64, String}
decoded_protobuf = params.try { |i| URI.decode_www_form(i) }
.try { |i| Base64.decode(i) }
.try { |i| IO::Memory.new(i) }
.try { |i| Protodec::Any.parse(i) }

start_time = decoded_protobuf
.try(&.["50:0:embedded"]["2:1:varint"].as_i64)

end_time = decoded_protobuf
.try(&.["50:0:embedded"]["3:2:varint"].as_i64)

clip_title = decoded_protobuf
.try(&.["50:0:embedded"]["4:3:string"].as_s)

return (start_time / 1000), (end_time / 1000), clip_title
SamantazFox marked this conversation as resolved.
Show resolved Hide resolved
end