Bun CLI for downloading EchoVideo/Echo360 recordings from all enrolled courses or a selected course.
echomirror uses the Echo360 Cookie header stored in:
./cookies
The file should contain the raw cookie value. Do not include:
Cookie:
To get the cookie:
- Login to Echo360
- Open DevTools → Network
- Reload the page
- Open an Echo360 request
- Copy the
Cookierequest header - Save it to
./cookies
You can also provide it once:
bun run echomirror.ts --token 'COOKIE_VALUE'The value is saved to ./cookies and checked on future runs.
bun run echomirror.ts --help
bun run echomirror.ts --list
bun run echomirror.ts --course 2026_1:comp4403
bun run echomirror.ts --course comp4403
bun run echomirror.ts --all--list shows available course IDs.
--course accepts either the full ID or a unique course code.
Default:
~/Downloads/Docs/uq/{year_sem}/{course}/recordings/{week}_{lecnum}_{lecname}.mp4
Example:
bun run echomirror.ts --all \
--dest '~/Downloads/Docs/uq/{year}/{course}/recordings/{week}_{lecnum}_{lecname}'Available fields:
| Field | Example |
|---|---|
{year} |
2026 |
{semester} |
1 |
{year_sem} |
2026_1 |
{course} |
comp4403 |
{week} |
01 |
{lecnum} |
02 |
{lecname} |
introduction |
{id} |
Echo360 lesson ID |
echomirror keeps a .ledger.json file in the destination root.
Example:
{
"2026_1/comp4403/recordings/01_01_intro.mp4": "lesson-id"
}The ledger links downloaded files to Echo360 lesson IDs.
If the destination template changes, echomirror moves existing files instead of downloading them again.
Configure concurrency with:
ECHO_CONCURRENCY=6
ECHO_HTTP_CONCURRENCY=12
ECHO_SEGMENT_CONCURRENCY=8npm run typecheck
npm test
npm run buildRun directly:
bun run echomirror.tsIf Echo returns expired media links or a 403 response, echomirror reloads the lesson page and retries with fresh URLs.
Skipped recordings show the reason:
SKIP file.mp4 - destination already exists
SKIP file.mp4 - no downloadable video found
This is closer to what a GitHub README should look like: quick start first, details only where needed.