Skip to content
rigaz29Public
forked from troke12/odm

About

Segmented, resumable download manager for Windows, Linux and macOS: multi-connection transfers, queues and scheduler, browser integration. Written in Go.

Resources

Stars

4 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

Ochi Download Manager (ODM)

A segmented, resumable download manager for Windows, Linux and macOS, written in Go. ODM opens several connections per file, resumes at the exact byte where a transfer stopped, and organizes downloads into categories and scheduled queues. It also downloads torrents and magnet links. It runs as a desktop app, or headless with a JSON API.

ODM on Windows: the main window with downloads running, and one download's progress window

Features

Downloading

  • Up to 32 connections per file using Range requests (8 by default), with per-server overrides. The first connection opens immediately. Another opens once any connection stores file bytes after the last one opened, up to the configured limit, so one slow connection does not hold the rest back and a server that refuses is not asked on more. Several connections use HTTP/1.1, one socket each. A single stream can still use HTTP/2.
  • An idle connection takes half of the chunk that will take the longest to finish, when that chunk will take at least twice as long as the fastest one. Until a pace is known, it takes half of the largest remaining chunk. A connection's pace falls while it receives nothing, and one with no first byte after a second counts as stalled, so a hung connection's work is the first handed out.
  • Resume after a pause, crash or restart from the exact byte offset. If a link expires, give the download a new address and it continues where it stopped, as long as the new address serves the same file.
  • Range requests ask for the raw bytes (Accept-Encoding: identity), even over an Accept-Encoding set on the download, so a compressed response is not written in place of the file.
  • A connection that closes before its chunk is finished retries from the last byte written. A server that caps each response (1 MiB at a time, say) still finishes the file: only attempts that store nothing count toward the retry limit.
  • A file's server may take up to 5 minutes to start answering, for files it builds on demand (archives, exports); once bytes flow, 30 seconds without any counts as a stall and the connection is tried again. Playlists, keys and pages keep a 30 second limit.
  • A saved ETag or Last-Modified is sent as If-Range on resume (a weak ETag never is: Last-Modified stands in, as servers answer a weak one with the whole file). If the file on the server has changed, the partial download is discarded and started again from the first byte. A 200 for a range that already covers the whole file is kept when that validator still matches.
  • A later chunk re-reads a short stretch of the chunk before it. If the two copies differ, the rest of the file is fetched on one connection. If that copy still differs, the partial file is discarded and the download starts again from the first byte, once: a later disagreement, after a pause or a restart too, fails the download instead of starting over again.
  • A server that answers a smaller range with the whole file keeps bytes already stored. The remainder is fetched on one connection; when the first chunk got the whole file, that answer is kept and runs to the end instead of being asked for again.
  • Servers that do not support ranges are fetched on a single stream.
  • Global and per-download speed limits, plus an optional data cap per time window. The global limit is switched off and on from the status bar (the Downloads menu on Linux and macOS) or the tray, and keeps its value while off.
  • HTTP and SOCKS5 proxies, or the system proxy (the default).

Organizing

  • Files are sorted into category folders (Video/, Audio/, Documents/, …), and each category can have its own destination folder. Categories and the file types they take can be added, deleted and changed.
  • The New Download window remembers the save folder chosen last time, and falls back to the default folder when that one is gone.
  • Named queues with a run order. Each queue can download a set number of files at once. A synchronization queue checks its finished files against the server and downloads the ones that changed again, replacing the local copy.
  • A scheduler per queue: start with ODM, start at a set time (once or on chosen weekdays), start again every so many minutes until stopped, stop at a set time, retry failed files, and open a file, exit, sleep, hibernate or shut down when the queue finishes (after a 30-second countdown that can be cancelled).
  • ZIP preview: the files inside a ZIP archive are listed before it is downloaded, reading only the end of the archive.
  • Site logins (HTTP Digest or Basic, sent only to a host that asks), import and export of the download list, and a site grabber that crawls a page and queues the files it links to.
  • A new download never replaces an existing file: if the name is taken, it is saved as name (2).ext. Adding a link that is already in the list asks first, or follows a setting for the browser, clipboard and grabber.

Torrents

  • Magnet links and .torrent files, by address or from the disk (⋯ → Open .torrent file…, or dropped on the window), open the New Download window. A magnet link first gets its list of files from its peers, the number connected shown meanwhile. Then the files can be ticked one by one, each with a priority (high, normal or low), next to the folder, category and queue.
  • Torrents run in odm-libtorrent, a small companion program on libtorrent (helper/libtorrent). ODM downloads it the first time a torrent needs it (about 4 MB, from ODM's own releases, checked against its SHA-256), asking first unless automatic downloads are on. It keeps it with yt-dlp and ffmpeg. Being a program of its own keeps ODM.exe in Go alone, and a crash there stops the torrents, not ODM.
  • Files are written under name.odmpart until the torrent is complete; a torrent of several files becomes a folder.
  • A finished torrent seeds, outside its queue's slots, until it uploaded as much as its size or for 30 minutes, whichever comes first. Options → Torrents changes the ratio and the time, or seeds never or until stopped, and a torrent can have its own target in its progress window (Options on completion); one that stopped seeding seeds again when its new target wants more. Stop seeding is in the list's menu and the progress window.
  • The progress window shows the peers and seeds, what was uploaded and the ratio, the pieces, and each file. Until the torrent is complete, a file can be left out or taken in again there, or given another priority; a file left out keeps what it had downloaded. Once it is complete, a file it left out can still be ticked: the torrent downloads it into its folder and is complete again. The list marks a seeding torrent and its upload speed.
  • The same torrent is not added twice: ODM knows it by its info hash, from a magnet link in any form or a .torrent file, wherever it came from. New Download says it is in the list already and shows it; it can be downloaded again once the first is complete and no longer seeding.
  • Options → Torrents also has the port (picked at random once), incoming connections, opening the port on the router (UPnP, NAT-PMP), an upload limit, and whether an address that turns out to be a .torrent file is downloaded as the torrent (the default) or as the file.
  • On Windows ODM offers itself for magnet links and .torrent files, for the current user: it is listed in Settings → Default apps, and when no program opens magnet links yet, it becomes the one that does. Windows keeps the choice of the program. Options → Torrents turns this off, and removes what ODM registered. Not yet on Linux and macOS.
  • The first time a torrent runs, Windows' firewall asks whether odm-libtorrent may use the network. Allow it on private networks, so that peers can reach ODM; without it torrents still download, from fewer peers.
  • Peers and trackers see your IP address. A SOCKS5 proxy (Options → Proxy / Socks) carries every torrent connection; an HTTP proxy or the system's only reaches trackers. Some ISPs slow down or block torrent traffic. Downloading or sharing copyrighted material through torrents can be against the law; that is up to you.
  • The Fyne build (-fyne archives) has no torrent windows.

Desktop

  • A main window with categories and queues at the side, a card for each running download (speed over the last minute, its connections, time left), and a list that sorts, resizes and hides its columns, selects several rows, and stays quick with thousands of downloads. The search box (Ctrl+K) filters the list, takes a pasted address, and runs any command by name.
  • A progress window per download that shows each connection, and a dialog when a download completes.
  • Light and dark themes that follow Windows or are chosen in Options, in English or Indonesian.
  • Narrator and other screen readers read every part of the windows, and the keyboard reaches all of it (in the list: the arrows to move and select, the Menu key for a download's menu).
  • Runs from the system tray, with the system's notifications when a download finishes or fails. ODM can launch at login, and starting it again brings the running window forward.
  • Checks GitHub Releases for new versions. It only notifies; it never updates itself.
  • The windows are a page drawn by the system's web view (Wails): Microsoft Edge WebView2 on Windows, WebKitGTK on Linux and WebKit on macOS. ODM's previous windows, built with Fyne and with the same features, remain as a build for older Linux distributions.

Integration

  • A browser extension (Chrome, Edge, Firefox) hands downloads to ODM through native messaging, and opens them in a New Download window where you choose the folder and name, and for a stream the quality and audio track. ODM can register itself with each browser.
  • A Download this video button appears over a video player when the extension sees the page load a video or audio file. It names the file after the page title. Streams split into many segments (HLS/DASH) are downloaded segment by segment in the quality you pick (the best by default); separate video and audio tracks are joined with ffmpeg if it is installed (next to ODM, on PATH, or chosen in Options > Downloads, which also shows the ffmpeg version ODM found). A live stream (HLS, DASH, or one endless response such as FLV) is recorded until you stop the download (Pause or Stop), the broadcast ends, or nothing new arrives for a while. Facebook and Instagram broadcasts are recorded from the manifest their signed-in player loads. A result in MPEG-TS becomes MP4 when it finishes (copied, not re-encoded; Matroska when the streams do not fit MP4). DRM-protected video is not supported and never will be.
  • On YouTube (watch pages, Shorts, embedded players) the button lists the video's qualities and audio-only formats as yt-dlp reads them, and ODM downloads the one you pick through yt-dlp, with its progress, pause and resume. A YouTube address pasted into New Download works the same way. yt-dlp reads the page itself and signs in to the site as you, as YouTube asks of some visitors ("Sign in to confirm you're not a bot"): by default with the cookies of the browser you download from, which works in any browser with ODM's extension, Chrome included. The extension sends the site's cookies with the page, and ODM keeps them in memory for yt-dlp, which gets them in a cookie file removed after each run. Options → Programs ("Sign in to video sites with the cookies of") turns this off, or names a browser whose cookies yt-dlp reads itself instead, which works with Firefox; Chrome and other Chromium browsers lock their cookies while open, and recent Chrome encrypts them. When yt-dlp cannot list a video's qualities, the button's menu says why.
  • A broadcast on such a page (YouTube Live, Twitch, TikTok and others yt-dlp reads) shows "● LIVE" with a Record row per quality. ODM records the playlist or stream yt-dlp finds with its own recorder, from the click until you stop it, and asks yt-dlp for a fresh address when the old one expires. A live stream sent as one endless response (TikTok's FLV, which the button also offers when the player loads it) is recorded in parts that ffmpeg joins into one MP4.
  • yt-dlp and ffmpeg need no installing. The first time one is needed, ODM asks whether it may download them (about 20 MB): yt-dlp from its own releases, and a small ffmpeg built for ODM that only copies streams between containers (scripts/ffmpeg-min.sh, published by the ffmpeg-min workflow, LGPL). Each is checked against the SHA-256 its release lists, kept in %LocalAppData%\odm\tools, and updated silently once a day. Options > Downloads turns this off, updates them now, or points at copies of your own, which ODM otherwise also finds next to it or on PATH.
  • The extension's toolbar icon counts the media a page has loaded, and its popup lists them (from every frame) for players the button cannot find.
  • The extension's Download with ODM on a magnet: link hands ODM the torrent, and a .torrent file the browser starts to download goes to ODM as a torrent.
  • A clipboard monitor queues downloadable URLs you copy, and magnet links. You can turn it on or off at any time.

Install

Once a version is tagged, prebuilt archives are attached to GitHub Releases:

Platform Archive
Windows x64 odm-windows-amd64.zip
Linux x64 odm-linux-amd64.tar.gz
Linux ARM64 odm-linux-arm64.tar.gz
Linux x64, older distributions odm-linux-amd64-fyne.tar.gz
Linux ARM64, older distributions odm-linux-arm64-fyne.tar.gz
macOS (Apple silicon) odm-darwin-arm64.tar.gz
macOS (Intel) odm-darwin-amd64.tar.gz

Unpack the archive and run ODM.exe (Windows) or ./odm (Linux, macOS).

On Windows ODM needs the Microsoft Edge WebView2 Runtime. It comes with Windows 11 and with Windows 10 kept up to date; where it is missing, ODM says so and offers Microsoft's download page.

On Linux ODM needs GTK 4 and WebKitGTK 6.0 (the libwebkitgtk-6.0-4 package on Debian and Ubuntu, webkitgtk6.0 on Fedora), which Ubuntu 24.04, Debian 12, Fedora 39 and later have. On older distributions, such as Ubuntu 22.04 or Linux Mint 21, take the -fyne archive: ODM's previous windows, built with Fyne, with the same features. On GNOME the tray icon needs the AppIndicator extension.

On macOS open ODM the first time with right-click → Open, since it is not signed. It shows no notifications there, since it is not an .app.

On Linux and macOS the windows run as they are, not polished yet: they keep the system's window frame and label shortcuts Ctrl. Settings and download state are stored in <config>/odm/. <config> is %AppData% on Windows, ~/Library/Application Support on macOS and ~/.config on Linux.

Build from source

ODM needs Go 1.25 or later. The engine uses only the standard library. The desktop UI (internal/gui, the gui build tag) is a React page embedded in the program, so its page is built first with Node.js 22 or later. On Windows it needs no cgo; on Linux and macOS it does. The previous UI, built with Fyne behind the fyne build tag, needs cgo everywhere.

Target Command Requirements
Windows ./scripts/build.sh windows Node.js and npm
Linux ./scripts/build.sh linux Node.js and npm, libgtk-4-dev libwebkitgtk-6.0-dev
macOS ./scripts/build.sh darwin (or darwin-intel) Node.js and npm, Xcode command line tools
Linux, Fyne UI ./scripts/build.sh linux-fyne libgl1-mesa-dev xorg-dev libxkbcommon-dev
macOS, Fyne UI ./scripts/build.sh darwin-fyne Xcode command line tools
Windows, Fyne UI ./scripts/build.sh windows-fyne mingw-w64 (CC_WINDOWS, default x86_64-w64-mingw32-gcc)
Headless ./scripts/build.sh cli none
go test ./...                                    # engine tests, no UI needed
(cd internal/gui/frontend && npm ci && npm test && npm run build)  # the desktop UI's page
go test -tags gui ./internal/gui ./internal/i18n # the desktop UI's Go side (cgo on Linux and macOS)
go build -tags gui,production -ldflags -H=windowsgui -o ODM.exe ./cmd/odm  # Windows desktop build
go build -tags gui,production -o odm ./cmd/odm   # Linux or macOS desktop build
go test -tags fyne ./internal/ui                 # Fyne UI tests (cgo)
go build -tags fyne -o odm ./cmd/odm             # Fyne desktop build for the current OS

scripts/winres.sh rebuilds the Windows resources linked into every Windows build (manifest, icon, name) when one of them changes.

Usage

ODM.exe                                  # open the app
ODM.exe -hidden                          # start in the system tray
ODM.exe -add https://host/big.iso -no-ui # fetch one URL in the terminal, then exit
ODM.exe "magnet:?xt=urn:btih:…"          # open a magnet link (or a .torrent file) in New Download
Flag Meaning
-dir, -conns, -files Override the download folder, connections per file, and simultaneous downloads
-add URL Download one URL headless and exit
-no-ui, -open Run without a window / control whether a window opens
-hidden Start in the tray (used by launch-at-login)
-serve, -addr Also serve the web UI and API on -addr (default 127.0.0.1:8721)
-register-browser, -unregister-browser Register or remove the browser native host
-version Print the version
a magnet link or .torrent file Open it in the New Download window, in the running ODM if there is one

Keyboard shortcuts (main list): Ctrl/Shift+click to select several downloads, Ctrl+A to select all, Del to remove, Enter to open the progress window, arrow keys to move, Ctrl+N to add a URL, and Ctrl+F to search. The search box keeps the downloads whose file name, address or description contains every word typed; Esc clears it. On Windows, also Ctrl+K for the search box, which runs commands by name as well, Space to pause or resume, Shift+Del to remove and delete the files, Ctrl+C to copy the addresses, and the Menu key or Shift+F10 for the selected download's menu. On macOS, use Cmd instead of Ctrl.

Notifications. A system notification says when a download finishes or fails, unless its complete dialog was just shown while ODM is in front. On Windows, ODM can also play the system sound for these events. Both are in Options → Downloads.

Tray and start-up. Closing the window hides ODM in the tray, and downloads keep running. Options → General controls close-to-tray and Launch ODM on startup. Launch-at-login is registered for the current user only: the Run key under HKCU on Windows, an XDG autostart entry on Linux, and a LaunchAgent on macOS. On Linux desktops without a tray (for example GNOME without an AppIndicator extension), the icon may not appear. Starting ODM again still shows the window.

Proxy. Options → Proxy / Socks offers three choices:

  • No proxy.
  • System settings (the default): the HTTP(S)_PROXY variables, and on Windows also the proxy set in Internet Options. Automatic configuration (PAC) scripts are not evaluated.
  • A manual HTTP or SOCKS5 proxy.

Browser integration

  1. Start ODM once: it registers itself with Chrome, Edge, Chromium and Firefox. Options → General shows the status. (ODM.exe -register-browser does the same from a shell.)
  2. Install the extension. On Windows, ODM's Setup window (it opens at the first start; later ⋯ → Help → Set up ODM…) lists your browsers and installs it in each: Firefox asks to add the signed add-on, and for Chrome, Edge, Brave or Opera it gives the folder to load and the steps. It installs yt-dlp and ffmpeg too. Or from the release:
    • Chrome, Edge, Brave, Opera: unzip odm-extension-chromium.zip, then Developer mode → Load unpacked in chrome://extensions.
    • Firefox: open odm-extension-firefox.xpi (signed by Mozilla).
  3. Restart the browser once.

extension/README.md has the details, including where the registration is written on each OS.

Security model

ODM opens no TCP port by default. A running instance listens on a Unix domain socket in the user's config directory (odm.sock). Torrents are the exception, while one runs: odm-libtorrent then listens on the torrent port (TCP and UDP, on every interface) for peers, and asks the router to open it (UPnP, NAT-PMP). Options → Torrents turns either off, and it stops a minute after the last torrent. Trackers and web seeds on this computer or the local network are dropped from a torrent that came from the internet, so a torrent cannot make ODM reach local services. The browser relay uses this socket, and it also stops a second copy of ODM from starting. Web pages can send requests to 127.0.0.1 but cannot reach a socket file, so websites you visit cannot reach the API. The socket needs Windows 10 version 1803 or later. Without it, ODM still runs, but browser hand-off is disabled.

-serve exposes the web UI and API over TCP. That listener requires a random token generated at each start and printed at start-up. Opening /?token=… sets a SameSite=Strict cookie; scripts send the X-ODM-Token header. Requests from any other Origin are refused.

Headless mode and HTTP API

Builds without the desktop UI (./scripts/build.sh cli), or runs with -serve, serve a basic web UI and this JSON API. The web UI covers adding, pausing and removing downloads, and adds a .torrent file from the computer it runs on (.torrent… in New Download, or dropped on the page). Scheduler and most Options are desktop only.

Method Path Purpose
GET / PUT /api/settings Read or update settings (applied immediately)
GET / POST /api/downloads List downloads, or add {"url","dir","connections","headers","speed_limit"}; a magnet link is a torrent, and "torrent": true makes a .torrent address one
POST /api/torrents Add a .torrent file sent as multipart/form-data in the field torrent, with dir, file_name, category, queue, description and start (false adds it stopped)
GET / DELETE /api/downloads/{id} One download; DELETE ?file=true also deletes the file
GET / POST /api/downloads/{id}/files A torrent's files (index, path, size, done, priority), or change them: {"priorities": {"<index>": 0}} leaves one out, 1 is low, 4 normal, 7 high
POST /api/downloads/{id}/seed A torrent's own seeding target: {"mode": "", "ratio": 200, "minutes": 60} (until a ratio or a time), "never", "forever", or "options" to follow the Options
POST /api/downloads/{id}/pause | /resume | /retry | /open | /reveal | /stop-seeding Control a download
POST /api/downloads/{id}/limit | /options Per-download speed limit / open-when-done
GET /api/probe?url= Size, type and file name of a URL without adding it
POST /api/probe/stream Qualities of an HLS/DASH playlist {"url","headers"}; an add with "stream" takes one as "quality"
POST /api/probe/site Qualities yt-dlp finds at a video page {"url"} (503 "missing" without yt-dlp); an add with "site": true takes one's "format"
POST /api/actions/pause-all | /stop-all | /resume-all | /clear-completed Batch actions (stop-all also stops started queues)
GET /api/events Server-Sent Events stream of the list

How a download works

  1. Probe. A ranged GET bytes=0-0 returns the file size, range support, file name, cookies and validators.
  2. Plan. The file is split into up to N chunks of at least 64 KiB. A tiny last chunk is merged into the one before it.
  3. Transfer. Workers write each chunk into the .odmpart file at its absolute offset. Each range request asks for the raw bytes. With more than one connection the requests use HTTP/1.1, so each connection has its own socket. The first connection opens immediately. Another opens after every connection already running has stored file bytes, up to the configured limit. A worker that finishes early takes half of the chunk with the most time left, when that chunk will take at least twice as long as the fastest one. Until a pace is known, that is the largest remaining chunk. Bytes past that chunk's new end are left for the connection that took them. A connection that receives no bytes for 30 seconds, including while it waits for response headers, is closed and that chunk is retried from the last byte written. The other connections keep going. If the server answers a smaller range with the whole file, bytes already stored are kept and the remainder is fetched on one connection.
  4. Finish. The .odmpart file is renamed to the final name.

Each chunk's progress ({id,start,end,done}) is saved as JSON, together with the ETag and Last-Modified from the probe, so a restart continues from the exact byte while the file on the server is unchanged. If If-Range fails, or a later probe reports a different validator or size, ODM deletes the partial file and downloads the new one. A 200 for a range that already covers the whole file is kept when the validator still matches. A chunk that starts after another one also reads 64 bytes of that earlier chunk and compares the two copies. When they differ, the other connections stop and one connection finishes from the last matching byte. If that copy differs as well, the partial file is deleted and downloaded again from the first byte, still on one connection. A resume after this fallback stays on one connection. Segmented ranges, byte-offset resume and chunk splitting are standard download-manager techniques. ODM implements them in its own code.

Project layout

cmd/odm             entry point: desktop app, native-messaging relay, headless mode
internal/engine     probe, chunk planner, transfers, queues, scheduler, settings, state
internal/gui        desktop UI (Wails: WebView2, WebKitGTK, WebKit): the service, tray and windows; the React page in frontend/
internal/ui         previous desktop UI (Fyne), kept for older Linux: main window, progress, Scheduler, Options
internal/i18n       the translations both desktop UIs share
internal/server     JSON + SSE API, token guard, embedded web UI
internal/ipc        Unix-socket control channel and single-instance lock
internal/native     native-messaging framing and browser-launch detection
internal/browserreg native-host registration for Chrome, Edge, Chromium, Firefox
internal/sysproxy   OS proxy lookup (environment, Windows Internet Options)
internal/autostart  launch at login (Run key, XDG autostart, LaunchAgent)
internal/assoc      Windows registration for magnet links and .torrent files
internal/torrent    runs odm-libtorrent and gives the engine its torrents
internal/tools      ODM's own copies of yt-dlp, ffmpeg and odm-libtorrent
helper/libtorrent   odm-libtorrent, the C++ companion program on libtorrent
internal/update     GitHub Releases version check
internal/clipmon    clipboard watcher (native on Windows, polled by the desktop UI elsewhere) and URL detection
internal/osutil     open, reveal and shutdown helpers
cmd/extpack         builds the Chromium (.zip) and Firefox (.xpi) extension packages
internal/extpack    per-browser manifest derivation and packaging
extension/          MV3 browser extension source and native-host manifests

Roadmap

  • A properties dialog for each download.
  • A credentials prompt for HTTP 401 responses from a host with no site login.
  • A virus-scan hook, grabber projects, and translations.
  • Signed self-update, and code-signed Windows builds.

License

MIT © 2026 Ochi Download Manager contributors.

odm-libtorrent, downloaded by ODM for torrents, is built with libtorrent (BSD-3-Clause), Boost (BSL-1.0), OpenSSL (Apache-2.0) and nlohmann/json (MIT); its archive carries their licences.

ODM is an independent implementation. It ships no code, binaries, assets or data from any other product, and it does not bypass copy protection or activation. Copyright protects expression, not ideas. This project claims rights only over its own source and asserts none over any idea, algorithm or behavior. See DISCLAIMER.md for the full statement.

About

Segmented, resumable download manager for Windows, Linux and macOS: multi-connection transfers, queues and scheduler, browser integration. Written in Go.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages