You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Where should we write the GIF?
Output demo.gif
# Set up a 1200x600 terminal with 46px font.
Set FontSize 46
Set Width 1200
Set Height 600
# Type a command in the terminal.
Type "echo 'Welcome to VHS!'"
# Pause for dramatic effect...
Sleep 500ms
# Run the command by pressing enter.
Enter
# Admire the output for a bit.
Sleep 5s
I get the following, which seems to be at 2x speed compared to the example in the README:
Reacted by Ruan Spies, Vladislav Deryabkin, Chad Skeeters, Adrian Sieber, Sean, Oliver Weiler, Andrey Kozhev and Joe Reynolds
I can't reproduce this on my machine, but I think it has something to do with the number of frames that the VHS instance is able to capture. Can you try setting the framerate to 24 (the default is 60)
To explain this bug further, VHS will try to capture a frame every 1/framerate seconds (by default this is every 16.7 milliseconds) however if the capturing process takes longer, let's say 30 milliseconds per frame then VHS won't have enough frames to render the GIF at 60 FPS, but it will still try to. So it assumes that we are using 60 FPS when we really only have 30 FPS and results in a sped up GIF.
One solution is to time how long the frame capture takes (on average) and then use that as the actual frame rate so that the GIF isn't sped up.
# Where should we write the GIF?
Output demo.gif
# Set up a 1200x600 terminal with 46px font.
Set FontSize 46
Set Width 1200
Set Height 600
Set Framerate 24
# Type a command in the terminal.
Type "echo 'Welcome to VHS!'"
# Pause for dramatic effect...
Sleep 500ms
# Run the command by pressing enter.
Enter
# Admire the output for a bit.
Sleep 5s
Results in
Any ideas why it might be slower to capture a frame? Here are some system/environment stats
I have no idea why frames would be capturing slowly on that machine, it seems to be very fast. Do you have a lot of applications open like chrome, slack, VS Code etc... while recording the GIF?
Would I do this by counting the number of frames and dividing by the gif length or something?
We have some logic to see how long a frame capture took so that we can sleep for the rest of the time:
I have no idea why frames would be capturing slowly on that machine, it seems to be very fast. Do you have a lot of applications open like chrome, slack, VS Code etc... while recording the GIF?
I quit everything so activity monitor looked like this
During vhs < demo.tape running, it got up to this
But still doesn't look overloaded! Very strange.
FWIW the dockerized run works for me, so that can be my workaround for now :)
docker run --rm -v $PWD:/vhs ghcr.io/charmbracelet/vhs demo.tape
Ok thanks! Extra bits of info is that I installed vhs via brew on the intel mac and via go on the m2 mac. On both macs I installed the ffmpeg and ttyd deps via brew as per the README. I have Brave Browser set as my system default on both (not sure it matters at all).
This might be a super long shot, but what happens if you set chrome to your default. VHS uses a chromium browser and since brave is chromium it might be using that. I have no idea though, this is a long shot.
Here's another long shot: are your devices battery powered when running vhs? In other words: might another energy profile limit rendering performance of the remote controlled browser instance?
This is still making vhs more frustrating than it should be to use for me :/. I spend a decent amount of time adjusting the frame rate, dimensions, and sleep times to get an output that looks reasonable.
Thankfully, I think I found something that fits our needs and is written in Go.
Midterm is a virtual terminal emulator. There is no GUI, but it has conveniences for rendering back to a terminal or to HTML.
Would be interested if you think this would be a viable solution. I plan to do some experiments to see if this can do the job. The author (@vito) is someone I rate very highly as he was one of the main developers for Concourse CI and is now part of the Dagger team.
Thanks for the kind words 🥲
For what it's worth I'd be happy to help if using Midterm seems like a viable path to a fix. This issue affects me too, and Midterm is pretty fun to work on, so if y'all run into issues I'll try my best to address them.
Just tried out vhs. Ran into this issue. It's a dealbreaker for me. I tried upping the resolution of my capture to get better looking text, but now its playback speed is ridiculous. Even Sleep 15s flies by before I can see what happened on screen.
This is on a 2023 M2 Max with lots of RAM & disk available, so not sure why it would be slow.
I'll subscribe to this issue because other than this, it looks like a slick tool that I'd love to use. I'll come give it another shot if this gets resolved. 👍
Reacted by Jonathan Zollinger, Chakib Benziane and Egor Tarasov
Love using vhs, thank you for the great tool! However I also came here to bump the issue up: it's a dealbreaker for me, I would LOVE to capture in higher resolution (building whole-screen TUIs) and so far I'm only managing to capture with 5 fps 😿
Yes, I also unfortunately no longer use it after spending several hours trying to brute force picking resolution + speed. It would be okay if we could just multiply our sleep \ typing interval by a certain machine-specific factor to compensate slowdown, but unfortunately the frame speed is not 'consistently slower'. vhs could output a dozen frames at a decent speed, go through half of the typing bit, and then slowdown through typing the second half, which makes the whole typing element very junky irrespective to your speed settings.
I've been hoping to tackle this problem but have recognised we have some architectural issues to solve. It's not just about being able to capture screenshots fast enough, but also making sure the events we send are received on time.
From everything I have learned about terminals and the knowledge shared by the primary Ghostty developer, that this is a very complex space. No one here (including @vito) wants to create a fully featured headless terminal. That is a massive task and not a trivial piece of work.
I've had my fingers crossed that we might one day see libghostty and could create some Go bindings for it. This would give us the type of terminal we need that won't rely on a browser for capturing state. There's so much more we could do with these foundations. Without solid design, we are left in a the current state where we aren't really solving the problem, just applying more hacks.
Sometimes you just need to take a step back before we can go forward. We need help finding a highly functional headless terminal that we can integrate. Then we can build on top of that and solve these type of problems.
I started a discussion #644 around a working (for me) SVG implementation fork at https://github.com/agentstation/vhs - might be relevant to getting a clear image without speeding up the output! 😄
This might be a super long shot, but what happens if you set chrome to your default. VHS uses a chromium browser and since brave is chromium it might be using that. I have no idea though, this is a long shot.
This resolved the issue for me. Perhaps there should be some warning output when frames are dropped. I have a fork that does this.
I haven't forgotten about this issue and have spent a few years really thinking about this problem and we need to actually solve it. I recognise that we have an architectural issue and that experimentation is required to try some different approaches.
With the recent news of libghostty 1.0 being released, I decided to see if I could get a proof of concept running using the design I recommended in my earlier post. With frontier AI models, I was able to make some significant progress which resulted in a solution that validates the approach. Quite simply, it works!
By using a virtual terminal (libghostty), we can drop the need for a headless browser (chrome) and just capture the state changes. This also means we no longer need to care about converting the terminal to an animated image or video at capture time. We can do our render/export afterwards which lowers the CPU demands. In other words, we have a step for capturing the terminal and another independent step for rendering in our preferred output format.
As we are now capturing the state that is purely text, we also pick up the ability to generate SVG images which end up being significantly smaller file sizes with the added benefit of being scalable and text can be selected.
Here's the crazy part, because AI can write code so easily, what might have been a fairly simplistic proof of concept previously ended up being a very feature rich derivative (with a highly experimental scripting language). I've taken the issues and lessons from VHS and applied as much of that knowledge as possible to my own application. I hope that implementation concepts (or even code) could be considered for bringing back into VHS (with tighter quality controls). We now have a working solution that solves many of the long running issues that have been left unresolved.
I'd love to get some feedback and testing of Shellshot to be sure that the problems mentioned in this thread are actually fixed. I am especially mindful that I am sharing an alternate solution (I honestly am not trying to self promote) but this was all about seeing if we could solve the problems mentioned by this issue. I do not think it would take much time and effort to create pull requests for VHS that swapped out the existing backend for capturing and rendering the images/videos into this new pattern. I would expect there would be more code removed than added.
Activity
maaslalani commentedon Oct 29, 2022
I can't reproduce this on my machine, but I think it has something to do with the number of frames that the VHS instance is able to capture. Can you try setting the framerate to 24 (the default is 60)
maaslalani commentedon Oct 29, 2022
To explain this bug further, VHS will try to capture a frame every 1/framerate seconds (by default this is every 16.7 milliseconds) however if the capturing process takes longer, let's say 30 milliseconds per frame then VHS won't have enough frames to render the GIF at 60 FPS, but it will still try to. So it assumes that we are using 60 FPS when we really only have 30 FPS and results in a sped up GIF.
One solution is to time how long the frame capture takes (on average) and then use that as the actual frame rate so that the GIF isn't sped up.
robinovitch61 commentedon Oct 29, 2022
That looks better!
Results in
Any ideas why it might be slower to capture a frame? Here are some system/environment stats
Would I do this by counting the number of frames and dividing by the gif length or something?
maaslalani commentedon Oct 29, 2022
I have no idea why frames would be capturing slowly on that machine, it seems to be very fast. Do you have a lot of applications open like chrome, slack, VS Code etc... while recording the GIF?
We have some logic to see how long a frame capture took so that we can sleep for the rest of the time:
vhs/vhs.go
Line 199 in 1508f49
So we would probably measure each frame and average the number of frames we captured each second.
robinovitch61 commentedon Oct 29, 2022
I quit everything so activity monitor looked like this

During

vhs < demo.taperunning, it got up to thisBut still doesn't look overloaded! Very strange.
FWIW the dockerized run works for me, so that can be my workaround for now :)
maaslalani commentedon Oct 29, 2022
Interesting, so in docker you're able to get 60 frames per second? That's definitely really strange.
robinovitch61 commentedon Oct 29, 2022
Dang I was hoping that was the case but just got this on my other machine too
So might be a mac thing?
maaslalani commentedon Oct 29, 2022
This is super strange, I will definitely look into this. I don't know if it's a Mac thing, I have a mac and things work correctly for me.
I'll try and see if there's anything funky going on. It's really strange that it's not a memory/cpu issue. But that also means it could be solvable!
maaslalani commentedon Oct 29, 2022
Really appreciate all the info you've given, it's super helpful! I'll try and see if there's something is going wrong in VHS.
robinovitch61 commentedon Oct 29, 2022
Ok thanks! Extra bits of info is that I installed vhs via
brewon the intel mac and viagoon the m2 mac. On both macs I installed theffmpegandttyddeps viabrewas per the README. I have Brave Browser set as my system default on both (not sure it matters at all).maaslalani commentedon Oct 29, 2022
This might be a super long shot, but what happens if you set chrome to your default. VHS uses a chromium browser and since brave is chromium it might be using that. I have no idea though, this is a long shot.
robinovitch61 commentedon Oct 29, 2022
No luck - installed latest chrome, set as default, restarted computer, same output from tape
maaslalani commentedon Oct 29, 2022
Gotcha, it was a long shot. Really appreciate you trying it out and ruling that possibility out!
muesli commentedon Oct 30, 2022
Here's another long shot: are your devices battery powered when running vhs? In other words: might another energy profile limit rendering performance of the remote controlled browser instance?
20 remaining items
robinovitch61 commentedon Sep 17, 2024
This is still making
vhsmore frustrating than it should be to use for me :/. I spend a decent amount of time adjusting the frame rate, dimensions, and sleep times to get an output that looks reasonable.chasewilson commentedon Nov 8, 2024
Would love to see a resolution here. Glad that there are work arounds. Still having same issues on latest OS versions and VHS.
vito commentedon Nov 28, 2024
Thanks for the kind words 🥲
For what it's worth I'd be happy to help if using Midterm seems like a viable path to a fix. This issue affects me too, and Midterm is pretty fun to work on, so if y'all run into issues I'll try my best to address them.
NfNitLoop commentedon May 4, 2025
Just tried out vhs. Ran into this issue. It's a dealbreaker for me. I tried upping the resolution of my capture to get better looking text, but now its playback speed is ridiculous. Even
Sleep 15sflies by before I can see what happened on screen.This is on a 2023 M2 Max with lots of RAM & disk available, so not sure why it would be slow.
I'll subscribe to this issue because other than this, it looks like a slick tool that I'd love to use. I'll come give it another shot if this gets resolved. 👍
Jorres commentedon Jun 8, 2025
Love using vhs, thank you for the great tool! However I also came here to bump the issue up: it's a dealbreaker for me, I would LOVE to capture in higher resolution (building whole-screen TUIs) and so far I'm only managing to capture with 5 fps 😿
saward commentedon Jul 7, 2025
How are people using
vhswith this issue in place? Just finding a resolution that works for them, and making the speeds match it?Jonathan-Zollinger commentedon Jul 7, 2025
I've scrapped using it until it's fixed, unfortunately.
Jorres commentedon Jul 7, 2025
Yes, I also unfortunately no longer use it after spending several hours trying to brute force picking resolution + speed. It would be okay if we could just multiply our sleep \ typing interval by a certain machine-specific factor to compensate slowdown, but unfortunately the frame speed is not 'consistently slower'.
vhscould output a dozen frames at a decent speed, go through half of the typing bit, and then slowdown through typing the second half, which makes the whole typing element very junky irrespective to your speed settings.andelink commentedon Jul 7, 2025
Also not using it due to this issue
mikelorant commentedon Jul 9, 2025
I've been hoping to tackle this problem but have recognised we have some architectural issues to solve. It's not just about being able to capture screenshots fast enough, but also making sure the events we send are received on time.
From everything I have learned about terminals and the knowledge shared by the primary Ghostty developer, that this is a very complex space. No one here (including @vito) wants to create a fully featured headless terminal. That is a massive task and not a trivial piece of work.
I've had my fingers crossed that we might one day see
libghosttyand could create some Go bindings for it. This would give us the type of terminal we need that won't rely on a browser for capturing state. There's so much more we could do with these foundations. Without solid design, we are left in a the current state where we aren't really solving the problem, just applying more hacks.Sometimes you just need to take a step back before we can go forward. We need help finding a highly functional headless terminal that we can integrate. Then we can build on top of that and solve these type of problems.
jackspirou commentedon Aug 6, 2025
I started a discussion #644 around a working (for me) SVG implementation fork at https://github.com/agentstation/vhs - might be relevant to getting a clear image without speeding up the output! 😄
rahji commentedon Nov 1, 2025
Unfortunately, this bug makes vhs not useable for something like capturing runal output
robinovitch61 commentedon Apr 5, 2026
This seems to be improved when I run
vhsoutside a terminal multiplexer liketmuxrybkr commentedon Aug 23, 2026
This resolved the issue for me. Perhaps there should be some warning output when frames are dropped. I have a fork that does this.
mikelorant commentedon Nov 13, 2026
I haven't forgotten about this issue and have spent a few years really thinking about this problem and we need to actually solve it. I recognise that we have an architectural issue and that experimentation is required to try some different approaches.
With the recent news of libghostty 1.0 being released, I decided to see if I could get a proof of concept running using the design I recommended in my earlier post. With frontier AI models, I was able to make some significant progress which resulted in a solution that validates the approach. Quite simply, it works!
By using a virtual terminal (libghostty), we can drop the need for a headless browser (chrome) and just capture the state changes. This also means we no longer need to care about converting the terminal to an animated image or video at capture time. We can do our render/export afterwards which lowers the CPU demands. In other words, we have a step for capturing the terminal and another independent step for rendering in our preferred output format.
As we are now capturing the state that is purely text, we also pick up the ability to generate SVG images which end up being significantly smaller file sizes with the added benefit of being scalable and text can be selected.
Here's the crazy part, because AI can write code so easily, what might have been a fairly simplistic proof of concept previously ended up being a very feature rich derivative (with a highly experimental scripting language). I've taken the issues and lessons from VHS and applied as much of that knowledge as possible to my own application. I hope that implementation concepts (or even code) could be considered for bringing back into VHS (with tighter quality controls). We now have a working solution that solves many of the long running issues that have been left unresolved.
I'd love to get some feedback and testing of Shellshot to be sure that the problems mentioned in this thread are actually fixed. I am especially mindful that I am sharing an alternate solution (I honestly am not trying to self promote) but this was all about seeing if we could solve the problems mentioned by this issue. I do not think it would take much time and effort to create pull requests for VHS that swapped out the existing backend for capturing and rendering the images/videos into this new pattern. I would expect there would be more code removed than added.