ProTV by ArchiTechVR | Usage Guides and Walkthroughs

Misc Notes

Understanding URLs in VRChat

All video players, generally speaking, work on Quest. Just gonna get that answer out of the way.

What doesn’t always work on Quest is the urls themselves. There are a few points to make regarding this:

NOTE:
VRChat made an update which enables the YoutubeDL on the Android build. This does not invalidate the information below, but it makes it become optional instead of required.

  1. The urls that people are most used to aren’t actually urls for media but for websites. Most commonly is Youtube, which is mostly in the form of https://youtube.com/watch?v=VIDEOID. This url is a website url, not a media (aka direct video) url. Video players do not know how to read a website url, so they would normally fail.

    BUT! VRChat has a trick up its sleeve to handle this. They use a command line tool called YouTubeDownLoad(YTDL). What this does is fetches the content of the webpage url, and fishes around that content until it finds a url that is a valid media url, then spits that back to VRChat so the program can tell the desired video player (either UnityVideo or AVPro) to play the direct url.

  2. Due to technical limitations beyond the VRChat dev’s reach, YTDL is unable to be used natively on the Quest platform. Only PC has access to this tool currently. This means that when a user tries to play a generic youtube video using the common shortform that you see in the browser URL bar… it’s not going to work. This is no longer correct as VRChat has enabled YTDL on the Android build.

  3. The first workaround option we have is using the YTDL tool externally to VRChat on a PC. What this does is gives you the direct media url which you can then enter into the video player which will then sync to Quest users and they’ll able to see it at that point.
    There are some drawbacks to this method:

    • First is that it requires an external computer to run the YTDL program in order to parse the website url into the longer-form media url.

    • Second is that for pretty much all large-scale media hosting platforms (such as youtube/video/dailymotion/etc) embeds a number of various parameters within the long-form urls, one of which is an expiration timestamps. So once the expiration timestamp has passed, the URL is no longer valid an will no longer load the video. This means that it is not realistic to put the URLs into the world at build time, as they would eventually not work. This also makes it difficult to simply share streams as well because most of those urls expire after an hour or two.

  4. The second workaround is to use a custom server external to VRChat that is exposed to the internet which runs the YTDL tool for the user and then returns the media url. This helps because each time the URL is fetched, it has a new timestamp in it, so it can work for extended periods of time. The difficult thing is that it does require server admin knowledge if you set it up on your own.

    • There is a free service that does this publicly, referred to as “Jinnai”. This service is quite popular, but is generally unreliable due to it’s overuse. Videos tend to fail 50% of the time. https://t-ne.x0.to/?url=
      This service no longer does URL resolution. There are are some other services that accomplish similar or same features, but as they are external resources, they won’t be listed here.

    • There is an open source option called Vroxy if you want to host your own. It even includes setup and update scripts in the repo for any Debian-based OS (like Ubuntu) to make setup a breeze.

    • One thing to note about using a server proxy like the above two, is if there is too much suspicious traffic from the server’s IP, youtube/twitch/vimeo/etc can just rate-limit or straight up block the server’s IP causing url resolution to fail.

  5. The final workaround is much more involved as it involves hosting the videos yourself from a custom server. You’d basically use YTDL to grab the video itself, then put it on a server you have and have people access the URL directly to your server instead of the mainstream hosting platforms. This is oviously an advanced method that the average world creator is not going to do.

All this doesn’t even go into the actual media content, like codecs and formats, which can also contribute to video failures. But that’s for another time.

About YoutubeDL specifically…

In order for VRChat to determine what the direct URL is for a given video, it makes use of the tool called youtubeDL. This tool is what allows desktop to be able to “watch youtube videos” (or other hosting sites like vimeo/twitch/etc). Currently due to technical reasons, this tool is not available on the Quest version of VRChat, ergo why youtube doesn’t work on quest by default.

There are two ways around this limitation when dealing with quest.

  1. On desktop, manually resolve the url outside of vrchat. This involves downloading a copy of youtubeDL onto your local machine, opening CMD (or equivalent command line program), then running either of the following commands:

    • The simplest one-liner is youtubedl -g -f best https://youtube.com/watch?v=VIDEO_ID
      This will simply get (the -g option) the url that is noted as the most compatible (the -f best option).
    • If you want to see what formats are available instead of just the “best” one, you can do youtubedl --list-formats https://youtube.com/watch?v=VIDEO_ID
      This will list all options available, examine the media codec types and resolution in the output to find your desired option, then copy the format ID (for youtube it’s a plain number on the left of each option) and replace the “best” term with that ID.
      Like so: youtubedl -g -f 312 https://youtube.com/watch?v=VIDEO_ID
      (Also if you are using vimeo with this method, I highly recommend any of the formats that start with hls-akfire_interconnect_quic- as they are good quality and compatible with Quest as well)

    Once you’ve retrieved the long-form direct URL for the youtube video, copy it and paste it into the input field for the TV.

    And additional thing to note with this method is that for most major video hosting platforms (like youtube and twitch), the long-form url has an embedded expiration timestamp in the URL. This means that the URL will only work for up to that timestamp and then will start failing for people who either late join, or reload the video. For those who already connected and are playing the video, it’ll continue to play.

  2. If you have knowledge of self-hosting stuff and a bit of programming experience, you could easily make a resolver redirect that utilizes youtubeDL remotely to resolve the URL for whoever requests it.
    This requires a server to host it on (like a VPS, AWS, or whatever), a domain (optional) and a bit of knowledge with nginx and some server language.
    The result should be where the URL is of the server and within that URL (say for example, a query parameter) is the ACTUAL url you want resolved, the server target would resolve the actual url with youtubeDL and return a 301 redirect to the requesting client which would then play that new URL.
    This would work long-term as well because every time someone tries to (re)load the URL in the world, it would cause it to be resolved to the latest expiration timestamp, thus removing the issue mentioned in the first option.
    I have tested a very rudimentary version of this and it does work, with the exception of livestreams (like twitch) on Quest. For some reason that platform does not like being redirected to live media.

Random tips to be aware of

  • When you call LoadURL/PlayURL on a video player instance, if the URL is invalid, the error callback will be called IMMEDIATELY before returning from the LoadURL/PlayURL method call.
  • It appears that complex encoding (such as URL encoded characters from eastern languages) has issues on Quest. If you are doing any custom hosting, for consistency and avoiding problems in the future, it is recommended to ONLY use ASCII based characters in urls. If you are going a basic video file serve, make sure the video file names are also only ASCII based.
3 Likes