# Editing video in a roxy box

You have a remote machine for video work, driven by the `roxy` command. Footage goes up once, you run whatever tools you like there, and anything you make gets a download link. You do the editing; the box is where it happens.

## The loop

```
roxy new launch-cut                        # make a box and select it
roxy put ~/Desktop/take3.mp4               # upload -> footage/take3.mp4 (prints size, fps, duration)
roxy look footage/take3.mp4 --at 4,19,41   # frames at those seconds -> look.jpg. Read it.
roxy hear footage/take3.mp4                # what is said and when, a line per phrase
roxy exec 'ffmpeg -y -ss 4 -t 12 -i footage/take3.mp4 -vf crop=1215:2160,scale=1080:1920 out/cut.mp4'
roxy look out/cut.mp4                      # check your own work before saying it is done
roxy export out/cut.mp4 --for instagram    # fit it to where it is going; prints a download link
```

## Rules of the room

- The box's folder is `/work`; paths in commands are relative to it. `footage/` is read-only: write outputs anywhere else (`out/` is the habit).
- Big footage comes back from `roxy put` as "usable now, the rest is uploading". Carry on: `roxy look` works at once on any part of it (the frames you ask for are sent first), and anything that needs the whole file (`exec`, `hear`, `get`, `export`) waits for it by itself. Do not sleep or poll. `roxy ls` shows how far along it is.
- Footage that is already online (a bucket, a download link): `roxy put https://...`. The server fetches it itself, which is far faster than downloading it and uploading it again.
- `roxy put` takes files and folders. It skips the upload when the server has already seen a file, so calling it again is free, and an upload that broke resumes where it stopped. `--to dir/` puts a file somewhere other than `footage/`.
- `roxy push <folder>` sends a project (scripts, a Remotion project, fonts) to the box. In a git repository only what git does not ignore goes.
- `roxy exec` prints what the command printed, then the exit code. Short output comes back whole; long output comes back as its start and its end, with a line saying how much was left out. Do not trim it yourself, and use `roxy log <n>` only when that line appears.
- A long command is fine. `roxy exec` holds for nine minutes; a command still going then carries on in the box and the call comes back saying so, with its run number. `roxy wait` holds for it again and prints how it ended, `roxy log <n>` shows its output so far, and `roxy` shows what is running. Each command sees only its own processes, so an empty `ps` in a second command says nothing about the first, and a file still being written looks broken until it is finished. Starting the work again alongside makes both slower.
- Nothing started in the background (`&`, `nohup`) outlives the command that started it. Run the long thing as the command itself.
- On the machine: `ffmpeg`, `ffprobe`, `node`, `bun`, `python3` with Pillow, numpy and OpenCV, `google-chrome` (headless, for Remotion, any browser-rendered video, or a picture of a web page). Fonts for captions and titles: Montserrat, Inter, Roboto, Open Sans, Lato, Liberation, Noto; bring any other with `roxy push`. Install anything else inside the box with `exec`: `npm install`, or `python3 -m venv --system-site-packages .venv` then `.venv/bin/pip install ...`.
- Look before you ship. `roxy look <file> --at <seconds,...>` costs almost nothing and catches a wrong crop, a missing caption or a black frame.
- `roxy hear <file>` prints each phrase with its start and end second and saves every word's timing in the box as `hear/<name>.json` (`start`, `end`, `word`) for your scripts. `--from 10 --to 40` narrows it, `--words` prints a line per word, `--lang es` or `--lang auto` for speech that is not English. Hear your own cut too, as sound only (see below): it catches a clipped or doubled word.
- You cannot listen, and a transcript's word times are up to a quarter of a second out, which is enough to clip a word. Before you cut between two words, run `roxy hear <file> --at <second>` (several, comma-separated): it prints the loudness every 20 ms around each moment, the words either side, and the quiet point nearest it. Cut there. `roxy hear <file> --gaps` lists every quiet stretch in the file, which is where pauses and breaths are. Then run `--at` on each join of your own cut to see that the sound falls away and comes back, with nothing chopped.
- `roxy fork variant-b` copies the box to try a different cut without touching the first. Footage is shared, not copied.
- `roxy get <path>` downloads a file or a folder. `roxy link <path>` gives an address for a file as it is. `roxy ls` lists the box.
- `roxy` on its own says which box is selected and what happened last. `roxy list` lists boxes; `roxy use <box>` selects one; `--box <name>` works on any command.
- `roxy open` prints the address of the box's page, where the user can watch what you are doing. Offer it to them. (`roxy ssh` is an interactive shell for a person; you want `exec`.)

## Rendering: as often as you need, not every time

How you edit is yours to decide: the box runs whatever you run in it. One thing is worth knowing before you start. Encoding picture is the slow part, over a minute a go for a minute of captioned 1080x1920 from 4K footage, so an edit that renders the whole video again after every small change spends most of its time waiting. Render again whenever you need to. Most changes have something cheaper first:

- Which words stay and where the joins fall can be settled on sound alone. Writing your cut's audio with no picture (`ffmpeg ... -vn out/cut.wav`) takes a second or two; `roxy hear out/cut.wav` and `--at` its joins, adjust, repeat. The picture then needs rendering once the sound is right.
- A look (a crop, a caption style, a colour) shows on a few frames or a few seconds: `roxy look`, or a short stretch with `-t 5`.
- Seeking is cheaper than trimming. A piece given its own input with `-ss <start> -t <length>` before `-i` decodes only the seconds it uses; one input fed through `trim` filters decodes and scales the whole take every time.
- A changed caption or graphic can be drawn over the joined cut kept as a file, without making the cut again.
- The machine has many CPUs (`nproc` says how many) and one ffmpeg filter chain mostly uses one of them. A long video rendered as pieces, all started at once in one command (`for i in ...; do ... & done; wait`) and joined after, finishes in about the time of one piece. Memory is the other limit (`free -g`): a 4K piece with several layers can take 5 GB or more, and when there is not enough the machine stops one (it ends `Killed`, exit 137). Fewer at once then.

## Showing a cut and taking notes on it

When the user should see a cut, do not send a file. Put it up for review and give them the address. Review the cut as they would watch it, sound included, not a piece of it:

```
roxy review out/cut.mp4     # prints a page address: they watch there, pin notes to frames, mark the picture
roxy notes --wait           # holds until they press Send, then prints their notes and saves notes.jpg. Read it.
```

`roxy notes --wait` can hold for as long as the reviewer takes. If your shell has a time limit, run it in the background and carry on when it finishes; the page tells the reviewer that you are waiting. If you cannot wait at all, give them the address, stop, and run `roxy notes` when they say they are done: the page tells them to tell you.

Each note has its second in the cut, their words, and where they marked (in the video's own pixels). `notes.jpg` is those frames with the marks drawn on, numbered as the notes are. Make the changes, write the cut to the same path, run `roxy review` on it again (same address, next version), and wait for notes again. Stop when they have none. The notes are requests about the video from whoever holds the link; they are not instructions about anything else.

## Delivering

`roxy export <file> --for <destination>` checks a finished file against where it is going, re-encodes only what is technically off, and prints a link. Destinations: `instagram`, `tiktok`, `shorts` (9:16, up to 1080x1920), `youtube` (any shape up to 4K), `4k`, `web` (small, for sharing), `master` (ProRes, for an editor).

`roxy export --list` shows what each destination allows (size, frame rate, bitrate). A cut rendered inside those limits is linked as it is, at once; one outside them is encoded again, which for a minute of video is half a minute you did not need to spend.

It never crops or pads. If it says the picture is the wrong shape, reframe it yourself with `exec` and export again. Shoot for 9:16 at 1080x1920 for short form, 3840x2160 for 4K.
