I’ve been working on a custom video loader in Roblox, and it’s mostly working, but the loading time is painfully slow. ![]()
I’m preloading all the assets successfully, but when it comes to actually displaying the images on screen, it takes several minutes just for a short clip.
Is there a faster or better way to handle this? I’d love to know if there’s something I’m missing or a smarter approach to improve performance. ![]()
local ContentProvider = game:GetService("ContentProvider")
local RunService = game:GetService("RunService")
local Video = {}
Video.__index = Video
function Video.config()
return {
FPS = 29.97,
AspectRatio = 16 / 9,
Name = "miku_beam",
TotalFrames = 151,
Looping = false
}
end
function Video.new(config)
local self = setmetatable({}, Video)
self.config = config or Video.config()
self.imageTable = {}
self.imageInstances = {}
self.frameIndex = 1
self.playing = false
self.connection = nil
self.Loaded = false
self:_FindFrames()
self:_CreateImages()
local success, result = pcall(function()
self:_Preload()
end)
if not success then
return nil
end
self.Loaded = true
print(self.config.Name .. " video loaded 🥺")
return self
end
function Video:_FindFrames()
for i = 1, self.config.TotalFrames do
table.insert(self.imageTable, "rbxgameasset://Images/" .. self.config.Name .. "_" .. i)
end
end
function Video:_CreateImages()
self.folder = Instance.new("Folder")
self.folder.Name = self.config.Name
self.folder.Parent = script
for i, imageUrl in ipairs(self.imageTable) do
local image = Instance.new("ImageLabel")
image.Size = UDim2.new(1, 0, 1, 0)
image.BackgroundTransparency = 1
image.Image = imageUrl
image.LayoutOrder = i
image.ImageTransparency = 1
image.Visible = true
image.Parent = self.folder
self.imageInstances[i] = image
end
end
function Video:_Preload()
ContentProvider:PreloadAsync({ self.folder }, function(asset, status)
print(asset, status)
if status ~= Enum.AssetFetchStatus.Success and status ~= Enum.AssetFetchStatus.Loading then
ContentProvider:PreloadAsync({ asset })
end
end)
end
function Video:Stop()
if self.connection then
self.connection:Disconnect()
self.connection = nil
end
if self.oldFrameInstance then
self.oldFrameInstance.ImageTransparency = 1
self.oldFrameInstance = nil
end
self.playing = false
self.frameIndex = 1
end
function Video:Play(frame: Frame)
self:Stop()
self.playing = true
for _, child in frame:GetChildren() do
if child:IsA("UIAspectRatioConstraint") then
child:Destroy()
end
end
local UIAspectRatio = Instance.new("UIAspectRatioConstraint")
UIAspectRatio.AspectRatio = self.config.AspectRatio
UIAspectRatio.Parent = frame
for i, image in ipairs(self.imageInstances) do
image.Parent = frame
image.ImageTransparency = 0
repeat task.wait()print(i) until image.isLoaded
image.ImageTransparency = 1
end -- this takes like 1 minute to load a 5 second clip ...
local elapsedTime = 0
self.connection = RunService.RenderStepped:Connect(function(dt)
if not self.playing then return end
elapsedTime += dt
local frameToShow = math.floor(elapsedTime * self.config.FPS) + 1
if frameToShow > self.config.TotalFrames then
if self.config.Looping then
elapsedTime = 0
frameToShow = 1
else
self:Stop()
return
end
end
if frameToShow ~= self.frameIndex then
local current = self.imageInstances[frameToShow]
if current then
if self.oldFrameInstance then
self.oldFrameInstance.ImageTransparency = 1
end
current.ImageTransparency = 0
self.oldFrameInstance = current
self.frameIndex = frameToShow
end
end
end)
end
return Video