Open 1ec5 opened 1 year ago
This Mastodon post clued me into a well-supported Web API for recording the contents of a canvas. This example focuses on capturing live video and audio from the user’s camera and microphone, but all we need are the non-invasive parts that record the webpage and spit out a WebM URL for download. It may be possible to control the frame rate so that the user won’t have to sit through the entire animation, as in OpenHistoricalMap/ohm-embed-1yr#5.
Maybe relevant: this is the code that's used in gl-director
to create a video source from a Mapbox GL canvas (essentially just using the captureStream
stuff that @1ec5 links to above) - https://github.com/developmentseed/gl-director/blob/main/app/assets/scripts/components/home/video-pane.js#L62 - just to see a real-world example, that also does a similar thing of rendering video by capturing a map canvas.
It may be possible to control the frame rate so that the user won’t have to sit through the entire animation, as in https://github.com/OpenHistoricalMap/ohm-embed-1yr/pull/5.
I think the problem might often be the reverse - where you want to make sure each frame is fully rendered before adding that frame to the video - where you actually need to "slow down" the animation in the browser in order to get a video at the fidelity one desires. There's https://hubble.gl/ which does this really nicely for Deck.GL based maps - ensuring a smooth video render, regardless of the user's local rendering speeds.
The details here can definitely get a bit hairy :-) - but I think using canvas.getSource()
to just record what's happening on the map canvas and letting users download that as a video file is probably a good start, and that's probably not too hard to implement.
Nice, I wasn’t aware of gl-director – very slick!
I think the problem might often be the reverse - where you want to make sure each frame is fully rendered before adding that frame to the video - where you actually need to "slow down" the animation in the browser in order to get a video at the fidelity one desires.
That’s true if you’re animating the map continuously, but in this case, I was thinking of something closer to a flipbook or timelapse effect. The output animation’s framerate might end up being something like 1 hertz, 10 hertz at most. We could probably manage to record it at up to 20 hertz if we disable animation transitions and capture frames after the map idles.
I think ideally we’d export a widely compatible animation format like animated GIF or APNG, but the WebM produced by captureStream
is certainly better than nothing.
This Mastodon post clued me into a well-supported Web API for recording the contents of a canvas.
Turns out the post was actually talking about using the MediaRecorder
API.
I was thinking of something closer to a flipbook or timelapse effect.
I see. So then what I think we should do is:
I normally prefer "actual video files" to GIFs because they tend to offer better compression, etc. but I think this might be a good use-case to just convert to GIF. Animated PNGs sound potentially good, but I couldn't find any libraries to encode to them in client-side JS.
I think this should be worth giving a shot and shouldn't be too hard to test out?
Ideally we’d offer as many formats as possible, since some places you’d want to share an animation only accept one format or another. We can start with whichever format is easiest; doesn’t really matter.
UPNG.js offers APNG encoding. (There are others; if I remember correctly, a JavaScript-based Firefox extension was the very first APNG encoder ever made.)
433 tracks reenabling the basic image export functionality so that people can share their work in social media and e-mail or save it as a souvenir. But a static screenshot is of limited use in visualizing time series data. Creating an animation from every frame can be time-consuming, but if OHM handles that for the user, I think that would help set OHM apart from non-historical maps like OSM.
Building off the approach in https://github.com/OpenHistoricalMap/issues/issues/433#issuecomment-1631679205, we’d need to animating the time slider as fast as possible: as soon as the map goes
idle
, take another screenshot and increment the slider immediately instead of waiting for the set interval. UPNG.js looks useful for assembling the screenshots into an APNG. Libraries for encoding animated GIFs include gif.js and gifshot.