I’m trying to render an animation (camera animation) out of a scene into an image sequence. I have been searching in the docs and forum as well as trying in a playground. This is what I have gotten so far:
In this PG, I imported a model then created an 240 frames camera animation fly around the model. My goal is render these 240 frames animation into 240 individual image file on disk. Then after I can use other approach (like ffmpeg) to convert this image sequence into whatever video format I need.
I was able to output some images, however, with some issues:
I was expecting getting 240 .png files (from frame 0 to frame 239) on my local disk. But I only ended up getting around ~180 images. Some frames looks got dropping during exporting.
The files written to disk have messed up names. The images before frame 100 can still exported with frame number in the file names, but any outputs after frame 100 all have random file naming. Are there any ways to name the output images in a better way such as: myOutput.####.png. (#### is 4 padding frame number)
I was also trying to add camera motion blur. But somehow it returns error and how able to render motion blur at all.
Please let me know if there are solutions to these 3 issues.
Besides, if anyone has any other better ideas regarding how to render video from a scene please let me know too. As far as I know, render a image sequence first and convert to video file after is the safest way to implement this. Although I have found some other solutions here:
I think the async/await might be the reason I couldn’t get every frame in the first place.
Can you add more detailed solution code in my original PG? I have been trying to apply your concept in my PG and unfortunately couldn’t be able to get it works…
@roland Wow!! this is amazing!! Thank you so much for the super presentable code!!
Just wondering:
what was the root cause why the motion blur in my original PG didn’t work? My motion blur code looks pretty much as your code. Looks it is because of the rendering pipeline in my original PG?
is there a particular reason you changed the createScene function to a async func in your PG?
@roland
Thank you so much!! These all makes sense.
Sorry one last thing. I am trying to download all the image data with this function:
function downloadSerializedImage(serializedImageData, fileName) {
// Create a link element
const link = document.createElement('a');
link.style.display = 'none';
document.body.appendChild(link);
// Set the href attribute of the link to the base64 image data
link.href = serializedImageData;
// Set a filename for the downloaded file
link.download = fileName;
// Simulate a click on the link to trigger the download
link.click();
// Clean up by removing the link from the DOM
document.body.removeChild(link);
}
Trying to evoke this func after the addImage() function. However I can’t be able to download all 240 images. How should I do it? Is it still because of the async/await thing? Sorry I am very new to web dev. Still dont understand the entire Promise concept fully yet.
I suggest to join all Base64 encoded pngs into one string, download it write a script which you can run locally. It could split the string into separate Base64 strings, convert them into binary pngs and save them to a local drive. If you’rein trouble doing this I can lend you a helping hand again
Other solution is to create a REST API handler on a server (it can be your local machine) and fetch the data one by one to this API endpoint and save the data on a local drive. I’d prefer this solution but it’'require to run the Playground locally as well. Do you want to use the Playground to run your code or have you already set up you app to run on your local server?
Javascript runs in a single thread on the CPU. When you perform a time consuming operation this thread is blocked and the page becomes unresponsive unless you wrap that time consuming operation into with a Promise. You can use two approaches to achieve this.
1: using callbacks
function timeConsumingOperation() {
return new Promise((resolve, reject) => {
// do something time consuming here
resolve() // call resolve when done (it's like a simple return from this function(
resolve(someValue) // or you can resolve with a value (it's like returning a value from this function)
reject() // or if something bad happens you can reject the Promise,
})
}
You can then call this function:
timeConsumingOperation().then((someValue )=> {
// do something with someValue
), () => {
// rejected, do something
})
2: You can use async/await to achieve the same thing:
async function timeConsumingOperation() { // automatically wraps the function with a Promise
return someValue
}
Calling the function:
const someValue = await timeConsumingOperation()
There is much more into JS Promises so I suggest you to look for more information on the web. It’s crucial to a web developer to master Promises.
I ended up successfully saving all png images to my local machine with the one long string solution you mentioned. (use python) This is a great step for me already in terms of prototyping! This entire video rendering process will eventually be running on a backend service. So this is a great enough for me now.
And thank you so much for the Promise explanation. I will definitely dive deeper for it. I have to master it soon or later haha.
Appreciate all the helps so far.
Best regards,
Tawibox