# Video Player v1.1
Play your own Videos in their full resolution, without lag.
This resource is going through a major rewrite due to the release of editable images. This post will stay as an “archive” of the old method used. Watch for new replies to know when the new version is released.
Table of contents:
| Showcase
The module uses a smart way to calculate how many frames of the video have passed since every heartbeat. It utilizes the audio track to create smooth playback, even on low-end devices. If you complete the set-up correctly, your video will never fall behind the music; it will stay synced! I conducted several testing sessions to test how reliable it is. The results are below. Take a look at its performance!
The video was shot at 1280 x 720 and 24 FPS. I compressed it so I could upload it here.
Okay, but this is on a high-end computer; what about older devices?
It’s simple; the player is smooth and optimized very well; videos shouldn’t have problems playing on mobile or bad hardware, but bad hardware is bad hardware. The video will have a noticeable lag. This is something that the Roblox Engine itself is limited to. Until Roblox fully releases their “VideoFrame” feature to the public, this is the best we can do. Refer to the archive below for the old video show on my phone. I’ll record a video with the new version soon!
Now featuring subtitle text.
A subtitle reader is now embedded in the module; you can feed it your subtitle code and it will play it alongside the video. Very useful if you are planning to make music events in your game. The video above has the English subtitles for this showcase; here is the same video, but in a different language, Russian:
Easy uploading.
The old method of importing each asset through bulk import in Studio was very painful, but no more! I have made a Python script to help. It is very easy to use. Refer to the github repository for a guide.
You can also watch this Video that I made. Sorry for the low quality and a lot of useless footage where I just waited. The video covers the full use of the module.
Notice: I had to use a random sound from the toolbox because Roblox banned the one I uploaded in the video. I also had to manually copy the IDs from the terminal because of a minor bug in the script. That bug was fixed quickly and is no longer present. If your asset name or description gets moderated, it will return HTTP Error 400.
This module can be used to create a wide variety of fun animations inside your game. You can make smooth-loading UI elements, video tutorials, gifs, and much more!
Because you are free to edit the source code for your own needs, you can expand its possibilities and create what you need.
Version 1.0 | Archived Videos
| Code Usage
To use the module, let’s first import it. You can find it here.
- You will see a small information message left by me and two folders. The “Raw” folder contains the raw code without any comments. If you don’t like reading them, then go straight for that.
There would be a few groups named after the directory where you should place them. The music goes to Workspace, the UI goes to StarterGUI, and the module goes to ReplicatedStorage. You can, of course, change it later if you want.
Inside the UI, you will see the so-called “Container”. This will be the UI element that you are going to use as a reference to where the frames will play. The container I have left is an example. It is simply a big frame at 1:1 scale made to fit the whole screen, but you can always change it; the usage on SurfaceGUIs has not been tested or confirmed yet.
Let’s first look at how we are going to “import” the video. Sadly, this method of playback uses a decal for every frame. If you have a longer video, you will have to import all the frames. But you can always skip every second frame, which will reduce the amount by a lot but make your video choppier. On how to actually get the frames from a video file, you can look at this YouTube Tutorial I found and used.
Head to the github repository of the asset uploader script. Follow the guide there to get it working. If you face any issues, leave a reply here or directly on GitHub.
- You can use the Asset Manager and Bulk Import in Roblox Studio to upload them MANUALLY. As of v1.1, we are going to use the method above.
Once you have gotten all the frames from output.txt
it’s time to convert them to their actual IDs. What you have currently are decalIDs, which are different from imageIDs. I have left an additional script in the module. Open it and replace the frame table with your own. After that, copy the whole script, go to the view tab on the top of your Studio, enable the command bar and output, then paste that whole script in the command bar and hit enter. It should start printing a lot of IDs; once it finishes, it will stop printing. You should see an arrow. Click it. Now you will see the whole converted table; you have to copy it. After that, simply go back to the initiator script and replace the frame table there with the new one. If you did everything correctly, the new IDs should be different from the originals.
Refer to the archive if you are using the manual method.
Version 1.0 | Archive
Now that you are done uploading your frames, we will need to add them to our table in order. Get the first frame and copy its asset ID; find the “Initiator” script inside the UI container; and find the Frames Table. Paste your ID there; now repeat this for the second, third, and so on frames until you have no more left. In the end, it should look like this:
local FrameIDs = {
13699569380, --// Your first frame
13699569096,
13699568875,
13699568602,
13699568397 --// Your last frame
- If you have trouble removing
rbxassetid://
then press Ctrl + F to open the Find menu. There, enterrbxassetid://
, click on the small arrow in the corner, leave “Replace” empty, and press the “Replace All” button on the right.
After you are done listing the frames in a table, it’s time to format them. I have added a simple function in the module so you don’t have to. Just use it like this:
local FrameTable = VideoControl:GenerateFrames(FrameIDs)
If you don’t want to use this function, you will need to format all IDs into their rbxassetid string form, which looks like this: "rbxassetid://13699569380"
.
Finally, all you have to do is add your audio ID to the “Music” sound we just imported to the workspace.
As of v1.1, the preload function was improved to load faster. If you suffer from issues, please use the old one in the archive. The new version makes a thread of each “chunk” of frames to load it faster. If you don’t preload your frames, then most of them will appear as gray “ghost frames”.
local chunksLoaded = 0
for chunkIndex = 1, math.ceil(#FrameTable / 100) do
task.spawn(function()
local tempTable = {}
table.move(FrameTable, chunkIndex * 100, chunkIndex * 100 + 100, 1, tempTable)
game:GetService("ContentProvider"):PreloadAsync(tempTable, function(asset, status)
if status ~= Enum.AssetFetchStatus.Success and status ~= Enum.AssetFetchStatus.Loading then
game:GetService("ContentProvider"):PreloadAsync({asset})
end
end)
chunksLoaded += 1
end)
end
repeat task.wait() until chunksLoaded == math.ceil(#FrameTable / 100)
Version 1.0 | Archive
game:GetService("ContentProvider"):PreloadAsync(FrameTable) --// Affects loading time but removes "Ghost frames".
As of v1.1, there is a new feature called subtitle code. A subtitle code reader is now embedded in the module, and you can use it. Because this might be confusing, don’t hesitate to leave a reply with your question or issue. Here is how you use it:
--// This is the subtitle code. It is very simple to use. Simply use the example below.
--// For example, at the 8th second, the text will change to "I want to be with you when the new dawn comes again,"
--// It will stay like that until the 15th second of the video, where it will change to what's next. It will continue until there is nothing left.
--// To add a time where there is no text, just put an empty string. I suggest adding an empty string at the beginning at 0 and at the end.
local Subtitles = {
{0, ""},
{8, "I want to be with you when the new dawn comes again,"},
{15, "I want to share the seconds, the joys and the sorrows."},
{22, "I'll carefully turn the page of the book where I'll"},
{32, "Collect and keep my memories."},
{35.8, "Maybe words can't tell how I feel,"},
{43, "But forgetting the fear, I'll try to take a step forward!"},
{50, "Hold out your palm and you'll soar into the sky"},
{54, "So boundless and so beautiful"},
{58, "Over the bridge of the rainbow"},
{61, "To the day to come That's waiting impatiently"},
{65, "I'll overcome my doubts, I'll find"},
{69, "What you once treasured"},
{72, "I'll be warmed by your smile and now I want to"},
{78, "Always be able to admire it!"},
{81, "One Week Friends"},
{88, ""}
}
Now finally use :PlayVideo(FrameTable, Container, FPS, Subtitles)
and you are good to go.
Set subtitles to false
if you don’t want to use them.
local Container = script.Parent -- Change this to your container.
VideoControl:PlayVideo(FrameTable, Container, 60, false)
- And now you are done. If you did everything correctly, after a few seconds of loading the frames, your video will start. To measure performance properly, I suggest using the microProfiler; enable it with Ctrl + Shift + F6.
The folder, including the scripts with comments, has more explanation on the technical and usage parts. Please refer to them if you want to know what each function does.
If you experience any issues or have a general question, don’t hesitate to ask me. Your feedback is important to me, so I can push this small module even further.
| Future Updates
If you have any feedback, suggestions, bug reports, improvements, or optimizations, don’t hesitate to leave a reply. This is currently what I have planned for the future of this module. I will try my best to update it so it is always fresh. New suggestions will be added to the list later.
Content | Check |
---|---|
Skip Button | |
Play, Pause, Rewind | |
Subtitles |
-
- Added
-
- In Development
-
- Not Yet Added
🖊️ | Update Log
Video Player | v1.1
2023-06-23T21:00:00Z
New Features
Embedded a subtitle code reader into the module.
Implemented a solution for uploading a large number of assets. Use the script here.
Changes
Changed the resample mode of each frame to Pixelated (configure it in the module)
also changed the scale type to fit, both of these changes are optional, you can remove them if the scale adds gray lines and cuts on the screen or if the resample mode makes it too pixelated or low quality on your screen
Image.ResampleMode = Enum.ResamplerMode.Pixelated --// Improves quality on larger screen resolutions. (rarely makes it worse looking)
Image.ScaleType = Enum.ScaleType.Fit --// Adds gray lines if the video does't fit the container.
Imrpoved documentation.
Better performance.
Added a FPS argument to the function to easily change it.
Removed some useless stuff that caused lag and rearranged some parts to improve readability and performance.
Merged the “Usages” and “Showcase” parts together.
I removed most details from the post so it’s easier to read.
Video Player | v1.0.1
2023-06-13T21:00:00Z
- I updated the post and fixed grammar mistakes. Made it more readable. Subtitles are in development. Added the “Update Log”.
| Links
Get the module from here.
Showcase:
Play the showcase game I made to test it on your device.
Download the showcase place here:
VideoPlayerShowcase.rbxl (100.1 KB)
This is only proof of a concept. Not everything is perfect, which is why I want to share it, so we can find problems and their solutions together and create a better experience.