@banou/ripple

中文文档
0.0.36发布于 2026/11/06MITES Module零依赖构建来源已验证近 30 天下载 4351

Download and stream torrents in your browser

原始使用文档
文档目录6 节
  1. Features
  2. How it is built
  3. Development
  4. Embedding
  5. Privacy
  6. License

Ripple

Download and stream torrents in your browser. Ripple runs a real BitTorrent engine (libtorrent, compiled to WebAssembly) in the page, reaches peers through the FKN relay, and plays a video while it downloads. There is nothing to install and no Ripple server.

Features

  • Add a magnet or a .torrent. Paste it, drop it, or open it from your system once Ripple is installed as an app, which then opens magnet: links and .torrent files.
  • Watch while it downloads, with subtitles, a choice of audio track and a Normalize volume switch.
  • Pick the files you want before the download starts.
  • Keep files in the browser or in a folder on your disk, and save one file, or a zip of several.
  • Create a torrent from files or a folder (v1, v2 or hybrid, private with a source tag, web seeds) and seed it straight from those files.
  • Your library on every device. Signed in to FKN, your list and its thumbnails sync, encrypted in your browser before they leave it.
  • Share links that open the player or a download page, which other sites can embed.
  • One engine for all your tabs. One tab runs it and the others use it.
  • Speed limits for everything or per torrent, and the peers, trackers, files and all-time share ratio of each torrent.
  • No Ripple account and no analytics.

How it is built

  • UI: React 19, routed with React Router 7 and styled with Emotion, in src/router and src/components.
  • Engine: libtorrent-wasm in a Web Worker (src/torrent/worker.ts), driven from the page by src/torrent/client.ts. One tab holds it under a Web Lock and the others reach it over a BroadcastChannel (engine-election.ts, engine-share.ts).
  • Network: @fkn/lib/net and @fkn/lib/dgram, carried through the FKN relay (relayWorker bridges the worker). Inbound peers reach a port the relay reserves.
  • Storage: OPFS, or a folder you grant (src/torrent/hybrid-storage.ts). The list, resume data and thumbnails are in IndexedDB.
  • Player: @banou/media-player at /watch (src/router/embed.tsx), with libav-wasm and jassub.
  • Sync: src/torrent/use-cloud-backup.ts and src/torrent/thumbnail-sync.ts, under ripple/ in the FKN account's storage.

Development

Use Node 24 (.node-version names 24.21.0).

npm ci
npm run dev            # http://localhost:4560
npm run build          # the site and the npm package, into build/
npm test               # unit tests (vitest, node)
npm run test:browser   # component tests in Chrome
npm run typecheck
npm run lint           # vp lint

The Playwright suites build first, then drive the built site in Chrome:

commandwhat it covers
npm run test:e2e:localthe app, needing nothing but the browser (and ffmpeg)
npm run test:e2e:machinelive figures keep their width, which depends on the machine's fonts
npm run test:e2e:swarmthe engine against real public swarms
npm run test:e2e:rigthe whole chain against a local swarm, see tests/swarm-rig

The swarm and rig suites need a headful Chrome, because headless Chromium stalls the engine at 0 B/s. Run them under xvfb-run -a -s "-screen 0 1280x720x24" so no window opens.

A push to main deploys torrent.fkn.app (Cloudflare Pages). When Test passes on that commit and package.json names a version the registry does not have yet, it is also published to npm (.github/workflows/publish-lib.yml). Each published version is signed for FKN with fkn-sign.

Embedding

/watch and /download are the pages another site puts in an iframe. Both take a magnet and the same query; the path chooses which one renders. /watch plays a file, /download delivers files.

paramvaluemeaning
magnetbase64 of the magnet URIthe form to write; permanent
mthe packed magnet, base64urlwhat Ripple's own share links write
fileIndexa file indexthe file /watch plays (the largest video if absent); the fallback /download uses
filesall, 3, 0-4, 0,2,5what /download delivers
languagea BCP 47 tag, such as fr or es-MXthe language of the page and of the player's controls, ahead of the one picked in Ripple (if absent, unreadable, or one they have no text in: the one picked, else the first of the browser's languages they have text in)
audioa BCP 47 tag, or originalthe audio language /watch starts in, ahead of the one last picked in it (original: the file's own)
subtitlesa BCP 47 tag, or offthe subtitle language it starts in, the same way
alwaysSubtitles1 or 00 starts subtitles off when the audio plays in their language

Each audio or subtitle language picked in the player is posted to the framing window as { ripple: 'picked', audio }, { ripple: 'picked', subtitles } (null for off) or { ripple: 'picked', alwaysSubtitles: true }, for the page to start its next media in it.

One of magnet or m is required, and m is read first when both are present. magnet= is the original form and every link written with it keeps working. m= is the same torrent packed into a much shorter link.

/watch?magnet=<base64>&fileIndex=3     plays file 3
/download?magnet=<base64>              the whole torrent
/download?magnet=<base64>&files=3      just file 3
/download?magnet=<base64>&files=0-4    files 0 to 4 inclusive, as a zip
/download?magnet=<base64>&files=0,2,5  those three, as a zip
/download?magnet=<base64>&fileIndex=3  same as files=3

One file is delivered as that file, and more than one as a single .zip. files outranks fileIndex. Indices the torrent does not have are dropped, and a selection that resolves to nothing says so instead of downloading the whole torrent.

A sandboxed frame needs allow-downloads, or the browser drops the download without an error. Leaving out sandbox works too.

<iframe src="https://torrent.fkn.app/download?magnet=..."
        sandbox="allow-scripts allow-same-origin allow-downloads"></iframe>

Why each part works the way it does is in docs/embedding.md.

Privacy

Ripple needs no account and runs no analytics. Your list and your files stay in your browser, or in a folder you choose. Signed in to FKN, your list and its thumbnails sync to your FKN account, encrypted in your browser first. Peers see the FKN relay's address, not yours. The privacy page lists what Ripple keeps (src/router/privacy.tsx).

License

MIT, see LICENSE.

版本与发布记录

@banou/ripple 共发布 36 个版本,首次发布于 2023/12/14;过去 12 个月发布了 30 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.0.36latest2026/11/061 天前
0.0.352026/10/2612 天前
0.0.342026/10/2613 天前
0.0.332026/10/2613 天前
0.0.322026/10/2513 天前
0.0.312026/10/2315 天前

关于 @banou/ripple 的常见问题

@banou/ripple 是什么?

Download and stream torrents in your browser

如何安装 @banou/ripple?

在项目目录运行 npm install @banou/ripple,或使用 pnpm add / yarn add / bun add。

@banou/ripple 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/banou__ripple 是否存在。

@banou/ripple 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@banou/ripple 可以商用吗?

@banou/ripple 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@banou/ripple 的下载量有多少?

根据 npm 官方下载统计,@banou/ripple 在 2026/10/08 – 2026/11/06 这 30 天内被下载 4,351 次,日均约 145 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@banou/ripple 还在维护吗?

最新版本 0.0.36 发布于 2026/11/06(1 天前);至今共发布 36 个版本,其中过去 12 个月发布了 30 个;首次发布于 2023/12/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。