# Terminally Addicted — video, audio, and everything else in a terminal

By Arya Garg

Canonical source: https://aryagarg23.com/writing/terminally-addicted

Archive date: 2024-10 (historical site date; not a verified publication date)

Register: Technical

Tags: HACK

Section: [Hackathons](https://aryagarg23.com/about#hackathons)

## Main

At HackOHI/O, Raihan Rafeek, Kaaustaaub Shankar and I wanted to make a joke. Then we decided the joke should be unnecessarily difficult to build.

Terminally Addicted put Spotify, GitHub issues, Todoist, GPT chat, Vim and YouTube inside one curses-based terminal. The YouTube player drew the video as ASCII and terminal colour while the audio played normally. I'm not going to argue this is the best way to watch YouTube, because it's worse.

My part of the project was mostly the architecture. I wanted to keep bolting unrelated pieces onto the same system without each new piece breaking the old ones or slowing the whole thing down. Spotify is one kind of state, GitHub issues are another, and a chatbot has its own interaction pattern. Then video shows up, and now you have screen ownership, input ownership, a renderer, audio, timing, cleanup and background work all fighting inside one terminal.

We won Most Original.

## Technical

| Terminally Addicted shell |
| --- |
| Python / curses shell |
| ↓ |
| Spotify API ‖ GitHub REST API ‖ Todoist API ‖ OpenAI chat ‖ Vim ‖ YouTube |

| Terminally Addicted YouTube playback |
| --- |
| yt-dlp |
| ↓ |
| Decoded video frames |
| ↓ |
| Go ASCII renderer |
| ↓ |
| Terminal frames ‖ Audio playback |
| ↓ |
| Sync loop |
| ↓ |
| Curses UI restored |

![Every command surface in one terminal window](https://aryagarg23.com/figures/terminally-addicted/command_map.png)

Python and curses ran the main terminal interface and command routing.

$sp controlled Spotify. $git created, closed and commented on GitHub issues. $todo connected to Todoist. $chat used the OpenAI integration. /set env opened the environment config in Vim.

For video playback, yt-dlp fetched the media. Video frames went to a Go renderer that turned pixel information into ASCII characters and terminal colour values. Audio playback ran separately.

The renderer and the audio path were kept in sync while the curses shell kept managing terminal state and input. Playback cleanup handed screen and input ownership back to the shell when playback ended or got interrupted.[^terminally-addicted-technical-1][^terminally-addicted-technical-2]

[^terminally-addicted-technical-1]: [Terminally Addicted repository](https://github.com/Aryagarg23/Terminally-Addicted)

[^terminally-addicted-technical-2]: [Demo](https://www.youtube.com/watch?v=SqKeySB5aBU)
