Add playlist support to embedded videos

This commit is contained in:
Omar Roth 2019-04-13 14:26:32 -05:00
parent ae52ff93b2
commit 9a7fea0447
3 changed files with 111 additions and 5 deletions

View file

@ -468,6 +468,13 @@ end
get "/embed/:id" do |env| get "/embed/:id" do |env|
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
id = env.params.url["id"] id = env.params.url["id"]
plid = env.params.query["list"]?
if md = env.params.query["playlist"]?
.try &.match(/[a-zA-Z0-9_-]{11}(,[a-zA-Z0-9_-]{11})*/)
video_series = md[0].split(",")
env.params.query.delete("playlist")
end
preferences = env.get("preferences").as(Preferences) preferences = env.get("preferences").as(Preferences)
@ -483,7 +490,33 @@ get "/embed/:id" do |env|
next env.redirect url next env.redirect url
end end
if id.size > 11 # YouTube embed supports `videoseries` with either `list=PLID`
# or `playlist=VIDEO_ID,VIDEO_ID`
if id == "videoseries"
url = ""
if plid
begin
videos = fetch_playlist_videos(plid, 1, 1, locale: locale)
rescue ex
error_message = ex.message
next templated "error"
end
url = "/embed/#{videos[0].id}"
elsif video_series
url = "/embed/#{video_series.shift}"
env.params.query["playlist"] = video_series.join(",")
else
next env.redirect "/"
end
if env.params.query.size > 0
url += "?#{env.params.query}"
end
next env.redirect url
elsif id.size > 11
url = "/embed/#{id[0, 11]}" url = "/embed/#{id[0, 11]}"
if env.params.query.size > 0 if env.params.query.size > 0

View file

@ -23,6 +23,80 @@
</head> </head>
<body> <body>
<%= rendered "components/player" %> <%= rendered "components/player" %>
<script>
<% if plid %>
function get_playlist(timeouts = 0) {
if (timeouts > 10) {
console.log("Failed to pull playlist");
return;
}
var plid = "<%= plid %>"
if (plid.startsWith("RD")) {
var plid_url = "/api/v1/mixes/<%= plid %>?continuation=<%= video.id %>&format=html&hl=<%= env.get("preferences").as(Preferences).locale %>";
} else {
var plid_url = "/api/v1/playlists/<%= plid %>?continuation=<%= video.id %>&format=html&hl=<%= env.get("preferences").as(Preferences).locale %>";
}
var xhr = new XMLHttpRequest();
xhr.responseType = "json";
xhr.timeout = 20000;
xhr.open("GET", plid_url, true);
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
if (xhr.response.nextVideo) {
player.on('ended', function() {
location.assign("/embed/"
+ xhr.response.nextVideo
+ "?list=<%= plid %>"
<% if params[:listen] %>
+ "&listen=1"
<% end %>
<% if params[:autoplay] %>
+ "&autoplay=1"
<% end %>
<% if params[:speed] %>
+ "&speed=<%= params[:speed] %>"
<% end %>
);
});
}
}
}
};
xhr.ontimeout = function() {
console.log("Pulling playlist timed out.");
get_playlist(timeouts + 1);
};
}
get_playlist();
<% elsif video_series %>
player.on('ended', function() {
location.assign("/embed/"
+ "<%= video_series.shift %>"
<% if !video_series.empty? %>
+ "?playlist=<%= video_series.join(",") %>"
<% end %>
<% if params[:listen] %>
+ "&listen=1"
<% end %>
<% if params[:autoplay] %>
+ "&autoplay=1"
<% end %>
<% if params[:speed] %>
+ "&speed=<%= params[:speed] %>"
<% end %>
);
});
<% end %>
</script>
</body> </body>
</html> </html>

View file

@ -249,7 +249,6 @@ function number_with_separator(val) {
<% sub_count_text = video.sub_count_text %> <% sub_count_text = video.sub_count_text %>
<%= rendered "components/subscribe_widget_script" %> <%= rendered "components/subscribe_widget_script" %>
<% if plid %> <% if plid %>
function get_playlist(timeouts = 0) { function get_playlist(timeouts = 0) {
playlist = document.getElementById("playlist"); playlist = document.getElementById("playlist");
@ -310,8 +309,8 @@ function get_playlist(timeouts = 0) {
xhr.ontimeout = function() { xhr.ontimeout = function() {
console.log("Pulling playlist timed out."); console.log("Pulling playlist timed out.");
comments = document.getElementById("playlist"); playlist = document.getElementById("playlist");
comments.innerHTML = playlist.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3><hr>'; '<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3><hr>';
get_playlist(timeouts + 1); get_playlist(timeouts + 1);
}; };