Skip to content

trying to only use next endpoint for the major data#5003

Draft
unixfox wants to merge 3 commits intoiv-org:masterfrom
unixfox:use-only-next-for-extra-info
Draft

trying to only use next endpoint for the major data#5003
unixfox wants to merge 3 commits intoiv-org:masterfrom
unixfox:use-only-next-for-extra-info

Conversation

@unixfox
Copy link
Copy Markdown
Member

@unixfox unixfox commented Oct 13, 2024

Description

This PR aims to avoid throwing a raw error and instead display all the data that we can extract from the /next endpoint but without displaying the "player" (video.js) element.

This is one big step towards #4985. Invidious will have to be able to display the watch page even when YouTube is blocking the IP.

This will give the same result as on www.youtube.com:

This way the user can still view the title of the video, accessing the channel page, viewing the comments and much more which is not yet blocked.

What changed?

  • The watch page is displayed properly but without the player if an error is found.
  • All the important data like title, viewcount is fetched from /next endpoint is unable from the /player endpoint.
  • The error message now throws the reason AND the subreason. Makes it clearer to the user what's really happening.

TODO

  • Integrate the embed page with the changes
  • Display the subreason on the watch page when there is an error
  • Fix description
  • Add mocks for a video without videoDetails

Try these videos ID for testing - on both a blocked IP and a not blocked one

  • 98TyXNPdMRo (private video)
  • 7KSfDyainYU (georestricted video)
  • KIuDBxqz__k (familySafe no)
  • yqaS07znJWY (unlisted video)
  • aaaaaaaaaaaa (notfound video)

Fixes

@unixfox unixfox requested review from a team and SamantazFox as code owners October 13, 2024 17:47
@unixfox unixfox marked this pull request as draft October 13, 2024 17:47
@unixfox unixfox force-pushed the use-only-next-for-extra-info branch 2 times, most recently from de76e24 to 250cffb Compare October 13, 2024 18:35
@unixfox unixfox force-pushed the use-only-next-for-extra-info branch 2 times, most recently from da00958 to a340868 Compare October 13, 2024 19:53
@unixfox unixfox requested a review from syeopite October 13, 2024 21:40
@unixfox unixfox force-pushed the use-only-next-for-extra-info branch from 60a5c1c to 9438a6d Compare October 13, 2024 22:08
@ic-scm
Copy link
Copy Markdown

ic-scm commented Oct 17, 2024

Thank you very much for this. Looking at instance yewtu.be which uses invidious-custom, it seems to be working just as expected, exactly as described in my linked issue, and with a 100% success rate.

Thank you for this great work - this is a huge step towards making Invidious convenient to use again. For me personally, it solves the entire problem.

The only thing I can potentially suggest is for the video thumbnail to be loaded and displayed on the page, separately from the broken video player. But that would be just a nice-to-have feature, and I'm guessing it may not be trivial to implement, when the official Youtube website just shows a black error screen, with the thumbnail nowhere to be seen.

Comment thread src/invidious/videos.cr
if reason = info["reason"]?
if info["reason"]? && info["subreason"]?
reason = info["reason"].as_s
puts info
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the debug puts here

Comment on lines -90 to +91
next_steps = error_redirect_helper(env)
error_message = <<-END_HTML
<div class="error_message">
<h2>#{translate(locale, "error_processing_data_youtube")}</h2>
<p>#{translate(locale, message)}</p>
#{error_redirect_helper(env)}
</div>
END_HTML
Copy link
Copy Markdown
Member

@syeopite syeopite Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your changes here will show the Error while processing the data sent by YouTube message on any InfoException while also removing the next steps message on all InfoExceptions

Example:

info exception

And InfoExceptions are raised in places unrelated to YouTube as well such as when a user inserts the wrong password.

Related: #4651


<div class="h-box">
<%= error_message %>
<%= next_steps %>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error page is used for everything and not just the watch page, so it must contain at least the "refresh" and "switch instance" buttons. Alternatively, we could split the error page logic for the watch page from the rest.

<%= translate(locale, "error_from_youtube_unplayable") %> <%= video.reason %>
</h3>
<h3>
<%= translate(locale, "next_steps_error_message") %>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want to use error_redirect_helper(). This error message alone (without any actions listed underneath) will be very confusing.

Comment on lines +120 to +122
<span id="refresh-page">
<a href="<% env.request.resource %>"><%= translate(locale, "refresh_page") %></a>
</span>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you add this link here? All browsers allow to refresh the page natively, and the close procimity with the "watch on youtube" link is prone to miss-clicks.

Comment on lines +207 to +209
if !(video_details = player_response.dig?("videoDetails"))
video_details = {} of String => JSON::Any
end
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you can use the more compact form:

Suggested change
if !(video_details = player_response.dig?("videoDetails"))
video_details = {} of String => JSON::Any
end
video_details = player_response.dig?("videoDetails")
video_details ||= {} of String => JSON::Any

Comment on lines +240 to +249
published_txt = video_primary_renderer
.try &.dig?("dateText", "simpleText")

if published_txt.try &.as_s.includes?("ago") && !published_txt.nil?
published = decode_date(published_txt.as_s.lchop("Started streaming "))
elsif published_txt && published_txt.try &.as_s.matches?(/(\w{3} \d{1,2}, \d{4})$/)
published = Time.parse(published_txt.as_s.match!(/(\w{3} \d{1,2}, \d{4})$/)[0], "%b %-d, %Y", Time::Location::UTC)
else
published = Time.utc
end
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I'd recommend using "scheduledStartTime" (see below) in the player response, as it's more accurate and doesn't need complex parsing logic.

{
	"playabilityStatus": {
		"status": "LIVE_STREAM_OFFLINE",
		"reason": "This live event will begin in 32 hours.",
		"playableInEmbed": true,
		"liveStreamability": {
			"liveStreamabilityRenderer": {
				"videoId": "hUoukmX_BRQ",
				"offlineSlate": {
					"liveStreamOfflineSlateRenderer": {
						"scheduledStartTime": "1729468800",
						"mainText": {
							"runs": [
								{"text": "Live in "},
                                {"text": "32 hours"}
							]
						},
						"subtitleText": {
							"simpleText": "October 21 at 12:00 AM"
						}
					}
				}
			}
		}
	}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: if you plan to fallback to the "subtitleText" value, there is a non-breaking space before AM/PM:
image

<% if video.reason %>
<h3>
<%= video.reason %>
<%= translate(locale, "error_from_youtube_unplayable") %> <%= video.reason %>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto: keeping the error message inside a player placeholder.

Comment thread src/invidious/videos.cr
# dont error when it's a premiere.
# we already parsed most of the data and display the premiere date
raise InfoException.new(reason.as_s || "")
raise NotFoundException.new(reason + ": Video not found" || "")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will expand to "Video unavailable: Video not found", which is not very explicit, imo.

Comment thread src/invidious/videos.cr
Comment on lines +332 to +336
if info.dig?("subreason").nil?
subreason = info["subreason"].as_s
else
subreason = "No additional reason"
end
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bloc of code can be summarized to the following, as you're already checking info["subreason"]? falsiness in the parent if

Suggested change
if info.dig?("subreason").nil?
subreason = info["subreason"].as_s
else
subreason = "No additional reason"
end
subreason = info["subreason"].as_s

Comment thread src/invidious/videos.cr
else
video = fetch_video(id, region)
Invidious::Database::Videos.insert(video) if !region
Invidious::Database::Videos.insert(video) if !region && !video.info.dig?("reason")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should make a getter dunction inside the Video class for reason/subreason.

"reason" => JSON::Any.new(reason),
"version" => JSON::Any.new(Video::SCHEMA_VERSION.to_i64),
"reason" => JSON::Any.new(reason),
"subreason" => JSON::Any.new(subreason),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to bump SCHEMA_VERSION in the Video class!

@NintendoManiac64
Copy link
Copy Markdown

NintendoManiac64 commented Feb 19, 2025

Integrate the embed page with the changes

To clarify, does this mean using the YouTube embedded player within the usual invidious video page? I know it wouldn't be "privacy respecting" in the same way as traditional invidious, so maybe as a sort of optional "compatibility mode" in the settings?

 

It sounds like some people have suggested something similar but instead mention just linking to the embed URL (youtube.com/embed/fo0bArBAZ) - I couldn't find anyone suggesting to directly embed the actual embedded YouTube player right on invidious.

(heck, I found out that you can even use various custom adblock filters to hide the "fluff" of the embed player such as suggestions & recommendations, and even end-screen video links/thumbnails, which makes me wonder if even invidious could similarly do that on the server side, or if that's only possible on the client side.)

...and now as I'm typing this, I'm remembering that YouTube supposedly has a newer type of embedded player that's "brandless" and lacks the fluff? Maybe that'd be better to use for embedding into the invidious video page...except, now that I review where I read about it, sounds like it's not something the user can choose and it's determined by the video channel itself?

 

Honestly my main use of invidious is just avoiding the "modern" bloated web page design of "javascript all of the things!" and the like, hence why I tend to still use invidious for navigating youtube even if I subsequently watch a video via the youtube.com/embed/fo0bArBAZ page

@syeopite
Copy link
Copy Markdown
Member

To clarify, does this mean using the YouTube embedded player within the usual invidious video page?

No, it would just mean displaying video info even if the player is unable to be rendered for whatever reason. Everything will still be in Invidious.

@ChunkyProgrammer
Copy link
Copy Markdown
Contributor

This should also close #4073

@mk-pmb
Copy link
Copy Markdown

mk-pmb commented Mar 19, 2025

Found this via #4744 . Is there any feedback still needed? Can I do something to help this move forward?

@unixfox
Copy link
Copy Markdown
Member Author

unixfox commented Mar 19, 2025

@mk-pmb There is still all the reviews that needs to be taken care off.

If you know about crystal, I would be happy to receive some contribution. If that's what you can help us, feel free to do a PR on my branch: https://github.com/unixfox/invidious/tree/use-only-next-for-extra-info or create a new PR in the invidious project :).

@mk-pmb
Copy link
Copy Markdown

mk-pmb commented Mar 19, 2025

I don't know crystal but I can try and replicate your changes based on current master, with the suggestions from this thread applied. 👍

@mk-pmb

This comment was marked as outdated.

@unixfox
Copy link
Copy Markdown
Member Author

unixfox commented Mar 21, 2025

hello @mk-pmb, yes sure sorry for the delay. I have created the branch: https://github.com/unixfox/invidious/tree/use-only-next-for-extra-info-base

I have opened the issues on my fork too.

I have a better idea, I invited you as a collaborator on my forked invidious repo, this way it will be easier to work on the branch use-only-next-for-extra-info directly. Don't screw up my others branches please 😄

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

7 participants