TwitchMediaLoader Node
The TwitchMediaLoader node handles the fetching, caching, and loading of Twitch visual media assets, such as emotes, badges, cheermotes, and user profile images, making them readily available for use in your Godot project as SpriteFrames or ImageTexture.
Overview
This node acts as a central manager for Twitch's visual elements. Its primary functions are:
- Fetching Metadata: Uses an assigned
TwitchAPIinstance to get information about available global/channel emotes, badges, and cheermotes. - Downloading: Downloads the actual image data from Twitch's CDN (
static-cdn.jtvnw.netby default). - Caching:
- Saves downloaded raw image data to specified disk cache directories (
user://emotes,user://badges, etc.). - Saves converted
SpriteFramesorImageTextureas.resfiles in the same cache directories. - Leverages Godot's
ResourceLoadercache for efficient in-memory access once loaded.
- Saves downloaded raw image data to specified disk cache directories (
- Conversion: Uses an associated
TwitchImageTransformer(especially important for animated emotes/cheermotes) to convert the downloaded data into GodotSpriteFrames. - Providing Assets: Offers asynchronous methods to request specific assets, returning the corresponding
SpriteFramesorImageTexture. - Fallbacks: Provides configurable fallback textures for cases where an asset cannot be loaded.
The goal is to efficiently manage these assets, reducing redundant downloads and providing easy access within your game logic or UI.
Prerequisites
- Add the Node: Add a
TwitchMediaLoadernode to your scene, often as a child ofTwitchServiceor as an autoload/singleton. - API Dependency: Assign a configured
TwitchAPIinstance to theApiproperty in the Inspector. When you just have oneTwitchAPInode in your scene it will assign it automatically. - Image Transformer: Ensure the
Image Transformerproperty is assigned, especially if you need support for animated emotes or cheermotes useNativeImageTransformerorMagicImageTransformersee also TwitchMediaLoader
Configuration (Inspector Properties)
Api(TwitchAPI): Required. TheTwitchAPIinstance used to fetch metadata about emotes, badges, etc.Image Transformer(TwitchImageTransformer): Recommended. The image transformer node used to convert downloaded image data (especially animated GIFs) intoSpriteFrames. If not set or not supporting animation, animated assets might be loaded as static images.Fallback Texture(Texture2D): A default texture used when a requested emote, badge, or cheermote cannot be loaded.Fallback Profile(Texture2D): A default texture used when a user's profile image cannot be loaded.Image Cdn Host(String): The base URL for Twitch's static asset CDN. Defaults tohttps://static-cdn.jtvnw.net.Cache Emote(String, global dir): The directory path where emote data and.resfiles will be cached.Cache Badge(String, global dir): The directory path where badge data and.resfiles will be cached.Cache Cheermote(String, global dir): The directory path where cheermote data and.resfiles will be cached.
Signals
emoji_loaded(definition: TwitchEmoteDefinition)- Emitted after an emote corresponding to the given
TwitchEmoteDefinitionhas been successfully downloaded, converted, and cached. This signals that theSpriteFramesresource is now available viaResourceLoaderor subsequentget_emotes*calls.
- Emitted after an emote corresponding to the given
Key Public Methods
Note: Most methods that involve fetching data from the API or downloading images are async and must be called with await.
Emotes
preload_emotes(channel_id: String = "global") -> void- Fetches the metadata (definitions) for global emotes (
channel_id = "global") or a specific channel's emotes via theTwitchAPI. Caches this metadata internally. Does not download the actual images.
- Fetches the metadata (definitions) for global emotes (
get_cached_emotes(channel_id: String) -> Dictionary- Returns the cached metadata dictionary for the specified channel ID (or "global"). If metadata isn't cached, it implicitly calls and awaits
preload_emotes.
- Returns the cached metadata dictionary for the specified channel ID (or "global"). If metadata isn't cached, it implicitly calls and awaits
get_emotes(emote_ids: Array[String]) -> Dictionary[String, SpriteFrames]- Downloads (if not cached), converts, and returns
SpriteFramesfor a list of emote IDs. - Returns a Dictionary where keys are the requested emote IDs (String) and values are the corresponding
SpriteFrames. Uses fallback texture if loading fails.
- Downloads (if not cached), converts, and returns
get_emotes_by_definition(emote_definitions: Array[TwitchEmoteDefinition]) -> Dictionary[TwitchEmoteDefinition, SpriteFrames]- Downloads (if not cached), converts, and returns
SpriteFramesfor a list ofTwitchEmoteDefinitionobjects. This allows specifying theme, type (static/animated), and scale. - Returns a Dictionary where keys are the requested
TwitchEmoteDefinitionobjects and values are the correspondingSpriteFrames. Uses fallback texture if loading fails.
- Downloads (if not cached), converts, and returns
Badges
preload_badges(channel_id: String = "global") -> void- Fetches the metadata (definitions) for global badges (
channel_id = "global") or a specific channel's badges via theTwitchAPI. Caches this metadata internally.
- Fetches the metadata (definitions) for global badges (
get_cached_badges(channel_id: String) -> Dictionary- Returns the cached badge metadata dictionary for the specified channel ID (or "global"). If metadata isn't cached, it implicitly calls and awaits
preload_badges. Structure is nested based on badge set ID and version ID.
- Returns the cached badge metadata dictionary for the specified channel ID (or "global"). If metadata isn't cached, it implicitly calls and awaits
get_badges(badges: Array[TwitchBadgeDefinition]) -> Dictionary[TwitchBadgeDefinition, SpriteFrames]- Downloads (if not cached), converts, and returns
SpriteFramesfor a list ofTwitchBadgeDefinitionobjects (specifying channel, set, version, scale). - Returns a Dictionary where keys are the requested
TwitchBadgeDefinitionobjects and values are the correspondingSpriteFrames. Uses fallback texture if loading fails.
- Downloads (if not cached), converts, and returns
Cheermotes
preload_cheemote() -> void- Fetches the metadata for all available Cheermotes (prefixes, tiers, image URLs) via the
TwitchAPI. Caches this metadata internally.
- Fetches the metadata for all available Cheermotes (prefixes, tiers, image URLs) via the
all_cheermotes() -> Array[TwitchCheermote]- Returns an array containing the cached
TwitchCheermotemetadata objects. Implicitly callspreload_cheemoteif needed.
- Returns an array containing the cached
get_cheer_info(cheermote_definition: TwitchCheermoteDefinition) -> CheerResult- Gets the
SpriteFramesand associated metadata (TwitchCheermote,TwitchCheermote.Tiers) for a specific tier of a Cheermote defined byTwitchCheermoteDefinition. Downloads/converts if necessary. - Returns a
CheerResultobject containing the data, ornullif not found.
- Gets the
find_cheer_tier(number: int, cheer_data: TwitchCheermote) -> TwitchCheermote.Tiers- A utility function to find the correct
TwitchCheermote.Tiersobject within aTwitchCheermotemetadata object that corresponds to a given cheer amount (number). Does not requireawait.
- A utility function to find the correct
get_cheermotes(cheermote_definition: TwitchCheermoteDefinition) -> Dictionary[TwitchCheermote.Tiers, SpriteFrames]- Downloads (if not cached), converts, and returns
SpriteFramesfor all tiers associated with a givenTwitchCheermoteDefinition(uses the prefix, theme, type, scale from the definition). - Returns a Dictionary where keys are
TwitchCheermote.Tiersobjects and values are the correspondingSpriteFrames.
- Downloads (if not cached), converts, and returns
User Profile Images
load_profile_image(user: TwitchUser) -> ImageTexture- Downloads (if not cached) and returns the profile image for the given
TwitchUserobject as anImageTexture. Uses theprofile_image_urlfrom the user object. - Returns the loaded
ImageTextureor thefallback_profiletexture on failure.
- Downloads (if not cached) and returns the profile image for the given
Utilities
load_image(url: String) -> Image- A generic function to download an image from any URL and return it as a Godot
Imageobject. Primarily for internal use or custom needs.
- A generic function to download an image from any URL and return it as a Godot
Caching Behavior
TwitchMediaLoader employs a multi-level caching strategy:
- API Metadata Cache: Fetched definitions for emotes, badges, and cheermotes are stored in internal dictionaries.
- Disk Cache (Raw Data): When an image is downloaded, the raw data (PNG, JPG, GIF) is saved to the corresponding cache directory specified in the Inspector (
user://emotes/, etc.) based on its definition (ID, scale, theme, etc.). - Disk Cache (Resource): After conversion, the resulting
SpriteFramesorImageTextureis saved as a Godot resource file (.res) in the same cache directory. - Memory Cache: Godot's
ResourceLoaderautomatically caches loaded resources (.resfiles). Subsequent requests for the same cached resource path will retrieve it directly from memory, avoiding disk reads or redownloads.
This ensures that assets are downloaded only once and subsequent loads are significantly faster. The cache persists between application runs as it uses the user:// directory.
Usage Example
extends Node
@onready var media_loader: TwitchMediaLoader = $Path/To/MediaLoader
@onready var emote_display: AnimatedSprite2D = $EmoteDisplay
@onready var profile_pic: TextureRect = $ProfilePic
func _ready():
# Example: Load a specific emote by ID
load_specific_emote("301544920") # Example KappaRoss emote ID
# Example: Load current user's profile picture (assuming TwitchService exists)
var current_user: TwitchUser = await TwitchService.get_current_user()
load_user_profile(current_user)
func load_specific_emote(emote_id: String):
print("Requesting emote ID: %s" % emote_id)
var emote_dict: Dictionary[String, SpriteFrames] = await media_loader.get_emotes([emote_id])
if emote_dict.has(emote_id):
var sprite_frames: SpriteFrames = emote_dict[emote_id]
emote_display.sprite_frames = sprite_frames
emote_display.play("default")
print("Emote loaded successfully.")
else:
printerr("Failed to load emote ID: %s" % emote_id)
func load_user_profile(user: TwitchUser):
print("Loading profile for: %s" % user.display_name)
var profile_texture: ImageTexture = await MediaLoader.load_profile_image(user)
profile_pic.texture = profile_texture
print("Profile image loaded.")