Skip to content

Repository files navigation

speedrr

speedrr - Dynamic Upload and Download Speed Manager for Torrenting (Golang Edition)

Note

This repository is a fork of itschasa/speedrr, rewritten in Golang for ultra-low memory footprint (~5–15 MB RAM), lightweight Docker image (<15 MB), single binary deployment, and native concurrency.

Change your torrent client's upload speed dynamically on events such as:

  • When a Plex/Jellyfin/Emby/Tautulli stream starts
  • Time of day and day of the week
  • Number of active media streams (stream-based predictive control)

Change your torrent client's download speed dynamically on events such as:

  • Time of day and day of the week

This tool is ideal for users with limited upload speed; however, anyone can use it to maximize seeding rates while keeping Plex/Jellyfin/Emby streams buffer-free! Great for Home Labs, NAS (Unraid, Synology, TrueNAS), and Raspberry Pi / SBC devices.

Features

  • Ultra Lightweight: Built with Golang. Consumes only ~5–15 MB RAM and runs from a <15 MB Docker container.
  • Multi-Server Support: Plex, Jellyfin, Emby, and Tautulli.
  • Multi-Client Support: qBittorrent and Transmission.
    • Bandwidth is split between clients by number of downloading/uploading torrents or manual share ratios.
  • Stream-Based Speed Control: Set specific upload speeds based on active stream count instead of bandwidth estimates.
  • Time/Day Schedules: Flexible time-of-day and day-of-week speed limits with support for percentages ("50%"), fixed values, and unlimited.
  • Resilient Startup: Exponential backoff retries if media servers or torrent clients are temporarily offline.

Process Architecture

Speedrr uses an asynchronous event-driven workflow to monitor media servers, evaluate schedules, and adjust torrent client speeds dynamically:

graph LR
    subgraph Stage1["1. Trigger & Monitoring"]
        MS["Media Server Polling<br/><i>(Plex / Jellyfin / Emby / Tautulli)</i>"]
        SCHED["Schedule Evaluator<br/><i>(Overnight & Weekend Workers)</i>"]
    end

    subgraph Stage2["2. Filter & Evaluate"]
        FILT["Stream Filters<br/><i>(Local LAN & Paused Timeout)</i>"]
        WIN["Active Window State<br/><i>(Time Window Check)</i>"]
    end

    subgraph Stage3["3. Target Speed Calculation"]
        CALC{"Target Speed Resolver<br/><i>(Stream Mapping + Reductions)</i>"}
    end

    subgraph Stage4["4. Client Enforcement"]
        QBIT["qBittorrent Web API<br/><i>(HTTP 200/204 Auth)</i>"]
        TRANS["Transmission RPC<br/><i>(CSRF Session ID Challenge)</i>"]
    end

    MS -->|Active Sessions| FILT
    SCHED -->|Active Window| WIN
    FILT -->|Filtered Stream Count| CALC
    WIN -->|Schedule Reductions| CALC
    CALC -->|Calculated Limits| QBIT
    CALC -->|Calculated Limits| TRANS

    classDef focal fill:#fff3ed,stroke:#eb6c36,stroke-width:2px,color:#eb6c36;
    class CALC focal;
Loading

Setup

Docker (GHCR)

Pull the Docker image:

docker pull ghcr.io/khw315/speedrr:latest

Example docker run command:

docker run -d \
    -e SPEEDRR_CONFIG=/data/config.yaml \
    -v /path/to/config_folder/:/data/ \
    --name speedrr \
    --network host \
    ghcr.io/khw315/speedrr:latest

Example docker-compose.yml:

services:
  speedrr:
    image: ghcr.io/khw315/speedrr:latest
    container_name: speedrr
    restart: unless-stopped
    network_mode: host
    environment:
      - SPEEDRR_CONFIG=/data/config.yaml
    volumes:
      - ./config:/data

Unraid

  1. Open your Unraid console and create a template:
cd /boot/config/plugins/dockerMan/templates-user && touch my-speedrr.xml && nano my-speedrr.xml
  1. Copy and paste the template from speedrr-unraid.xml.
  2. Open WebUI > Docker > Add Container > Select speedrr.
  3. Place your config.yaml in /appdata/speedrr/ and start the container.

Building from Source (Go)

  1. Install Go 1.22+.
  2. Clone this repository:
git clone https://github.com/khw315/speedrr.git
cd speedrr
  1. Build the binary:
go build -o speedrr .
  1. Run Speedrr:
./speedrr --config_path config.yaml

Stream-Based Speed Control

Instead of dynamically reducing upload speed based on bandwidth usage, you can configure Speedrr to set specific upload speeds based on the number of active streams.

Why Use Stream-Based Speeds?

Traditional bandwidth-based control is reactive—it reduces your upload speed based on how much bandwidth streams are using. Stream-based control is predictive—you define exactly what upload speed you want for different numbers of streams.

Benefits:

  • More Predictable: You control exactly what happens with 1, 2, 3+ streams.
  • Max Seeding When Idle: Set unlimited upload when no streams are active.
  • Better Balance: Fine-tune the trade-off between streaming quality and torrent upload.
  • Easier Configuration: Count streams instead of estimating bandwidth needs.

Quick Start

Add stream_based_speeds to your media server configuration:

modules:
  media_servers:
    - type: jellyfin
      url: http://your-jellyfin-server:8096
      api_key: your_api_key
      https_verify: false

      update_interval: 5
      ignore_streams:
        local: true
        ip_networks: [192.168.0.0/24, 127.0.0.1]
        paused_after: 300

      stream_based_speeds:
        enabled: true
        speeds:
          0: unlimited    # No streams = unlimited upload
          1: 10           # 1 stream = 10 Mbit/s upload
          2: 8            # 2 streams = 8 Mbit/s upload
          3: 6            # 3 streams = 6 Mbit/s upload
          4: 5            # 4+ streams = 5 Mbit/s upload
        default: 5

See config.stream_based.example.yaml for a fully documented configuration example.

Contributing

Contributions are welcome! Feel free to open issues or submit pull requests.

License

Distributed under the GPL-3.0 License.

About

Lightweight Golang daemon to dynamically manage qBittorrent & Transmission speeds based on active Plex, Jellyfin, Emby, and Tautulli streams.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

Contributors

Languages