Is there any way to use Cesium to export a video

Is there any way to use Cesium to export a video?
There is a tutorial to export video from Canvas and WebGL using websockets.


Want to know that if there is any other way to convert a Cesium animation to a video efficiently.

Hi Tristan,

We don’t have support for that yet, unfortunately, but it’s on our radar long-term!

Thanks,

  • Rachel

Tristan,

While Cesium has no “one click” out of the box support for recording video. This is actually a pretty straight forward thing to do with one of the many third-party libraries available. Cesium renders to an HTML canvas, so capturing frames and videos of Cesium is no different than any other canvas capturing technique.

One example would be using ccapture: https://github.com/spite/ccapture.js/.

Here’s a snippet that captures whatever is going on in the Cesium window and creates a webm movie (this won’t run as-is, but it gives you an idea of how it works. Basically, every time Cesium renders a frame, we save a frame of video.

var viewer = new Cesium.Viewer(‘cesiumContainer’);

var capturer;

var removeEvent;

startButton.onclick = function() {

capturer = new CCapture( { format: ‘webm’, framerate: 30 } );

capturer.start();

removeEvent = viewer.scene.postRender.addEventListener(function(){

capturer.capture( viewer.scene.canvas );

});

};

stopButton.onclick = function() {

removeEvent();

capturer.stop();

window.open(capturer.save());

capturer = undefined;

};

The exact details depend on your use case, for example, do you want to capture a pre-planned camera flight? Or just whatever the user is doing? Do you want to save the video to the server, or to the client machine? Do you care about time and do you want the video to run at the same speed of the Cesium clock?

Having out of the box video capture (or a plug-in) is something that’s been on my todo list for a while, but with everything else going I haven’t had any time to work on it. However, perhaps we can get a lot of mileage by choosing a decent library and at least having a blog post or Sandcastle example showing an end-to-end solution.

Hope that helps,

Matt

Thanks, Rachel. Good to know that it is listed on the plan.

在 2017年4月15日星期六 UTC+8上午1:59:36,Rachel Hwang写道:

Hi Matthew,

Many thanks for your help. I will try this way.
Actually I want to convert Cesium annimation with a pre-planned camera to a video in the background, so it will run in a server.

在 2017年4月15日星期六 UTC+8上午8:06:02,Matthew Amato写道:

ffmpegserver works beautifully for that purpose.

Since that didn’t work.

Here’s a video I created using ffmpegserver + CCapture.

Thanks for sharing, Ryan. This looks great!

Cheers,

  • Rachel

在 2017年4月26日星期三 UTC+8上午3:02:24,Ryan Hickman写道:

Since that didn't work.

https://www.youtube.com/watch?v=cVC8lRV5QwE&feature=youtu.be

Here's a video I created using ffmpegserver + CCapture.

ffmpegserver works beautifully for that purpose.

On Friday, April 14, 2017 at 2:52:15 AM UTC-6, trista...@garmin.com wrote:Is there any way to use Cesium to export a video?
There is a tutorial to export video from Canvas and WebGL using websockets.
Capture Canvas and WebGL output as video using websockets - SmartJava
Want to know that if there is any other way to convert a Cesium animation to a video efficiently.

Many thanks, Ryan. We are trying this way.

Can you please tell what does ffmpegserver do? I know about ffmpeg though.

Also, i will be really thankful if you can provide a step by step process of achieving what you did.

CCapture + ffmpegserver.

The documentation at https://github.com/greggman/ffmpegserver.js/ is sufficient. Also, read what Matthew Amato posted above. Combined, you’ll get the same result as I did.

Oh, i was looking at the wrong ffmpegserver repository. Thanks for the link

Hi Ryan,

It is so great for your repo! Is there any way to generate video without running html? I mean just with a service that send a request to get a video.

Tristan,

It would theoretically be possible to modify Cesium to work server-side using node.js and some third-party extensions (node-canvas/node-webgl). See: https://groups.google.com/forum/#!topic/cesium-dev/j723wkYI1EA

With this done, it would then be possible to render a video using ffmpegserver.

Great post!
It is working for me.
But any idea how to set the frequency that render is called which indicates the frequency that capture.capture is called

My suggestion to you would be to look at the TerriaJS stuff that has “postRender” hooks and “notifyRepaintRequired” (ctrl/cmd+f both of those phrases). This also works beautifully for reducing CPU/GPU usage when the map is not in the foreground or hasn’t been manipulated in some time.

https://github.com/TerriaJS/terriajs/blob/d23ef3a9b6b16ba4a98bdc6cd48c82b0cdf31ada/lib/Models/Cesium.js

In case anyone still needs this, you can now use the captureStream method to record your canvas and export a Webm video file.HTMLCanvasElement.captureStream() - Web APIs | MDN

1 Like

@clementchdn

Thank you for the follow up :pray: This looks like a great resource.

-Sam

1 Like

This worked for me for a demo, still some issues, had to record two times subsequently to get a proper video. But can serve you as a starting point.

// video recording
const toolbar = document.querySelector("div.cesium-viewer-toolbar");
const modeButton = document.querySelector("span.cesium-sceneModePicker-wrapper");

//start button
const startButton = document.createElement("button");
startButton.classList.add("cesium-button", "cesium-toolbar-button");
startButton.innerHTML = "Start";
toolbar.insertBefore(startButton, modeButton);
 // Find the canvas element to capture
var canvasElt = document.querySelector('canvas');
// Get the stream
var stream = canvasElt.captureStream(25); // 25 FPS
const mediaRecorder = new MediaRecorder(stream);
let chunks = [];
mediaRecorder.ondataavailable = function(e) {
  chunks.push(e.data);
}
startButton.onclick = function() {
    mediaRecorder.start();
};

//stop button
const stopButton = document.createElement("button");
stopButton.classList.add("cesium-button", "cesium-toolbar-button");
stopButton.innerHTML = "Stop";
toolbar.insertBefore(stopButton, modeButton);
stopButton.onclick = function() {
    mediaRecorder.stop();
    console.log(chunks);
    const blob = new Blob(chunks, { 'type' : 'video/webm;' });

    var a = document.createElement("a");
    a.href = window.URL.createObjectURL(blob, {type: "video/webm"});
    a.download = "demo.webm";
    a.click();
};

1 Like