[Archive] Video Player v1.1 | Play your own Video inside Roblox! Full Resolution, FPS and Audio

I’m going to provide a small tutorial for this. I’ve got a website for getting the frames and a script that adds them to a dictionary automatically (may work on it more to skip frames that have the same id in case you accidentally inserted 2 of the same frame)

4 Likes

Update: turned the script into a small module. Things you can do: choose the path of the folder/model/container or whatever
Choose if you’d like to use getchildren or getdescendants.
Oh also you have access to the table, just do Module.FrameTable or something like that.
im trying to add more features since there’s barely anything i can add, but I’m thinking of adding an optional boolean that adds the table to an “universal” module that holds all of the dictionaries.

Also it no longer works because I’m the best at coding, especially modules
7680_keepincool
edit: module is fully done. I will provide a community resource post soon

4 Likes

Here’s my module for making your life a little easier: Asset dictionary
also here’s the website: https://www.onlineconverter.com/
(By the way, my module works on any type of downloadable asset, aka animation, decal, texture, mesh, image label, image button, shirt (not crap keyboard) and pants)

4 Likes

I am glad to hear that you have made this module. I hope more people will find it useful.


News on Update v1.1!

News on Update v1.1!

I’m almost done finishing up some stuff. Expect the update pretty soon (in a few hours or tomorrow).

What changed?

  • A full guide with a video on how to use the module and import the frames (with the new Python script).
  • Improved loading times and performance on the low end. Automated some calculations so you don’t have to go around the module yourself.
  • Added subtitles, which you will be able to code yourself. They depend on their own format, just like real subtitles. You will need to sync them with the music manually; of course, if you don’t like them or don’t need them, you don’t have to use them. Once again, they are customizable; you can pick the container to play them in. More features to the formatting will come soon. I’m planning to add some features like being able to pick the color or even add a gradient. I also might make it word-for-word with animations in the future, but I still don’t know how to realize that, so I don’t guarantee it.
  • Many more things are subject to change; if you have suggestions, don’t hesitate to leave a reply.

The update is not out; it will be in a few hours or tomorrow as of writing this.

2 Likes

Oh, I thought it was loading the whole video. When I went to the demo place and opened the Shift+F3 menu, it appears to be trying to pre-load about ~1300 frames, which I assumed was the whole video.

2 Likes

Update v1.1 is out!


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 t

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.


I recommend reading the post again, since there were a lot of changes made to it. I have added a lot of new video material.

1 Like

The IDs as in a dictionary? I’ve made a module for getting a type of asset’s IDs into a dictionary. It’s hard to explain lol. Asset dictionary

2 Likes

Hey so it’s me again lol, first of all, great job on the update, the video plays way smooth now, but theres now an issue that I don’t know if it has to do with the frame dimesions or something, basically the videos now have some weird gray frames at the edges like if the video gets cropped instead of filling the entire frame like it did in the 1.0 version, something like this:


It doesn’t seem that you had added something like that hence why I’m asking, overall the module improved quite a lot in smoothness, good job!

2 Likes

That is a small change. I forgot to add, thanks for reminding me. Basically, I set the frame’s resample mode to Pixelated so it looks a little better on bigger screens, and I set the mode to Fit, which creates those lines. To fix it, simply change the size of the container to “fit” exactly the resolution of the video or change it to Image.ScaleType = Enum.ScaleType.Stretch inside local function loadGroup(framesToLoad). I will edit the post to add this change in a few minutes. Both of these changes are optional, and you can remove them completely. Roblox, by default, should set it to stretched. Fit actually makes it fit. I don’t really know how to do UI, but all I know is that the size of the container should be as big as the size of your image to avoid any stretch effects or weird stuff on devices with irregular screen sizes.

  • New Code:
local function loadGroup(framesToLoad)
		for i=1, framesToLoad do
			if FrameTable[#Images + 1] == nil then break end
			local Image = Instance.new("ImageLabel")
			Image.ZIndex = #Images == 0 and Container.ZIndex or 1 - #Images
			Image.AnchorPoint = Vector2.new(.5, .5)
			Image.Size = Container.Size
			Image.Position = Container.Position
			Image.Image = FrameTable[#Images + 1]
			Image.ResampleMode = Enum.ResamplerMode.Pixelated
			Image.ScaleType = Enum.ScaleType.Stretch
			Image.Parent = Container
			table.insert(Images, Image)
			task.wait()
		end
	end
  • Old Code:
local function loadGroup(framesToLoad)
		for i=1, framesToLoad do
			if FrameTable[#Images + 1] == nil then break end
			local Image = Instance.new("ImageLabel")
            local result
            if #Images == 0 then
                result = Container.ZIndex
            else
                result = 1 - #Images
            end
			Image.ZIndex = result
 --// Before I used an if statement, but I changed it to a ternary statement to remove that useless variable and just make it more readable.
			Image.AnchorPoint = Vector2.new(.5, .5)
			Image.Size = Container.Size
			Image.Position = Container.Position
			Image.Image = FrameTable[#Images + 1]
			Image.Parent = Container
			table.insert(Images, Image)
			task.wait()
		end
	end
3 Likes

Came back after I released an update to my module (why? I don’t know tbh lol) and I played the game. It wasn’t the right screen size (although you addressed it, you didn’t patch that in the game lol) and sometimes there were ghost frames (mostly at the start and one at the end)

That response was quick lmao

1 Like

I haven’t been on the forum for a few weeks, I haven’t played Roblox in like a month, thanks for telling me, I’ll check onto it right now.
(Yes I was quick because finally after 3 years my browser notifications work)

Update:


I was able to re create it, also suffered an issue I thought shouldn’t be present.
This may mean 3 stuff:

  1. I have forgot to add the new patches and messed up something which can be fixed in 2 clicks.
  2. There was a recent change that broke it and can be fixed, or a recent change that can not be fixed. The “issue” I suffered was a really slow loading time, which I very well remember was not present. On my laptop which I tested everything I never had the issue and it always loaded instant. Yes, also the whole video was ghost frames. I got that screenshot after I played the video once, reset my character so it plays again. My script simply got outdated a little bit and I must update it if the change is fixable.
  3. It’s simply a Roblox issue that was either present before or started happening recently. I haven’t been on Roblox for about a month or two and I haven’t read any news, I hope it, it’s simply bad code or a recent update that has a fix.

To sum it up:
The sizing issue is my mistake and it will be fixed in the showcase place.
The sudden change in loading times and the whole video being ghost frames when you try to play it for the first time is either one of those 3:

  • Recent Roblox update that changed something and can be fixed
  • Recent Roblox update that change something and can not be fixed (only very short videos that don’t put a lot of stress)
  • Issue that was present before, but haven’t ever seen it/started happening now.
    I will make an investigation to see what happened and read news for the past few months to see for any changes that might break it.
    For the best if there were changes then a rewrite of the whole module would be a way to do it, but I think that the module itself is completely fine, it’s just the loading part that needs to be done, but on the latest update I made it slightly better by adding chunks and multi threading for each chunk, but I don’t know, I will check again.
1 Like

this is kind of unrelated but i found a funny bug. after loading delete the cache files and watch roblox seize out and the script erroring “attempt to index nil with Destroy”
you can’t fix this and the user has to intentionally trigger this but it’s funny and may even skip cutscenes lmao

1 Like

So idk what’s wrong with your showcase place but when I join it and it finishes loading it starts flashbanging all over the place and then proceeds to make the screen grey with the subtitles still going…

1 Like

me when roblox preloadasync doesn’t actually preload gasp

that’s a ghost frame.

1 Like

It does it like every second idk. After I resetted it does work fine might’ve just been something not loading correctly

1 Like

Preloadasync never preloads i swear. the images were cached. that’s why.

1 Like

The problem is that Roblox can’t load that much at a time, the subtitles run in their own thread so they are not affected by the video. The video plays alongside the audio thread (in simple words the current frame is a timestamp from the audio), the video does play, but the frames have not loaded yet, so Roblox replaces it with that gray background. I’m still looking for a fix or update. This topic was discussed before on the forum, yes with actual staff members, this is surely only a Roblox problem and a limitation that can’t be went around. As of making this module and testing, the Roblox Asset Delivery and Marketplace literally crashed at least 3 times (talking about this status page).

It’s sad to say, but as stated this is only a “proof of concept” and this will never be reliable or good to use in a game. Unless Roblox does something this will be the best you can do. I don’t think that making a pixel screen will do it better. I think it will actually be worse, but who knows, might try it someday.

1 Like

Well I mean they are gonna release videos later this year (announced by staff) so uhhh

It sucks because preload literally NEVER works for me. It literally does not do anything but yield (doesn’t even yield enough)

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.

Summary

After a lot of time and hard decisions, I decided to rewrite all of the codebase and finally do what I deemed impossible. I had this idea a very long time ago, but I just couldn’t implement it correctly. As of the release of editable images, this is no longer a headache to think about. We have a very performant writePixels() method that can be used. Sadly, at the current stage of this beta feature, it cannot be used inside an actual game, but hopefully in the future this will change and we will get to see it happen. The way it was supposed to work is that we have an encoder that will read the binary data of the video and convert it to readable values that we can use for our colors. The problem with that is that the only way to make it readable is to convert it to a string. This topic is very complex, so I won’t go into a lot of details here. The easiest way you could think of is to simply put each bit in a string and then convert that back using a simple algorithm. This is indeed the easiest way, but we will have an overhead of 192 times more than it actually should be. Computers were made to read binary code; a bit is the smallest value it reads; it’s simply a 0 or a 1. Yes or no. A byte is 8 bits, which allows it to store values from 0-255 in decimal numbers. Instead of saving each bit, we can store a single byte per color value. This makes 1 pixel equal to 3 bytes instead of 192. RGB (red, green, and blue) has exact decimal values from 0-255. I am still looking for better optimization and compression methods that will help reduce it even further. The first time I tried it, I turned a 30kb image into 3gb of data (somehow). Currently, as you will see in the videos, I have significantly reduced that and optimized it for 0–15 second 480p videos. I will not post any of the code here, but you can follow the Github repository, which was deleted btw. Read the new update at the bottom of this message. As of writing this, the latest commit doesn’t include any of the Python code I wrote. I am moving my codebase to C++, and that’s for a good reason (it’s faster and works better with binary instructions). If you want to see any of the old bad code, look for older commits. With that being said, I want to archive this resource since it won’t be needed anymore. Also, as of the beta release of the actual video implementation by Roblox, none of this might be needed for developers. I am not really happy with what they are doing, but hopefully in the future it will change. 2K Robux for some 60 seconds of semi-good quality, no alpha channel, and only a single auido track? That is just pointless to say; Roblox has got to do better than that. I will stop yapping about it now and just show you what I have so far with a video example.
Personally, I think this was the best attempt of all I had:


Here is another attempt with a higher resolution (please note that the audio is out of sync since it’s playing from Spotify and it’s not the full video :skull:)
sing along pa pa ra pa pa back to time pa pa ra pa pa - Album on Imgur

UPDATES

2024-03-03T21:00:00Z

Summary

This is still being worked on. After a few months I realized how complex this idea is.
I am currently testing with some other compression methods. If what I have in my mind ends up working it will be safe to say I am making a “roblox video codec”.
I don’t want to explain the whole idea here, you can watch a video here.
In short, I am now trying to implement an actual video format and not a copy of gifs or motion jpegs. I am currently experimenting with delta frames. The whole idea is that we only store the pixels that have changed since the last frame, this way we reduce the size of each frame by a lot. Especially for more static videos, this will work perfectly, just like real videos do. Here is a small showcase.

Showcase

The very first frame of our video:


The next frame that we want to compress:

The delta (difference) between the first frame and the second frame: (black spots are parts that didn’t change)

The decoded image only using the very first frame and the delta: (identical to the original)

Anyone looking for the old repository - it was deleted.
I want to start over from scratch and write better code than before.
I will try to finish this stupid project sooner.
If you ask why there are random parts that are on the delta, but visually they didn’t change, well that’s an artifaction from the video. The only issue with videos are these randomly changing chunks. The higher the quality of the recording - the better output you are going to get. The video I used was low resolution and bitrate on purpose (not really, but yeah).

2024-03-18T21:00:00Z

Summary

updated repository with new workflow
published it as a package on wally
implemented CI/CD
will add unit tests with TestEz in the future
the preview game has been updated to be used with the new workflow and auto deployment. you can still watch the videos in the post though.
nothing much. just a small update on the progress.
i figured out quite a lot during the process.
i am actively working on finally getting a reliable, fast decoder. the “codec” will use something similar to the MJPEG standard, just with my own twists.

please note that the source code in the repository itself is currently empty and nothing makes sense. i am working hard to get it done sooner. for any contributions/questions hit me up here or on discord. i will rarely update this post as of now on.

2024-04-19T21:00:00Z

Summary

Well, it’s been almost a month since the last update. I don’t want to keep this dead so let’s sum up what I was doing for this time.:

  • Completely rewritten code structure
  • A whole new optimization idea that has a potential to save 50% of the decoding time. The module now initializes and prepares all frames. It completely rewrites how the data is represented in the buffer so it’s easier for me to read it. Here I actually can get the static memory usage below the initial video file size.
  • New debugging and error handling.
  • Insanely fast speeds due to the new data structure, it is now mainly based on buffers. If I’m correct, it is doing 21mb/s of readind/writing from/to a buffer(s). 3k frames initialized in about 7.3 seconds.
  • A ton of new math optimizations that I can use. I made a discovery of this IDCT (Inverse Discrete Cosine Transform) fornula which promises to be insanely fast compared to the traditional DCT III (3) formula listed on Wikipedia.
  • I scraped the idea of trying to write the code to be ran in parallel. If stuff don’t go that well I will do something about it, but for now it will be ran in serial.
  • I also quit the idea of trying to make “delta frames”. It doesn’t work effectively with the JPEG format.
  • More and more code optimizations, more comments and better readability.

The repository commit history dead. I don’t make any commits, but I am making changes and a lot of progress!

Trying to understand low level computer science and math concepts you won’t even learn in university it’s quite the hassle to try and speedrun it. For the past month I have probably rewritten the code structure at least 5 times, each new version teaching me something new and helping me improve as a programmer. I am not planning to do it again, but it might be required for some part of the code if I am going to use parallel. I am sure this old project that I started as a joke now has a lot of potential to inspire others to power their imagination.

Also let me remind you, this is a knockoff lego game running a trash language called lua. Speeds like these are insane and just shows how something trash becomes great over time. Big respect to the creators and maintainers of lua. I am going to end this update with a screenshot of how the debug and error handling looks like. Do note that some of the information there can be straight up nonsense (most of the frame data). There is no decoding of the pixel data yet, the limit and goal is 1 / 60 (0.016s). There are many other optimizations I used, but haven’t mentioned. When I finish this project I will make a breakdown and review every single optimization I used. That’s all I had to say for today.



Oh, also… Totally forgot, I made a logo for the project. I know it looks bad, don’t tell me that :skull:

Do you like the logo?
  • Yes
  • No
  • Maybe

0 voters

Are you interested in a full breakdown of the optimizations and techniques used?
  • Yes
  • No

0 voters

5 Likes

Wow! This system looks like it has a lot of potential, patiently looking forward for the rewrite!

4 Likes