Core Architecture
The architecture of ProTV has two main concepts.
- Centralized management of multiple video player components.
- Event Listener Registry for propagating information to other udon behaviors.
Centralized Management
In order to give developers freedom over what player configuration they wish to use, ProTV implements a proxy-ish script that sits on the same game object as the desired video player component (being either Unity player or AVPro player). This script is called VideoManagerV2.
Each video manager has a handful of configuration options available to it. It also has two lists that should be populated as needed: Speakers and Screens.
These lists associate any Audio Source and Mesh Renderer game objects to the script for automatic management.
These proxies are then also associated with the main script called TVManagerV2. The tv manager has a handful of config options as well for the overall operation of its particular instance of ProTV.
TV Options
-
Autoplay URL
A url that is automatically loaded as soon as the TV has finished initializing. This is considered a “default” field because plugins are able to override this setting as needed (more on this later).
-
Autoplay URL Alt
Part of the “Alternate URL” feature. Similar to the standard autoplay url, it will automatically load as soon as the TV has finished initializing.
-
Autoplay Start Offset
Specifies how many seconds to wait after initialization (basically when the world is loaded in) to attempt to load the autoplay video. This is primarily used to avoid RateLimit errors or to specify load order when there are multiple TVs in the world that have some sort of autoplay defined on them. If there are one or less TVs with autoplay, this setting can be ignored.
-
Initial Volume
Pretty straight forward. This specifies what the volume should be for the TV at load time between 0% and 100% (represented as a 0.0 to 1.0 decimal)
-
Initial Player
This integer value specifies which index of the related Video Managers array option the TV should start off with. The array of video managers is 0-index based. This means that if you have, say, 3 video players in the list, if you wanted to have the TV default to the second video manger in that list, this option would need the value of 1
in it. If you only have one video manager, then set this option to 0
.
-
Paused Resync Threshold
This is more so a visual feedback feature where if the video is paused locally but the video owner is still playing, the video will update the current playback timestamp every some number of seconds determined by this option. If you don’t want the video to resync while paused, set this value to Infinity
(yes the actual word) to have it never update until the user resumes the video.
-
Automatic Resync Interval
Setting for telling the TV how many seconds to wait before trying to resync. This affects two separate things.
- First is the Audio/Video sync. This particularly affects AVPro for long form videos (like movies) where after some time or excessive CPU hitching (such as repeated alt-tabbing) can cause the audio to eventually become out-of-sync with the video (usually it’s the video that falls behind).
- Second is the Owner sync. This is where the owner of the current video determines the target timestamp that everyone should be at. ProTV has a loose owner sync mechanism where it will only try to enforce sync at critical points (like switching videos, the owner seeks to a new time in the video, owner pauses the video for everyone, etc).
This option defines how many seconds to wait before attempting to do the above resync.
-
Retry Live Media
This is for specifying how many retry attempts should be made when live media fails. Basically when a livestream goes down, ProTV will attempt to reload the same URL some number of times, determined by this setting, before determining that the stream should actually be considered failed/finished. This was originally created to help when doing things like swapping DJs on a VRCDN stream.
-
Start Hidden
NOTE: This option is considered deprecated and shouldn't be used unless you know what you are doing. It is recommended to simply disable the TV gameobject in the inspector manually if you want it to start off as hidden.
This setting automatically hides the TV’s gameobject after initialization, but before and autoplay video has been loaded. Useful if you have some plugins that need to modify the TV during the init phase.
-
Allow Master Control
A security setting that declares whether or not the instance master (aka the user who has been in the instance the longest) has the right to lock/manage the TV.
NOTE: The instance owner (aka the creator of the instance itself) will ALWAYS have the right to lock/manage the TV regardless of master.
-
Sync To Owner
A flag to tell the TV whether or not it’s supposed to synchronize with the owner. The setting is typically set to true. Though, for example, it can be particularly useful when trying to make a local-only music player.
-
Video Managers
The other part of the Initial Player setting. This is the actual list of VideoManager scripts that the TV should be handling.
Event Listener Registry (aka Subscribers)
In order to better facilitate extensibility for this asset, ProTV implements a behavior subscription structure where any Udon script can register itself to the TV and will receive specific events and data based on the TV’s activity.
These events are a bit more granular than the standard udon events for video players (though ProTV does emulate those). It is recommended to be judicious when deciding what event to listen with.
Registering
To connect your udon behavior to the TV, the minimum required is a reference to the desired TVManagerV2 script, the Start event and a reference to the current script (aka self
or this
). Here’s what the minimum setup looks like:
USharp:
public class MyCustomScript : UdonSharpBehaviour {
public TVManagerV2 tv; // the public TV reference
void Start() { // the Start event
tv._RegisterUdonSharpEventReceiver(this);
// 'this' refers to the current script
}
}
UGraph:
The variable and event names are a bit long for the input field in the node, so the full string is commented below the nodes.
Once this is done, your script will begin to receive events from the TV. You can also run this logic at any point in the runtime (not just in the Start event, though that is the most common use case) and it will register to the TV correctly.
Listening for Events
There are various types of events available for different contexts. All events called from the TV script begin with the _Tv
prefix to avoid event naming collision with other script usages.
Init Phase
- _TvReady
- Occurs when the TV has completed all initialization and is ready to be controlled.
- If a behavior is registered to the TV after the initialization phase (Start event), then it will be called on the target behavior immediately after registering.
- USE THIS EVENT TO “CATCH UP” WITH THE TV’S CURRENT STATE. This helps ensure that even if the plugin starts off as disabled on world load, as soon as it becomes registered, it can immediately sync up its internal state with the TV’s.
Based on TV Activity
-
_TvPlay
- Occurs when a video has started or resumed playing
-
_TvPause
- Occurs when a video has been paused locally
-
_TvStop
- Occurs when a video has been stopped locally
-
_TvMediaStart
- Occurs immediately after a video has been loaded
-
_TvMediaEnd
- Occurs immediately after a video has finished playing
- Can be used to trigger a new video, does NOT occur if video is set to loop
-
_TvMediaLoop
- Occurs when a video starts over after finishing
- Triggered only if video is set to loop OR if video is at the end and the owner pressed the play button for a one-time loop
-
_TvMediaChange
- Occurs when a user has claimed ownership of the TV and declared a new video to play
- This event happens before the video is actually loaded. To take action when a video is ready after it has been loaded, use the
_TvMediaStart
event.
-
_TvOwnerChange
- Occurs when a different player takes control of the TV.
-
_TvVideoPlayerError
- Occurs when the video failed to resolve and play for some reason
- This event will attempt to set the variable
OUT_TvVideoPlayerError_VideoError_Error
with the VideoError value that caused the event to trigger.
- When the VideoError is of INVALID_URL, this event is triggered immediately instead of waiting for the url to try and resolve the media.
-
_TvLoading
- Occurs when the TV’s loading state is enabled
- It can happen at various points, so this event is mostly used for UIs to reflect the loading state of the TV.
-
_TvLoadingEnd
- Occurs when the TV’s loading state is disabled
- It can happen at various points, so this event is mostly used for UIs to reflect the loading state of the TV.
-
_TvLoadingStop
- Occurs when the TV’s loading state is interrupted
- This is caused when the tv’s
_Stop
event is called while a video is loading.
- When this event is fired, the
_TvLoadingEnd
event will NOT be. It is recommended to have both events present to handle both cases.
Based on Change to a TV Setting
-
_TvVideoPlayerChange
- Occurs when the TV has swapped the video player configuration to a different one
- This event will attempt to set the variable
OUT_TvVideoPlayerChange_int_Index
with the current index value of the video player configuration that has been swapped to.
-
_TvMute
- Occurs when the local user mutes the current video
-
_TvUnMute
- Occurs when the local user unmutes the current video
-
_TvVolumeChange
- Occurs when the local user updates the volume percent value
- This event will attempt to set the variable
OUT_TvVolumeChange_float_Percent
with the updated volume percent. This event might be called many times in a short period, especially if it is affected by a slider element modifying the TV’s volume.
-
_TvAudioMode3d
- Occurs when the local user switches from positional to stereo audio
-
_TvAudioMode2d
- Occurs when the local user switches from stereo to positional audio
-
_TvEnableLoop
- Occurs when the local user enables looping for the current video.
-
_TvDisableLoop
- Occurs when the local user disables looping for the current video.
-
_TvSync
- Occurs when the local user enables video synchronization (disabled for owner as one cannot desync with oneself)
-
_TvDeSync
- Occurs when the local user disables video synchronization (disabled for owner as one cannot desync with oneself)
-
_TvLock
- Occurs when an authorized user (usually instance master) locks the TV for authorized use only.
-
_TvUnLock
- Occurs when an authorized user (usually instance master) unlocks the TV for anyone to use.
[WIP]