How it works
Three things happen here: a video gets produced, an account gets authorized once, and a finished video gets uploaded. Each is a separate command, typed by the operator. Nothing chains automatically, and nothing uploads without being told to.
Producing a video
-
The operator picks a book and saves its cover
From their own library. The cover for that edition is saved by hand into the working folder for that book and language.
-
Text is extracted from the file
From
.epub,.pdfor.txt, into a structured JSON input. Nothing is fetched from the internet at this step. -
runbuilds the videoA language model drafts the script in its own words; a text-to-speech service synthesises the narration; slides are rendered in headless Chrome; ffmpeg assembles the result. Out come the video, an
.srtcaption file, a transcript, a thumbnail and a metadata file. -
The operator watches it
This step has no command. If the result is wrong, it is rebuilt or discarded before anything is published.
short produces a vertical 1080×1920 version with burned-in captions, from the same
source material.
Authorizing an account
Once per platform, and again only if authorization is revoked or expires. The two platforms work differently, because they require different things.
YouTube — loopback, with PKCE
The tool starts a temporary HTTP server on 127.0.0.1, on a random port, and opens
Google's consent screen. Google redirects the authorization code back to that local address,
so it never leaves the machine. The exchange uses PKCE (S256), which means a stolen code is
useless without the verifier held in that process.
TikTok — registered HTTPS callback, copied by hand
TikTok registers the app as a Web platform and requires an HTTPS redirect, so loopback is not
an option. The callback page receives the authorization code and displays it. The operator
copies the URL and pastes it into the terminal, and the tool exchanges the code for a token
from the local machine, talking directly to open.tiktokapis.com.
The callback page is inert by design: it never sees a token, never calls the TikTok API, and stores nothing.
Both paths end the same way: the token exists only on the operator's machine. No server of ours performs the exchange, and none receives the result.
Where credentials are kept
| File | Holds |
|---|---|
.google-oauth.json | Google Cloud client credential, downloaded by the operator |
.google-oauth-token.json | YouTube access and refresh token |
.tiktok-oauth-token.json | TikTok access and refresh token |
.env | TikTok client key and secret |
All four are in .gitignore, so they are never committed. The Google token file is
written with mode 600 where the filesystem honours it.
Publishing
-
The operator runs the publish command
publishfor YouTube,tiktokfor TikTok. Without the--enviarflag, the command only prints what it would send — a dry run by default, upload by explicit request. -
The file is uploaded to the authorized account
To YouTube as a resumable upload, so a dropped connection resumes instead of restarting. To TikTok through the Content Posting API. Either way the bytes go from the operator's machine to the platform, with no intermediate service of ours.
-
Thumbnail, captions and metadata are attached
On YouTube, the custom thumbnail and the caption track are attached to that same video, and the publication time is set. This is the only reason
youtube.force-sslis requested. -
The result is reported to the terminal
Success, or the platform's error. Failures are shown, not retried silently.
updateexists to correct metadata on a video that is already published.
What never happens
- Credentials are never typed into anything built by us — only into Google's and TikTok's own screens.
- No token reaches a server. There is no backend, because there are no other users.
- No video or metadata is retained by us after publishing.
- No account other than the operator's is ever touched.
- Nothing publishes on a timer. A video goes out because a person typed a command with a flag.
The full command list is on the Capabilities page; the data each platform returns is itemised in the Privacy Policy.