{"id":37773732,"url":"https://github.com/scottvr/wtffmpeg","last_synced_at":"2026-02-14T14:07:31.227Z","repository":{"id":305970275,"uuid":"1024559174","full_name":"scottvr/wtffmpeg","owner":"scottvr","description":"a toy that has a local llm spit out ffmpeg commands from natural language prompts on the command-line","archived":false,"fork":false,"pushed_at":"2026-01-15T09:46:25.000Z","size":152,"stargazers_count":321,"open_issues_count":0,"forks_count":11,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-17T01:58:09.621Z","etag":null,"topics":["ffmpeg","llm"],"latest_commit_sha":null,"homepage":"http://blehg.paperclipmaximizer.ai/wtffmpeg/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scottvr.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-22T22:38:32.000Z","updated_at":"2026-01-15T09:46:30.000Z","dependencies_parsed_at":"2025-07-23T00:39:41.543Z","dependency_job_id":null,"html_url":"https://github.com/scottvr/wtffmpeg","commit_stats":null,"previous_names":["scottvr/wtffmpeg"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/scottvr/wtffmpeg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fwtffmpeg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fwtffmpeg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fwtffmpeg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fwtffmpeg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scottvr","download_url":"https://codeload.github.com/scottvr/wtffmpeg/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fwtffmpeg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29446440,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T12:43:28.304Z","status":"ssl_error","status_checked_at":"2026-02-14T12:43:14.160Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["ffmpeg","llm"],"created_at":"2026-01-16T14:56:44.325Z","updated_at":"2026-02-14T14:07:31.222Z","avatar_url":"https://github.com/scottvr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wtffmpeg - natural language to ffmpeg\nwithout the chat UI inconvenience\n\n## TL;DR (breaking CLI change, but the good kind)\nA snapshot of v0.1.0 was tagged as 'alpha' from the main branch. If you don't want to switch to the current (as of Feb 2026) beta release, you can pull that 'alpha' tagged release, or download tarballs or zips of it from github.\n\n- The old `-i` / “interactive mode” is now the **default**.\n- Running `wtff` with no arguments drops you straight into a REPL.\n- This is intentional. A command-line tool should behave like one.\n\nIf you previously used `wtff \"some prompt\"`: that still works, but now it **preloads context and then drops you into the REPL** instead of exiting immediately. If you truly want a single-shot, non-interactive invocation, there is a flag for that (see below).\n\n---\n\n## WTF is this?\n\n`wtffmpeg` is a command-line tool that uses a Large Language Model (LLM) to translate plain-English descriptions of video or audio tasks into **actual, executable `ffmpeg` commands**.\n\nIt exists to eliminate this workflow:\n\n1. Search Stack Overflow\n2. Read a 900-word explanation\n3. Copy/paste a command\n4. Fix three flags\n5. Repeat. (And repeat the entire workflow the next time you need to do something new.)\n\nInstead, you say what you want, review the generated command, optionally edit it, and then decide whether to run it.\n\nThe command is the point. The REPL was the intent. Truth is, that even as a capable long-time user of ffmpeg, even when I have historically arrived at very complicated ffmpeg command-lines or piped-together chains of commands, or long batches of them intersperse throughout bash logic, there are very few things I get right every tiime. \n\nffmpeg usage is often very much a process of running many different *almost right* commands, and altering the input options and flags and varying them until arriving at one or more commands that will no doubt be preserved in text documents or shell scripts for the user to refer to later.\n\nIt is often the case that I will spend a lot of time learning how (and how not) to accomplish some specific thing , and then *never* need to do that exact thing again. \n\nSo, if I am honest, I will admit that *every* ffmpeg session that accomplishes anything useful or meaningful, is already an exercise in up-arrow, command-history editing, and evolving mutating things you know how to accomplish, until you eventually arrive at a way to accomplish the thing you set out to do.  So, if I ackowledge that is true, then using a REPL for ffmpeg that is often correct, often nearly correct, \"learning\" and changing tactics throughout the process seems a natural fit.\n\nffmpeg usage, for me, is already very non-deterministic. ffmpeg is just enormously powerful, and its list of capabilities and ways to affect their outcome is immense.\n\n`wtffmpeg` is an auxillary tool for *using* ffmpeg. The ability of your command history and your knowledge, to couple directly in a command-line interface, while the model's responses are shaped and improved throughout your experimental session, actually makes this thing I made as a joke  into something I now haave an obligation to improve and maintain because  - approve of  it on moral grounds or not, be offended by it on intellevtual grounds if you care to be -  but ffmpeg cli configurator and experimental command lab assistant is a perfect use case for an LLM.\n\nI initially shipped `wwtffmpeg` as a tiny REPL app with a huge system prompt that was actual more valuable as a cheat sheet than a generalizable input for LLMs to \"be good at ffmpeg\".\nIt by default used Phi, and then slowly and inadvertantly through trial and error, I  arrived at system prompt was a necessary artifact of model capability constraints, and served essentially as *finetuning by transcript*. For a small local model. Because doing so was simultaneously ludicrous and undeniably useful.\n\nWith the updates to this branch, the default system prompt could likely be a hindrance to a SoTA model. This is why it is being retired to a profile labeled \"cheatsheet' in this release, along with a handful of other profiles enabled by the new `--profile \u003clist\u003e`, where \u003clist\u003e is a plain-text file pointed to by an avsolute path, or a \"profile name\" if you want to use a profile from youe wtffmpeg profile directory. Anyway, some (een the v0.1.0 Phi-tailored joke of a prompt) are shipped in the repo, but in the end it's just text, so you are free to use whatever you choose.\n\n---\n\n## Examples\n\n```bash\n$ wtff \"convert test_pattern.mp4 to a gif\"\n\n--- Generated ffmpeg command ---\nffmpeg -i test_pattern.mp4 -vf \"fps=10,scale=320:-1:flags=lanczos\" output.gif\n-------------------------------\nExecute? [y/N], (c)opy to clipboard:\n```\n\nIf you say y, it runs.\nIf you say c, it copies.\nIf you say anything else, nothing happens.\n\nYou stay in the REPL. As I just stream-of-consciousnesseed a lot of words on  the topic of, it's ;iterally the point.\n\nRunning\n```\nwtff\n```\nIt drops you into an interactive session where importantly:\n- Up/down arrow history works.\n- Left/right editing works.\n- History is persisted to ~/.wtff_history.\n- Each turn builds conversational context unless you tell it not to.\n\nThis is the intended interface.\n\n----\n\nSpme people seem to prefer sending their first return stroke to the LLM at the ti,e of command invocation. I don't know why, but to preserve their workflow, you can one-shot yourr request the way many people seem to do today, which is like:\n\n```\nwtff \"turn this directory of PNGs into an mp4 slideshow\"\n```\nThis works, but it is essentil just \"preloading your first request to the LLM. You aew still dropped into the hopefully now-pleasant REPL workflow.\n\nIf you really want single-shot, stateless execution, you can pass `--prompt-once`\n```\nwtff --prompt-once \"extract the audio from lecture.mp4\"\n```\n\nThis does not retain context. It generates once, then:\n\n- prints the command\n- optionally copies it\n- optionally executes it\n- exits\n\nThis is intentionally boring and predictable.\n\n----\n\nBt default wtffmpeg's REPL retains conversational context, as well as command history, but you can control or disable tthat.\n\n```\nwtff --context-turns N\n```\nwhere N is a number greater than or equal to zero that represents the number of conversational turns you'd like to keep in context, with 0 effectively making the REPL stateless, and higher numbers  imdicating a greater number of pairs of prompt/response (as well as growing to eat more RAM, tokens, etc, and eventually bringing your LLM to a point of struggling to appear coherent, but you are free to set this to whatever number is best for you. It defaults to 12.\n\n## Installation\nWhen random Internet user were clersly getting more excitement out of wtffmpeg than I was, I tended to accept PR's that were of little obvious value to me, but I accepted someone's initial OPENAI API integrations, and maybe more than one installation method I felt e3re unnecessary since it has had a pyproject.toml since day one and ccould be installed with then pip, pipx, or uv, and it would install a stub, in the bin or scripts directory of your system of venv Python path. One patch included a documentation change describing how to symlink wtffmpeg.py into a system path so you can access it by typing `wtff` from any command-line. That was literally a feature I shipped on day 1 via the `setuptools` innate scripts mechanism. But, as I said, these people were actually wanting to use wtffmpeg so who am I to deny them joy or explain that the feature was already there and documenteed. *shrug*\n\nBut after I'm now finding auto-generated LLM video slop (it's literally just a screenshot of a browser loading the wtffmpeg github repo browser render of README.md with a low-rent verion of a NotebookLM-style \"podcast\" for audio.  It's funny. And sad. But also someone wrote in a newsletter calling `scottvr/wtffmpeeg` \"Repo of the Week\". A corporate marketing/tutorial video on how to use their synthetic data and partially-automated model/prompt pairing combination and pricing tool referred kindly to wtffmpeg, and kept a browser tab to the repo open throughout the video. (Sadly, he also showed the aforementioned silly-but-working on Phi prompt, and unsurprisingly ChatGPT could outperform the wtffmpeg jokey prompt with one that it wrote itself.)) But also... an this *was* surprising: the maker of the video actually went out of his way to acknowledge that in some cases wtffmpeg's ludicrous prompt actually worked better! Using Phi. (LOL)\n\nBut I digress. Where were we? Oh yes, installation. Just do this:\n```\ngit clone https://github.com/scottvr/wtffmpeg.git\ncd wtffmpeg\npip install -e .\n```\n\n(or pipx, if that's your preference. Or `uv pip install` if you like. But really, this just works and doesn't need incremental changes to the process. Maybe I will toss it up on PyPi, once the modularization refactor is complete. But regardless, just `pip install` it from source, amd `wtff` command will just work without any symlinking or special installer support needed. That is to say, that I'm taking the project on again, at least for a bit, and hopefully you will all find it useful. If not, it is opern source and you are free to fork it and shape it how you think it should be, but I might argue there are much better and more appropriate projects to fork a project from, that one that was ludicrous architecture by design and intent, and was simultaneously actually useful and fun, while being the most polarizing thing I've ever done on the Internet at large. \n\n---\n\n# Configuration\n\n## Environment Variables.\nThese were graciously implemented by someone in the community. Thanks.\n\n- WTFFMPEG_MODEL: You can (but don't have to) specify a model name here. e.g, llama3, gpt-4o, codellama:7b)2\n- WTFFMPEG_LLM_API_URL: Base URL for a local or remote OpenAI-compatible API\nDefaults to http://localhost:11434 (Ollama)\n- WTFFMPEG_OPENAI_API_KEY: What else would this be? :-)\n- WTFFMPEG_BEARER_TOKEN: Bearer token for other OpenAI-compatible services.\n\n## CLI optional arguments\n```\nusage: wtff [options] [prompt]\n\n--model MODEL           Model to use\n--api-key KEY           OpenAI API key\n--bearer-token TOKEN    Bearer token for compatible APIs\n--url URL               Base API URL (OpenAI-compatible)\n--prompt-once           Single-shot, non-interactive mode\n--context-turns N       Number of turns of context to retain\n-x, -e, --exec          Execute without confirmation\n-c, --copy              Copy command to clipboard\n```\n\nThere's stil a few to document and a few others I haven't gotten around to implementing yet.\n\nThe old `-i` flag is accepted but ignored. Interactive is the default now.\n\n----\n\n### Inside the REPL \nLines starting with ! are executed as shell commands:\n```\n!ls -lh\n!ffprobe input.mp4\n```\n\nThese are just for convenience. You cannot, for example, `!chdir` and actually change your REPL process dir. (Though convenient `/cd` (slash commands) may be a thing soon.)\n\n----\n\n# Disclaimer\n`wtffmpeg` started as something I built to amuse myself. It accidentally became useful.\n\nIt executes commands that can destroy your data if you are careless.\nAlways review generated commands before running them.\n\nYMMV. Use at your own risk. I assume you know what ffmpeg can do.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottvr%2Fwtffmpeg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscottvr%2Fwtffmpeg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottvr%2Fwtffmpeg/lists"}