{"id":13394436,"url":"https://github.com/chjj/ttystudio","last_synced_at":"2025-05-15T03:05:50.158Z","repository":{"id":34683812,"uuid":"38657802","full_name":"chjj/ttystudio","owner":"chjj","description":"A terminal-to-gif recorder minus the headaches.","archived":false,"fork":false,"pushed_at":"2017-07-10T03:58:27.000Z","size":924,"stargazers_count":3243,"open_issues_count":20,"forks_count":92,"subscribers_count":54,"default_branch":"master","last_synced_at":"2025-04-21T03:52:04.240Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chjj.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-07T02:04:56.000Z","updated_at":"2025-04-20T07:25:55.000Z","dependencies_parsed_at":"2022-09-04T16:01:49.068Z","dependency_job_id":null,"html_url":"https://github.com/chjj/ttystudio","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chjj%2Fttystudio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chjj%2Fttystudio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chjj%2Fttystudio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chjj%2Fttystudio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chjj","download_url":"https://codeload.github.com/chjj/ttystudio/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264765,"owners_count":22041793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T17:01:19.675Z","updated_at":"2025-05-15T03:05:50.086Z","avatar_url":"https://github.com/chjj.png","language":"JavaScript","readme":"# ttystudio\n\n__A terminal-to-gif recorder minus the headaches.__\n\n![ttystudio](https://raw.githubusercontent.com/chjj/ttystudio/master/img/example.gif)\n\nRecord your terminal and compile it to a GIF or APNG without any external\ndependencies, bash scripts, gif concatenation, etc.\n\nInstall with: `$ npm install ttystudio`. (Add `-g` for global install).\n\n\n## Usage\n\n``` bash\n$ ttystudio output.gif --log\n  $ vim\n    hello world\n    :q!\n  $ ^Q # stop recording with ctrl-q\ninitializing writer\nwriting image\nwriting head\nwriting frame 0 - 132 left\nwriting frame 1 - 131 left\nwriting frame 2 - 130 left\n...\nwriting frame 131 - 1 left\nwriting eof\nwrote image to /home/chjj/output.gif\n$ chromium output.gif\n# or if you wrote to output.png (an APNG)\n$ firefox output.png\n```\n\n## The Difference\n\nttystudio differs from other terminal recorders in that:\n\n1. It has its own built-in gif and apng writer, no imagemagick required. The\n   writer now has built-in frame offset optimization.\n2. It has a font parser to render the font during image writing so no terminal\n   playback is required when writing the image (this also means __no GUI is\n   required at all__ - you can record on a remote machine via ssh).\n3. No concatenation of hundreds of gif files required. ttystudio automatically\n   writes out to one gif or apng.\n4. No glitchy frames due to imperfect GUI recording of the playback or gif\n   concatenation.\n5. ttystudio will record frames even if nothing is being updated on the screen.\n\nThis project has ended up making use of years of work I've done writing\nterminal libraries (my personal obsession). Once all the pieces were there,\nthis project became possible. It also sprang out of a need to find a\nterminal-to-gif recorder that actually worked.\n\n\u003csup\u003e(NOTE: The above .gif was recorded with ttystudio - _nested_ ttystudio\ninstances cause a slight glitch where the cursor is not visible. Not to matter\nin most cases).\u003c/sup\u003e\n\n\n## More Usage\n\n``` bash\n$ ttystudio output.gif --log # record and compile\n$ ttystudio frames.json --log # record\n$ ttystudio frames.json output.gif --range=0-50 # compile\n```\n\n\n### Use a frames.json file\n\n``` bash\n$ ttystudio --record frames.json --interval=100 # grab each frame on a 100ms interval\n  $ vim\n    hello world\n    :q!\n  $ ^Q # stop recording with ctrl-q\n$ ttystudio --compile frames.json output.gif --log\nparsing json\ninitializing writer\nwriting image\nwriting head\nwriting frame 0 - 132 left\nwriting frame 1 - 131 left\nwriting frame 2 - 130 left\n...\nwriting frame 131 - 1 left\nwriting eof\nwrote image to /home/chjj/output.gif\n$ chromium output.gif\n# or if you wrote to output.png (an APNG)\n$ firefox output.png\n```\n\n\n## How it works\n\n1. `$ ttystudio --record frames.json`:\n   [blessed][blessed]+[term.js][term.js]+[pty.js][pty.js] will spawn a\n   pseudo-terminal to let you record until you press ^Q.\n2. `$ ttystudio --compile frames.json output.gif`: ttystudio will parse each set of\n   frames into a bitmap, keeping in mind the foreground color and character in\n   each cell.\n3. It will use its parsed font (terminus-u14n/b by default) to render pixels\n   for each characters in the image.\n4. It will write out each frame to a .gif or .png file of your choice.\n\nIt's that simple. No bash script to run. No gifs to concatenate. No external\ndependencies required (i.e. ffmpeg or imagemagick) - ttystudio does it all on\nits own, in 99% javascript (aside from pty.js which is a node c++ binding to\nspawn terminals).\n\n\n## Options and Examples\n\nCompiling to APNG:\n\n``` bash\n$ ttystudio frames.json output.png --log\n```\n\nAccidentally recorded something you don't want in your image? The `range`\noption can help:\n\n``` bash\n# compile only frames 5 to 130\n$ ttystudio frames.json output.gif --log --range=5-130\n```\n\nThe `delay` option sets the delay between frames in the final image:\n\n``` bash\n# 100ms between output frames\n$ ttystudio frames.json output.png --log --delay=100\n```\n\nThe `--no-palette/--rgba` option can be used to avoid use a global palette\n(color type 3) when compiling APNGs (this is known to cause high memory usage\nwhen building the palette since it has to parse every frame beforehand).\nInstead, it will use color type 6 (RGBA). This will make the APNG larger, but\ndoes not risk OOMing the process. OOMing the process is unlikely to happen, but\nif it does, this option is here. Use `pngcrush` afterwards to optimize.\n\n``` bash\n$ ttystudio frames.json output.png --log --rgba\n```\n\nPiping:\n\n``` bash\n$ ttystudio frames.json - | feh -\n```\n\nReplaying frames in the terminal:\n\n``` bash\n$ ttystudio --play frames.json\n```\n\nAdding a border:\n\n``` bash\n# explanation of arguments:\n$ ttystudio output.gif --log --border=[width],[r],[g],[b],[a]\n# add a red border:\n$ ttystudio output.gif --log --border=10,255,0,0,255\n# white border:\n$ ttystudio output.gif --log --border=10,255\n$ ttystudio output.gif --log --border=10,255,255,255\n$ ttystudio output.gif --log --border=10\n```\n\nStart in screenshot mode. This allows you to take multiple screenshot whenever\n`C-p` is pressed. ttystudio will write them all to separate images.\n\n``` bash\n$ ttystudio o.gif --screenshot --screenshot-key C-p\n```\n\n\n### Full Options List\n\n- `-l, --log`\n  - Log status to stderr (now default).\n\n- `-q, --quiet`\n  - Do not log status to stderr.\n\n- `-f, --font [font-file]`\n  - Choose a BDF font in ttystudio's JSON format.\n\n- `-b, --font-bold [font-file]`\n  - Choose a bold BDF font in ttystudio's JSON format.\n\n- `-d, --delay [delay-ms]`\n  - Specify frame delay in ms (default: 100).\n\n- `-i, --interval [interval-ms]`\n  - Specify frame snapshot interval in ms (default: 100).\n\n- `-k, --key [quit-key]`\n  - Choose a key combination to quit recording (default: C-q).\n\n- `-n, --num-plays [num-plays]`\n  - Specify a number of plays for the animation (default: 0 - infinite).\n\n- `-r, --range [frame-range]`\n  - Choose a range of frames to compile. e.g. 5-200.\n\n- `-x, --ratio [pixel-cell-ratio]`\n  - Choose pixel to cell ratio. This option is useless right now since it is\n    overwritten by the font (default: 8x14).\n\n- `-t, --term [term-name]`\n  - Choose the terminal name for terminfo.\n\n- `--palette`\n  - Use a global palette for APNGs instead of RGBA.\n\n- `--no-palette, --rgba, --lct`\n  - Use RGBA for APNGs instead of a global palette. This will also avoid\n    building a global palette for GIFs and only use a local color table for\n    each frame.\n\n- `--border [width,r,g,b,a]`\n  - Add a border around the animation using the specified parameters.\n\n- `play, --play`\n  - Replay a frames file in the terminal.\n\n- `record, --record`\n  - Explicitly choose to record (not very useful).\n\n- `compile, --compile`\n  - Explicitly choose to compile (not very useful).\n\n- `screenshot, --screenshot`\n  - Start ttystudio in screenshot mode. It will take a screenshot on `C-p`\n    unless specified otherwise by `--screenshot-key`.\n\n- `--screenshot-key`\n  - Set the screenshot key when in screenshot mode. Default is `C-p`.\n\n- `--version`\n  - Display ttystudio version.\n\n- `-h, --help`\n  - Display help information.\n\n\n## Choosing a new font for your terminal recording\n\nSince ttystudio does not record a GUI, it needs to know which font you want to\nuse (it has no real idea of the font your terminal is using). ttystudio uses\nterminus (ter-u14n/b) by default, but you can change this.\n\nYour font __must__ be in [BDF][bdf] format. Once you have your font ready,\nplace it in the `fonts/` directory in ttystudio and run `$ make`.\nttystudio+pxxl.js will convert the `.bdf` font to a glyph bitmap format in a\njson file, which is what ttystudio uses.\n\n``` bash\n$ cp ~/ter-u12n.bdf ~/ttystudio/fonts/\n$ cp ~/ter-u12b.bdf ~/ttystudio/fonts/\n$ cd ~/ttystudio/fonts\n$ make\n...\n$ ttystudio output.gif --log \\\n  --font ~/ttystudio/fonts/ter-u12n.json \\\n  --font-bold ~/ttystudio/fonts/ter-u12b.json\n```\n\n\n## OSX\n\n[pty.js][pty.js] seems to currently be causing sporadic [input lag][lag] on\nOSX. This is being investigated.\n\n\n## Notes\n\nA special thanks to the folks who developed [pxxl.js][pxxl.js] - a BDF font\nparser. Without them, it would not have been possible to render a reasonable\nlooking font to the output gif/png.\n\n\n## Todo\n\n- More fonts and font formats supported.\n- Antialiased fonts.\n- Emit frames as events in writers.\n\n\n## Contribution and License Agreement\n\nIf you contribute code to this project, you are implicitly allowing your code\nto be distributed under the MIT license. You are also implicitly verifying that\nall code is your original work. `\u003c/legalese\u003e`\n\n\n## License\n\nCopyright (c) 2015, Christopher Jeffrey. (MIT License)\n\nSee LICENSE for more info.\n\n[blessed]: https://github.com/chjj/blessed\n[term.js]: https://github.com/chjj/term.js\n[pty.js]: https://github.com/chjj/pty.js\n[pxxl.js]: https://github.com/remcoder/Pxxl.js\n[tng]: https://github.com/chjj/tng\n[bdf]: https://en.wikipedia.org/wiki/Glyph_Bitmap_Distribution_Format\n[lag]: https://github.com/chjj/pty.js/issues/118\n","funding_links":[],"categories":["JavaScript","Images","Creating GIFs","Terminal Gif Creation","others","Packages","\u003ca name=\"screen-recorder\"\u003e\u003c/a\u003eScreen recorder","包","\\*nix/\\*nux"],"sub_categories":["Gif Creation","OS X","Command-line apps","命令行应用","Media"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchjj%2Fttystudio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchjj%2Fttystudio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchjj%2Fttystudio/lists"}