If you actually improve the code and optimize it more to get to the full resolution without losing FPS and performance, then your video player will turn out better than mine.
For the people asking for more context:
I’m currently also making a Video Player (artz is my friend actually ), but it uses a different way to render it. Compared to his, it’s currently better, but if you try it on a mobile device you will suffer pain, but I doubt his method will be performance friendly for any mobile device, videos need lots of computing power, and no phone has enough of that, especially with Roblox’s bad optimized spaghetti. His method is more reliable for performance at the moment, and it’s much easier to import the video, since it uses a string of pixel data, while my player uses decals, which might create problems for people on the low end or slow connection. My player does this:
- Let the game load it’s assets
- Start loading the video frames
- Make 2 groups of 150-200 frames that are being loaded on the screen each next frame having a lower zindex.
- Start to play the video after all frames are preloaded
- After 100-200 frames that were played run the same function to load the next group of frames and preload them. Repeat this until there are no more frames to load and let the video finish.
- Video finishes and plays it’s tweens to make a smoother transtition from the video to the actual game.
Differences between my method and his:
- My depends on how much Render FPS you have, the lower = more inaccuracy of the task.wait() function, which results in frames falling behind and unsyncing with the music and frame rate.
- I use each frame from a decal, while he uses a string of pixel data encoded into JSON.
- He uses a lot of actors for each pixel, while I use a for loop.
Ways I can improve mine to achieve better performance:
- Make a calibration sequence, where the code will measure the starting time and the current time, and depending on how much frames have played, if they were less than how much it should have played, it will remove all of those frames that should have played, which creates a glitchy effect in the video playback, but this same effect can be seen on a lot of low end devices trying to play a large video file, for example a movie, when the processor can’t handle up the video speed it starts to throttle and try to catch up with the audio, which in my case is exactly what I’m going to try and do.
- Remove ALL unneccesary calculations or functions in the code, with something that has to be super accurate, any calculation done on the CPU will cause innaccuracy to build up.
- Tweak the numbers for all the functions, for example, after how many played frames to load new ones, or how much new ones to load.
This is what I have in mind currently, if I’m wrong please correct me and if you have a suggestion to try tell me.
This is the code:
local TrackControl = require(game:GetService("ReplicatedFirst"):WaitForChild("TrackControl"))
local VideoControl = {}
function VideoControl:GenerateFrames(IDTable)
local Frames = {}
for _, v in IDTable do
table.insert(Frames, "rbxassetid://".. v)
end
return Frames
end
function VideoControl:PlayVideo(FrameTable,Container)
local Frames = table.maxn(FrameTable)
local Images = {}
local function loadGroup()
for i=1, 150 do
if not FrameTable[1] then return end
local img = Instance.new("ImageLabel")
img.ZIndex = if Images[1] then Images[table.maxn(Images)].ZIndex-1 else Container.ZIndex-i
img.AnchorPoint = Vector2.new(.5, .5)
img.Size = Container.Size
img.Position = Container.Position
img.Image = FrameTable[1]
img.Visible = true
img.Parent = Container
table.insert(Images, img)
table.remove(FrameTable, 1)
end
game:GetService("ContentProvider"):PreloadAsync(Images)
end
loadGroup()
loadGroup()
game.Workspace.isVideo.Value = true
repeat task.wait() until game.Workspace.isLoaded.Value == true
TrackControl:ChangeToLanguage(30, "Russian")
TrackControl:ChangeTrack(30)
local loadItterator = 0
for _, v in Images do
task.wait(0.0330578512396694)
v:Destroy()
task.spawn(function() loadItterator += 1 if loadItterator >= 125 then loadItterator = 0 loadGroup() end end)
end
Container.Background.Visible = true
game:GetService("TweenService"):Create(Container, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.InOut), {GroupTransparency = 1}):Play()
TrackControl:ChangeTrack(math.random(1, 29))
task.wait(1.5)
game:GetService("TweenService"):Create(Container.Parent.TrackPlayer, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.InOut), {GroupTransparency = 0}):Play()
TrackControl:ChangeAutoPlay(true)
end
return VideoControl
Please ignore any side modules or functions I use and only look at the base code for the video player, for example TrackControl is not a part of the Video Player, but an extra to make the Video Player have slightly better audio playback, but still sound:Play() will do the same as the track module I have, the module just makes it a little simpler and adds smooth tweens (which don’t delay the audio or unsync it with the video)
Edit:
Forgot to add my example, sorry, here it is: