[HN Gopher] We Built a Video Rendering Engine by Lying to the Br...
       ___________________________________________________________________
        
       We Built a Video Rendering Engine by Lying to the Browser About
       What Time It Is
        
       Author : darshkpatel
       Score  : 163 points
       Date   : 2026-03-01 04:50 UTC (2 days ago)
        
 (HTM) web link (blog.replit.com)
 (TXT) w3m dump (blog.replit.com)
        
       | d--b wrote:
       | This is super smart but doesn't seem very future-proof...
        
       | amelius wrote:
       | > The core issue is that browsers are real-time systems. They
       | render frames when they can, skip frames under load, and tie
       | animations to wall-clock time. If your screenshot takes 200ms but
       | your animation expects 16ms frames, you get a stuttery,
       | unwatchable mess.
       | 
       | But by faking the performance of your webpage, maybe you are
       | lying to your potential users too?
        
         | ErroneousBosh wrote:
         | > But by faking the performance of your webpage, maybe you are
         | lying to your potential users too?
         | 
         | I think you're missing the point of it a little. The "user" is
         | someone who wants to watch a rendered video of the brower's
         | display, but if it takes longer than one frame (where you read
         | the word frame in this comment, think of a frame of video or
         | film, not a browser "frame" like people used to make broken
         | menus with) to actually draw the visual the browser will skip
         | it.
         | 
         | Instead this appears to just tell the browser it's got plenty
         | of time, keep drawing, and then capture the output when it's
         | done.
         | 
         | It's not too different to how you'd do for example stop motion
         | animation - you'd take a few minutes to pose each figure and
         | set up the scene, trip the shutter, take a few more minutes to
         | pose each figure for the next part of each movement, trip the
         | shutter again, and so on. Say it took five minutes to set up
         | and shoot each frame then one second of film would take an hour
         | of solid work (assuming 12 frames per second, or "shooting on
         | twos").
         | 
         | It's just saying "take all the time you want, show me it when
         | it's done" and then worrying about making it into smooth video
         | after the work is done.
        
           | SiempreViernes wrote:
           | > The "user" is someone who wants to watch a rendered video
           | of the brower's display
           | 
           | While such a person might indeed exist, I think the more
           | common situation is a vendor showing a demo of how a website
           | might work. In that situation the consumer wants a
           | _realistic_ depiction of someone interacting with the site.
           | Though of course for the user of the video service it might
           | be very useful if the video hides all manner of performance
           | issues.
        
             | actionfromafar wrote:
             | If the rendering machine is an anemic, cheap and overloaded
             | VPS, it may also show performance issues which don't exist.
        
       | chmod775 wrote:
       | I've done similar shenanigans before. That main loop is probably
       | simplified? It won't work well with anything that uses timing
       | primitives for debouncing (massively slowing such code down, only
       | progressing with each frame). Also a setInterval with, say 5ms
       | may not "look" the same when it's always 1000/fps milliseconds
       | later instead (if you're capturing at 24fps/30fps, that would be
       | a huge difference).
       | 
       | What you should do is put everything that was scheduled on a
       | timeline (every setTimeout, setInterval, requestAnimationFrame),
       | then "play" through it until you arrive at the next frame, rather
       | than calling each setTimeout/setInterval callback only for each
       | frame.
       | 
       | Also their main loop will let async code "escape" their control.
       | You want to make sure the microtask queue is drained before
       | actually capturing anything. If you don't care about performance,
       | you can use something like await new Promise(resolve =>
       | setTimeout(resolve, 0)) for this (using the real setTimeout)
       | before you capture your frame. Use the MessageChannel trick if
       | you want to avoid the delay this causes.
       | 
       | For correctness you should also make sure to drain the queue
       | before calling each of the setTimeout/setInterval callbacks.
       | 
       | I'm leaning towards that code being simplified, since they'd
       | probably have noticed the breakage this causes. Or maybe, given
       | that this is their business, their whole solution is vibe-coded
       | and they have no idea why it's sometimes acting strange. Anyone
       | taking bets?
        
       | echoangle wrote:
       | Crazy that this approach seems to be the preferred way to do it.
       | How hard would it be to implement the recording in the browser
       | engine? There you could do it perfectly, right?
        
         | medi8r wrote:
         | You can screen share from browser so surely that API?
        
           | SiempreViernes wrote:
           | The purpose seems to be flashy demo videos to sell web-based
           | tools, so rendering unrealistically smooth interactions is
           | sort of the point.
        
             | johnpaulkiser wrote:
             | Oh, I thought the purpose was to to build a "copy this
             | saas" app?
             | 
             | You give the agent a URL it records itself going through UX
             | flows, give that video to a coding agent and you have quite
             | a feature.
        
         | szmarczak wrote:
         | This is the correct solution. However you'd need someone that
         | knows C++ well, knows Chrome internals, is familiar with video
         | stuff, audio stuff, knows Chromium rendering pipeline, possibly
         | some GPU APIs as well. That person would cost huge amounts of
         | money due to the required knowledge and complexity.
         | 
         | And then you'd need to maintain the code so it works with
         | future Chrome versions.
        
           | andrewstuart wrote:
           | I did all that. It was hard. I'm not an expert but fought my
           | way though to make all that work. I didn't get it perfect but
           | I got it pretty good. There's some weird challenges when you
           | get that deep.
           | 
           | Just as I got it working AI came along which made it
           | pointless then I realised when I got to the bottom that you
           | cannot do it perfectly because it's not a deterministic
           | renderer. So I called the project to an end.
        
             | Ajedi32 wrote:
             | > AI came along which made it pointless
             | 
             | What? What does AI have to do with anything here?
        
         | bob1029 wrote:
         | It can't be _that_ hard...
         | 
         | https://source.chromium.org/chromium/chromium/src/+/main:com...
        
         | whazor wrote:
         | Don't forget the requirement of not dropping frames under load.
         | The browser engine might have assumed that requirement
         | throughout the entire code base.
        
       | xnx wrote:
       | Mentioned at the very end that this is based on
       | https://github.com/Vinlic/WebVideoCreator
        
       | soulofmischief wrote:
       | This post smells of LLM throughout. Not just the structure (many
       | headings, bullet lists), but the phrasing as well. A few obvious
       | examples:
       | 
       | - no special framework. No library buy-in. Just a URL
       | 
       | - Advance clock. Fire callbacks. Capture. Repeat. Every frame is
       | deterministic, every time.
       | 
       | - We render dozens of frames that nobody will ever see, just to
       | keep Chrome's compositor from going stale.
       | 
       | - The fundamental insight that you could monkey-patch browser
       | time APIs ... is _genuinely clever_
       | 
       | - Where we diverged
       | 
       | The whole post is like this, but these examples stand out
       | immediately. We haven't quite collectively put a name on this
       | style of writing yet, but anyone who uses these tools daily knows
       | how to spot it immediately.
       | 
       | I'm okay with using LLMs as editors and even drafters, but it's a
       | sign of laziness and carelessness when your entire post feels
       | written by an LLM and the voice isn't your own.
       | 
       | It feels inauthentic and companies like replit should consider
       | the impact on their brand before just letting people write these
       | kind of phoned-in blog posts. Especially after the catastrophe
       | that was the Cloudflare Matrix incident (which they later
       | "edited" and never owned up to).
       | 
       | And the lede is buried at the very end: This is just a vibe-coded
       | modification of https://github.com/Vinlic/WebVideoCreator, and
       | instead of making their changes open source since they're
       | "standing on the shoulders of giants", the modifications are now
       | proprietary.
       | 
       | In the end, being an AI company is no excuse for bad writing.
        
         | lccerina wrote:
         | Their whole product is about vibe-coding unmaintainable "apps",
         | not surprised they put the same level of (dis)attention in
         | their blog too.
         | 
         | Also yikes for the proprietary modifications. AI companies:
         | "what's yours is mine, and what's mine is mine only"
        
         | truetraveller wrote:
         | You forgot the first part. the famous x,y, and z: "by
         | virtualizing time itself, patching key browser audio APIs, and
         | waging war against headless Chrome's quirks.
        
           | soulofmischief wrote:
           | Yep, that's good one. "Virtualizing time itself" itself is
           | such a dead giveaway. What a nonsensical phrase.
        
             | andrewstuart wrote:
             | Virtual Time is a feature of Chrome to fast forward when
             | rendering.
             | 
             | See --virtual-time-budget
             | 
             | https://peter.sh/experiments/chromium-command-line-
             | switches/
        
               | soulofmischief wrote:
               | Yes, but "virtualizing time itself" as phrased is meant
               | to be superfluous, LLMs do that kind of thing a lot. It
               | makes it sound like some kind of mystical or novel
               | approach even though the actual pattern is already common
               | knowledge / explicitly supported.
        
               | andrewstuart wrote:
               | Yeah it does have that flowery turn of phrase.
               | 
               | Lesson: if your going to do LLM assisted writing, say to
               | it "make sure this has a distinct tone that consistent
               | and clearly quite different".
        
           | astrange wrote:
           | https://en.wikipedia.org/wiki/Isocolon#Tricolon
        
         | geonic wrote:
         | Yes, this kind of writing is rampant on X. Once you know it's
         | coming from an LLM (mostly ChatGPT in my opinion as it uses
         | this style often) you can't unsee it. And that immediately
         | makes me skip it.
        
         | roywiggins wrote:
         | Unfortunately, people seem to organically love this sort of
         | writing, since at least one or two of these get to near the top
         | half of the front page here every day.
         | 
         | I'm not even against using AI per se, but when something is
         | obviously written in ChatGPTese I'm not going to read it if I
         | don't have to.
        
         | zem wrote:
         | > - We render dozens of frames that nobody will ever see, just
         | to keep Chrome's compositor from going stale
         | 
         | what's the issue with this one? it sounds like something I
         | might write, tbh.
        
       | andrewstuart wrote:
       | I did this a few years ago. The approach these guys are taking is
       | kinda hacky compared to other better ways - and I've tried most
       | of them.
       | 
       | It works but only in a limited way there's lots of problems and
       | caveats that come up.
       | 
       | I dropped it in the end partly because of all the problems and
       | edge cases, partly because its a solution looking for a problem
       | an AI essentially wipes out any demand for generating video in
       | browsers.
       | 
       | I ended up writing code that modified chromium and grabbed the
       | frames directly from deep in the heartof the rendering system.
       | 
       | It was a big technical challenge and a lot of fun but as I say,
       | fairly pointless.
       | 
       | And there are other solutions that are arguably better - like
       | recording video with OBS / the GPU nvenc engine / with a hardware
       | video capture dongle and there's other ways too that are purely
       | software in Linux that work extremely well.
       | 
       | You can see some of the results I got from my work here:
       | 
       | https://www.youtube.com/watch?v=1Tac2EvogjE
       | 
       | https://www.youtube.com/watch?v=ZwqMdi-oMoo
       | 
       | https://www.youtube.com/watch?v=6GXts_yNl6s
       | 
       | https://www.youtube.com/watch?v=KzFngReJ4ZI
       | 
       | https://www.youtube.com/watch?v=LA6VWZcDANk
       | 
       | In the end if you want to capture browser video - use OBS or
       | ffmpeg with nvenc or something - all the fancy footwork isn't
       | needed.
        
         | andrewstuart wrote:
         | Here you go, capture browser video for $100......
         | 
         | https://www.amazon.com.au/AVerMedia-Streaming-Passthrough-Re...
         | 
         | Or use ffmpeg with nvenc it allows simultaneous capture of 12
         | sessions.
         | 
         | Toss away all the hard work futzing with the browser just put
         | in one ffmpeg command.
        
         | pjc50 wrote:
         | "Use OBS" is one approach that definitely works. If you run the
         | browser inside OBS it also disables hardware acceleration,
         | which may cause some issues but has the advantage of turning
         | DRM support off.
        
           | andrewstuart wrote:
           | No it doesn't disable acceleration.
           | 
           | Just use nvenc or intel or AMD hardware video capture.
        
         | virtualritz wrote:
         | > I dropped it in the end partly because of all the problems
         | and edge cases, partly because its a solution looking for a
         | problem an AI essentially wipes out any demand for generating
         | video in browsers.
         | 
         | That is only because your view omits some other problems this
         | solves/products this enables.
         | 
         | There is an incredible ecosystem of tools out the browser land,
         | to create animation.
         | 
         | If you can capture frames from the browser you can render these
         | animations as videos, with motion blur (render 2500 frame for a
         | second of video, blend 100 frames each with a shutter function)
         | to get 25fps with 100 motion blur samples (a number
         | AfterEffects can't do, e.g).
        
           | andrewstuart wrote:
           | There's a tiny, tiny market for people who would pay for
           | this.
           | 
           | Also you must understand that chrome is not a deterministic
           | renderer. You cannot get the per frame control because it is
           | fundamentally designed to get frames in front of the user
           | fast.
           | 
           | They did some work around the concept of virtual time a few
           | years ago with this sort of thing in mind and eventually
           | dropped it.
        
             | virtualritz wrote:
             | > There's a tiny, tiny market for people who would pay for
             | this.
             | 
             | Not sure what market you are talking about.
             | 
             | What I was talking about: people pay for motion graphics.
             | LLMs are excellent at creating motion graphics from/around
             | browser technology ...
             | 
             | Advertising is a huge market and motion graphics is
             | everywhere in video/film-based advertising.
             | 
             | > Also you must understand that chrome is not a
             | deterministic renderer. You cannot get the per frame
             | control because it is fundamentally designed to get frames
             | in front of the user fast.
             | 
             | It absoluetly deterministic if you control the input. There
             | is no "add random number to X" in Chrome. The non-
             | determinism is user inputs and time.
             | 
             | I know this because the company I work for did extensive
             | tests around this last year. I was one of the people
             | working on that part.
             | 
             | We looked into the same approach as replit. The only reason
             | we gave up on it was product-related which changed our
             | needs. Not because it is impossible (which, I guess, their
             | blog post prooves).
        
               | andrewstuart wrote:
               | Not when you can say to nano banana "make a video showing
               | a thousand monkeys running down a road all wearing suits,
               | with cinema quality credits rolling over listing the
               | ingredients of corn flakes", and it spits out something
               | amazing.
        
         | KeplerBoy wrote:
         | Using OBS won't make your sluggish animation seem buttery
         | smooth though. This seems to be the point of replit's attempt
         | here. Perfect frame pacing.
         | 
         | On top you could use that technique to record at frame-rates
         | higher than native. There's no reason why you shouldn't be able
         | to redraw a basic page with some animations at a few hundred
         | fps.
        
       | zeta0134 wrote:
       | Ha, my first thought is that I'd likely break this system. My
       | page synchronizes its animation playback rate to an audio
       | worklet, because I need to do both anyway, and some
       | experimentation determined that syncing to audio resulted in
       | smooth frame pacing across most browsers. This means that
       | requestAnimationFrame has the very simple job of presenting the
       | most recently rendered frame. It ignores the system time and, if
       | there isn't a new frame to present yet, does nothing.
        
       | yetihehe wrote:
       | About 20 years ago there was a similar problem with demoscene
       | creations. It was hard to capture demos in realtime in all their
       | glory. So one guy created a tool[1] that waited for a frame
       | render and presented proper time to demo so that frames would be
       | paced properly. "All popular ways of getting time into the
       | program are wrapped aswell - timeGetTime,
       | QueryPerformanceCounter, you name it. This is necessary so
       | .kkapture can make the program think it runs at a fixed framerate
       | (whatever you specified)."
       | 
       | [1] https://www.farbrausch.de/~fg/kkapture/
        
         | fnordian_slip wrote:
         | It's rather off-topic, but the linked blog is by the guy who
         | made .kkrieger, the tiny first-person shooter (only 96kB) in
         | the early 2000s. Though the website for it is now gone, as
         | .theprodukkt doesn't exist anymore, apparently. Nice to see his
         | other stuff, didn't think to look at the time.
        
           | xnx wrote:
           | .kkrieger https://news.ycombinator.com/item?id=14409210
        
             | jakub_g wrote:
             | I remember kkrieger being impressively small but also
             | requiring insane compute :) it would render at like 0.1 fps
             | on my poor machine. (Aligns with this comment:
             | https://news.ycombinator.com/item?id=14415567)
        
         | calvinmorrison wrote:
         | Dont forget .gif webcam streams! Just keep sending new frames!
        
           | jacquesm wrote:
           | Indeed. The problem with that was that the browser would
           | cache the whole bloody stream and that quickly led to issues.
           | That's why we switched to JPEG, which also greatly improved
           | the image quality over the GIF format, which really wasn't
           | designed for dealing with camera generated images.
        
         | whynotmaybe wrote:
         | It's still used in the gaming industry but fir the opposite,
         | you can go faster than time.
         | 
         | Some enterprise software also have it, mainly for testing and
         | they have lint tools that check that you never use Date.now()
        
         | future_crew_fan wrote:
         | > "one guy" sir, that's no way to refer to farbrausch
         | 
         | here is their Breakpoint 2007 demo, a 177 Kb executable
         | including 3d assets and textures.
         | https://www.youtube.com/watch?v=wqu_IpkOYBg
        
           | yetihehe wrote:
           | I know them since fr08 . But AFAIK kkapture was started and
           | maintained mostly by ryg. And the demo you linked is my
           | favorite from them.
        
         | jezzamon wrote:
         | Ha, I independently set that up for my own coding animations.
         | Not as crazy as faking the whole system time though, that's
         | cool!
        
         | Aardwolf wrote:
         | Isn't another solution to capture the video signal to the
         | monitor?
        
           | AndriyKunitsyn wrote:
           | What this capturing software also does is it lies to the demo
           | program about the time that passed between the frames, so the
           | demo makers don't even care about running in realtime,
           | because for them, it's like running on a PC that's almost
           | infinitely powerful.
        
       | G_o_D wrote:
       | https://chromewebstore.google.com/detail/scroll-capture/egmh...
        
       | marxisttemp wrote:
       | The prose here reads like it was LLM-generated.
       | 
       | Short sentences. Plenty of newlines. Enumerate everything.
       | _Always_.
        
         | macinjosh wrote:
         | The posts pointing out in every comments section that people
         | now use AI tools for writing are getting really tiresome.
         | 
         | You are not clever for noticing and you are just filling up the
         | comments section with useless noise.
         | 
         | Not every post needs to be a hand crafted literary masterpiece.
        
           | marxisttemp wrote:
           | The posts made by AI tools for writing are getting really
           | tiresome.
           | 
           | You are not clever for using them and you are just filling up
           | the submissions section with useless noise.
           | 
           | Not every post needs to be.
        
           | dinkleberg wrote:
           | Similarly, the comments complaining about comments
           | complaining about AI are growing quite tiresome.
        
       | NoahZuniga wrote:
       | This wouldn't work for CSS/svg animations?
        
       | tosti wrote:
       | What a waste of time. Just hook up an hdmi recorder
        
       | brcmthrowaway wrote:
       | Does anyone remember FRAPS?
        
       ___________________________________________________________________
       (page generated 2026-03-03 23:01 UTC)