No description
  • TypeScript 52.4%
  • Python 47.6%
Find a file
2026-10-06 21:00:55 +02:00
stodk-py fix(resolvers): separate Byse from VOE, support intermediate landing page resolution, and guard against non-VOE URLs 2026-10-06 21:00:55 +02:00
stodk-ts fix(resolvers): separate Byse from VOE, support intermediate landing page resolution, and guard against non-VOE URLs 2026-10-06 21:00:55 +02:00
.gitignore feat: initial release of StreamSDK (dual TypeScript & Python recode with TUIs, resolvers, and FFmpeg pipeline) 2026-09-07 22:17:56 +02:00
LICENSE feat: initial release of StreamSDK (dual TypeScript & Python recode with TUIs, resolvers, and FFmpeg pipeline) 2026-09-07 22:17:56 +02:00
README.md docs: enrich README with interactive Mermaid diagrams, state machine, TUI preview, and Forgejo styling 2026-09-07 22:31:38 +02:00
RECODE_PLAN.md fix: update official SerienStream domain from s.to to https://serienstream.to across all clients, TUIs, and docs 2026-09-07 22:22:29 +02:00

  ███████╗████████╗██████╗ ███████╗ █████╗ ███╗   ███╗███████╗██████╗ ██╗  ██╗
  ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██╔══██╗████╗ ████║██╔════╝██╔══██╗██║ ██╔╝
  ███████╗   ██║   ██████╔╝█████╗  ███████║██╔████╔██║███████╗██║  ██║█████╔╝ 
  ╚════██║   ██║   ██╔══██╗██╔══╝  ██╔══██║██║╚██╔╝██║╚════██║██║  ██║██╔═██╗ 
  ███████║   ██║   ██║  ██║███████╗██║  ██║██║ ╚═╝ ██║███████║██████╔╝██║  ██╗
  ╚══════╝   ╚═╝   ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═╝     ╚═╝╚══════╝╚═════╝ ╚═╝  ╚═╝

Modern Cross-Platform Streaming & Downloader Engine

Forgejo TypeScript 5.7 Python 3.10+ React Ink Rich FFmpeg Engine Tests Passing License: GPL-3.0

Architecture • Sequence • State Machine • Platforms • Resolvers • Quick Start • Terminal UIs • Comparison • Verification • FAQ • Roadmap


🚀 Overview

StreamSDK is a high-performance, cross-platform media discovery and stream downloading engine. It completely supersedes the legacy .NET StoDK by eradicating platform-locked dependencies (Windows WPF, WebView2, COM runtimes) in favor of lightweight, native networking and asynchronous muxing.

StreamSDK is structured as a unified monorepo providing two feature-equivalent, fully tested SDKs:

  • stodk-ts: Headless TypeScript SDK + interactive React/Ink TSX Terminal UI.
  • stodk-py: Async Python 3.10+ SDK (httpx + pydantic v2) + interactive Rich Terminal UI.

🏗️ System Architecture

flowchart TD
    subgraph UI ["🖥️ Interactive Interfaces"]
        TUI_TS["TSX TUI (React / Ink)"]
        TUI_PY["Python TUI (Rich)"]
        CLI["Command Line Interface"]
    end

    subgraph SDK ["⚡ Core SDK Layer"]
        SC_S["SerienStreamClient (serienstream.to / aniworld.to)"]
        SC_F["FilmoClient (filmo.to + CSRF /n Minting)"]
    end

    subgraph RESOLVER ["🔓 Multi-Hoster Stream Resolvers"]
        R_VOE["VOE / Byse (ROT13 + Byte-Shift + Base64)"]
        R_ST["Streamtape (norobotlink Tokenizer)"]
        R_DOOD["Doodstream (pass_md5 + Nonce)"]
        R_VID["Vidoza (HTML5 Video Inspector)"]
    end

    subgraph ENGINE ["🚀 Download & Muxing Pipeline"]
        QUEUE["DownloadQueue (Multi-Worker Async Semaphore)"]
        FFMPEG["FFmpeg Subprocess Runner (-c copy -stats)"]
        PARSER["Real-Time Stderr Progress Parser"]
    end

    subgraph STORAGE ["💾 Local File System"]
        OUT["Sanitized Clean MP4 Files (H.264 / AAC)"]
    end

    UI --> SDK
    SDK --> RESOLVER
    RESOLVER --> QUEUE
    QUEUE --> FFMPEG
    FFMPEG --> PARSER
    PARSER -. Progress Stats (FPS / Speed / Bitrate) .-> UI
    FFMPEG --> STORAGE

    style UI fill:#1e1e2e,stroke:#89b4fa,stroke-width:2px,color:#cdd6f4
    style SDK fill:#181825,stroke:#f38ba8,stroke-width:2px,color:#cdd6f4
    style RESOLVER fill:#181825,stroke:#a6e3a1,stroke-width:2px,color:#cdd6f4
    style ENGINE fill:#181825,stroke:#f9e2af,stroke-width:2px,color:#cdd6f4
    style STORAGE fill:#11111b,stroke:#cba6f7,stroke-width:2px,color:#cdd6f4

📡 End-to-End Sequence Diagram

sequenceDiagram
    autonumber
    actor User
    participant App as StreamSDK TUI / Script
    participant Site as serienstream.to / filmo.to
    participant Hoster as External Hoster (VOE / Byse)
    participant FFmpeg as FFmpeg Stream Engine
    participant Disk as File Storage

    User->>App: Input Title ("Dr. Stone" / "Shutter Island")
    App->>Site: Fetch Metadata & Season/Episode List
    Site-->>App: Return Titles, Seasons, Available Hoster Chips
    User->>App: Select Stream (VOE 720p, German Audio)
    App->>Site: Mint Stream URL (POST /n or /redirect/ID)
    Site-->>App: Redirect Destination (voe.sx/e/...)
    App->>Hoster: Scrape Obfuscated HTML & Scripts
    Note over App,Hoster: Multi-Stage Deobfuscation (ROT13, Junk Removal, Reverse B64)
    App->>App: Extract Direct HLS Playlist URL (master.m3u8)
    App->>FFmpeg: Spawn Subprocess (-i master.m3u8 -c copy -stats)
    loop Every 250ms
        FFmpeg-->>App: Stderr: frame=... fps=... speed=23.9x size=1.8MB
        App-->>User: Live Progress Bar & Stats Update
    end
    FFmpeg->>Disk: Write Muxed MP4 (Title (Year).mp4)
    App-->>User: ✅ Download Completed!

🔄 Download Lifecycle State Machine

stateDiagram-v2
    direction TB
    [*] --> Idle: Init TUI / CLI SDK
    Idle --> Discovering: Input Title or Direct Slug
    Discovering --> SeriesView: Discovered TV Show (Seasons & Episodes)
    Discovering --> MovieView: Discovered Movie (Direct Video Info)
    Discovering --> Error: HTTP 404 / Parse Error
    Error --> Idle: Retry Input

    SeriesView --> SeasonSelect: Select Season
    SeasonSelect --> EpisodeSelect: Select Episode
    EpisodeSelect --> LanguageSelect: Select Audio Language
    MovieView --> LanguageSelect: Select Audio Language

    LanguageSelect --> HosterSelect: Pick Provider (VOE, Streamtape, ...)
    HosterSelect --> Resolving: Request Direct Stream
    Resolving --> Deobfuscating: Scrape & Deobfuscate Payload
    Deobfuscating --> Fallback: Token Expired or Blocked
    Fallback --> HosterSelect: Auto-failover to Next Hoster

    Deobfuscating --> Muxing: Direct HLS (.m3u8) / MP4
    Muxing --> Verifying: FFmpeg Subprocess EOF
    Verifying --> Finished: Media Header Verification
    Finished --> [*]: Saved Clean MP4 to Disk

🌐 Supported Platforms

Platform Domain Content Type Protection / Protocol Status
SerienStream https://serienstream.to TV Shows / Series HTTP Redirect (/redirect/<id>) Active
AniWorld https://aniworld.to Anime Series & Movies .hosterSiteVideo + data-lang-key Active
Filmo https://filmo.to Feature Films CSRF Token (<meta>) + AJAX POST /n Active

Note

Domain Notice: s.to officially moved to https://serienstream.to. Both SDKs automatically rewrite legacy s.to requests to the current endpoint.


🔓 Stream Deobfuscation Engine

StreamSDK resolves streaming endpoints completely headless without launching web browsers.

The VOE Deobfuscator Pipeline

flowchart LR
    A["Raw &lt;script&gt; Tag"] --> B["Trim Edge Chars [2:-2]"]
    B --> C["ROT13 Letter Shift"]
    C --> D["Strip Junk Tokens (@$, ^^, ~@, %?, *~)"]
    D --> E["Base64 Decode #1"]
    E --> F["Byte Shift: ord(c) - 3"]
    F --> G["Reverse String (text[::-1])"]
    G --> H["Base64 Decode #2"]
    H --> I["Parse JSON: {'source': 'https://...'}"]

    style A fill:#313244,stroke:#f38ba8,color:#cdd6f4
    style I fill:#313244,stroke:#a6e3a1,color:#cdd6f4
🔍 View Hoster Resolver Specifications
Hoster Extraction Technique Fallback Mechanism
VOE / Byse JSON <script type="application/json"> deobfuscation Regex search for var a168c Base64 reversed string & 'hls': '...'
Streamtape Regex extracts document.getElementById('norobotlink').innerHTML + token + #ideoooolink Direct redirect follow /e/ to /v/
Doodstream Scrapes /pass_md5/ token, issues authenticated GET with Referer spoofing Dynamic random 10-char nonce + timestamp expiration
Vidoza Direct DOM traversal for <video id="player"><source src="..."></video> Video tag fallback

⚡ Interactive Quick Start

🟦 Option A: TypeScript / Node.js (stodk-ts)

1. Installation & Build

cd stodk-ts
npm install
npm run build

2. Launch Interactive TSX Terminal UI

npm run tui
# or directly via npx
npx tsx src/tui/cli.tsx

3. Run Automated Unit Tests

npm test

4. Minimal TypeScript SDK Code Snippet

import {
  SerienStreamClient,
  FilmoClient,
  resolveStreamUrl,
  downloadStream
} from 'stodk-ts';

// 1. Discover Series (serienstream.to)
const client = new SerienStreamClient('https://serienstream.to', 'serie/stream');
const series = await client.getSeries('breaking-bad');
console.log(`Discovered ${series.title} (${series.seasonsCount} Seasons)`);

// 2. Fetch Season 1, Episode 1 Streams
const episode = await client.getEpisodeVideoInfo('breaking-bad', 1, 1);
const activeStream = episode.streams[0]!;

// 3. Resolve Direct HLS Stream & Download via FFmpeg
const directUrl = await resolveStreamUrl(activeStream);
await downloadStream({
  streamUrl: directUrl,
  outputPath: './downloads/BreakingBad_S01E01.mp4',
  durationSeconds: 30, // Optional test sample limit
  onProgress: (prog) => {
    console.log(`Speed: ${prog.speedMultiplier}x | Transferred: ${(prog.outputFileSizeKb / 1024).toFixed(1)} MB`);
  }
});
🟨 Option B: Python 3.10+ (stodk-py)

1. Installation & Virtual Environment

cd stodk-py
python -m venv .venv
.\.venv\Scripts\activate      # Windows (or source .venv/bin/activate on Linux/macOS)
pip install -e .

2. Launch Interactive Rich Terminal UI

stodk
# or
python -m stodk.tui.cli

3. Run Automated Unit Tests

pytest -v

4. Minimal Python SDK Code Snippet

import asyncio
from stodk import (
    FilmoClient,
    resolve_stream_url,
    download_stream
)

async def main():
    # 1. Discover Movie (filmo.to)
    client = FilmoClient("https://filmo.to", "movies")
    movie = await client.get_filmo_movie_video_info("shutter-island")
    print(f"Discovered: {movie.title} ({movie.year}) with {len(movie.streams)} streams")

    # 2. Resolve Direct Stream URL
    active_stream = movie.streams[0]
    direct_hls_url = await resolve_stream_url(active_stream)
    print(f"Direct Stream URL: {direct_hls_url[:70]}...")

    # 3. Stream & Mux with FFmpeg
    def progress_handler(prog):
        print(f"Speed: {prog.speed_multiplier:.1f}x | Size: {prog.output_file_size_kb / 1024:.1f} MB")

    await download_stream(
        stream_url=direct_hls_url,
        output_path="./downloads/Shutter_Island_2010.mp4",
        duration_seconds=30,
        on_progress=progress_handler
    )

if __name__ == "__main__":
    asyncio.run(main())

🎮 Terminal User Interfaces (TUI)

Both implementations feature keyboard-driven terminal UIs without graphical bloat:

┌─── [ StreamSDK Terminal Interface ] ───────────────────────────────────────────────┐
│                                                                                    │
│  ? Select Target Platform: › serienstream.to (Series & Anime)                      │
│  ? Enter Title or Slug   : dr-stone                                                │
│                                                                                    │
│  ✔ Discovered Series: "Dr. Stone" (3 Seasons, 35 Episodes)                         │
│                                                                                    │
│  [Season 1: Stone World] ───────────────────────────────────────────────────────── │
│  ▸ S01E01: Stone World                 [VOE 720p] [Streamtape] [Doodstream]        │
│    S01E02: King of the Stone World     [VOE 720p] [Streamtape]                     │
│    S01E03: Weapons of Science          [VOE 720p]                                  │
│                                                                                    │
│  [Active Stream] VOE (German Dub / 720p H.264 AAC)                                 │
│  [Pipeline] Deobfuscating JSON -> Extracted master.m3u8                            │
│                                                                                    │
│  Downloading: Dr. Stone - S01E01 - Stone World.mp4                                 │
│  [████████████████████████████████████████░░░░░░░░░░] 82.4% (41.2 MB / 50.0 MB)    │
│  Speed: 18.4 MB/s (24.2x) | FPS: 576.0 | Bitrate: 4210 kbps | ETA: 00:00:03       │
└────────────────────────────────────────────────────────────────────────────────────┘
⌨️ Interactive Keyboard Controls & Shortcuts
Key Context Action
↑ / ↓ Menu Selection Move highlighted choice up or down
Enter Input & Menus Submit text search / Confirm selection
q Download Queue Gracefully stop queue and exit
Ctrl + C Any Immediately kill FFmpeg subprocess and clean up partial files

⚖️ Stack Comparison: TypeScript vs Python

Feature / Metric 🟦 TypeScript (stodk-ts) 🟨 Python (stodk-py)
Primary Domain Web integrations, Electron, Node microservices Data science, background daemons, CLI automation
Terminal UI Engine React + Ink (Component-based reactive TSX) Rich Console (Thread-safe live renders)
Networking Layer Native fetch with persistent Cookie Jar Asynchronous httpx.AsyncClient
HTML Parsing Engine cheerio (Fast v8 jQuery engine) beautifulsoup4 (html.parser)
Data Validation Strict TypeScript 5.7 compile-time types pydantic v2 runtime schema validation
Subprocess Runner execa with asynchronous stderr stream parsing asyncio.create_subprocess_exec stream reader
Cold Startup Time ~180 ms (tsx) / ~35 ms compiled bundle ~110 ms (.venv)
Test Suite 11/11 Vitest unit tests passing 11/11 Pytest unit tests passing

🧪 Verification & Benchmarks

All functionality has been verified with live downloads and automated tests:

Test Suite Execution

  • stodk-ts: 11/11 Vitest unit tests passing (Slug normalization, ROT13/shiftBack, VOE decoder, FFmpeg progress parser).
  • stodk-py: 11/11 Pytest unit tests passing.

Live Download Benchmark (Shutter Island, 2010)

Target URL  : https://filmo.to/movies/shutter-island
Hoster      : VOE (720p BluRay, English / German tracks)
Resolved URL: https://ugc-cdn-caching-...cloudwindow-route.com/.../master.m3u8
Speed       : 23.9x average muxing throughput
Result File : downloads/Shutter Island (2010).mp4 (1.81 MB verified sample)
Video Codec : H.264 (High Profile), 1692x720, 24.0 fps progressive
Audio Codec : AAC (LC), 44.1 kHz, stereo
Exit Code   : 0 (Flawless verification via ffprobe)

❓ Frequently Asked Questions & Troubleshooting

1. How do I bypass German ISP DNS blocks (CUII / Clearingstelle)?

Some German ISPs (Vodafone, Telekom, 1&1) poison DNS queries for serienstream.to and aniworld.to. To bypass this without a VPN, configure DNS over HTTPS (DoH) or set your upstream resolver to:

  • Cloudflare: 1.1.1.1 and 1.0.0.1
  • Quad9: 9.9.9.9 and 149.112.112.112

Tip

Both SDK clients work flawlessly over standard DoH proxies and encrypted DNS relays.

2. Why is FFmpeg failing with exit code 4294967274 or 403 Forbidden?

VOE and certain CDN nodes reject custom user agents or malformed -headers parameters sent from FFmpeg subprocesses on Windows. StreamSDK's built-in downloadStream engine handles header formatting automatically. Ensure you do not inject raw newline characters manually when customizing runner options.

3. Is FFmpeg mandatory? Where do I get it?

Yes, FFmpeg is essential for high-speed multi-threaded stream muxing (-c copy) and combining segmented HLS playlists into continuous MP4 files.

  • Windows: winget install Gyan.FFmpeg or download from gyan.dev
  • Linux: sudo apt update && sudo apt install -y ffmpeg
  • macOS: brew install ffmpeg
4. Can I run StreamSDK completely headless on a Linux server?

Yes! Both SDKs provide zero-dependency library imports that can be incorporated into scripts, Celery task workers, or cron jobs without initiating the Terminal UI.


🗺️ Roadmap

  • Ground-up recode of legacy C# .NET StoDK codebase
  • Headless TypeScript SDK (stodk-ts)
  • Headless Asynchronous Python SDK (stodk-py)
  • Multi-platform scrapers (serienstream.to, aniworld.to, filmo.to)
  • Direct Hoster deobfuscators (VOE, Streamtape, Doodstream, Vidoza)
  • Dual Terminal User Interfaces (Ink TSX & Rich Python)
  • Automated Unit Test suites in Vitest and Pytest
  • Migration to official https://serienstream.to endpoint
  • Direct MP4 fallback worker pool
  • Configurable proxy support (SOCKS5 / HTTP)
  • Docker container image for automated headless background queues

📁 Repository Structure

StreamSDK/
├── README.md                   # Interactive Forgejo documentation
├── RECODE_PLAN.md              # Master reverse-engineering specification
├── LICENSE                     # GNU General Public License v3.0
├── .gitignore                  # Global repository ignores
│
├── stodk-ts/                   # TypeScript Implementation
│   ├── src/
│   │   ├── client/             # serienstream.to & filmo.to scrapers
│   │   ├── resolvers/          # VOE, Streamtape, Doodstream, Vidoza
│   │   ├── downloader/         # FFmpeg runner & DownloadQueue
│   │   ├── tui/                # React / Ink TSX Terminal UI
│   │   ├── types/              # Type definitions
│   │   └── utils/              # Crypto, slug, request helpers
│   ├── test/                   # Vitest unit & integration tests
│   ├── package.json            # Node.js ESM configuration
│   └── tsconfig.json           # Strict TypeScript configuration
│
└── stodk-py/                   # Python Implementation
    ├── src/stodk/
    │   ├── client/             # Async HTTPX scrapers
    │   ├── resolvers/          # Python stream resolvers
    │   ├── downloader/         # Async FFmpeg subprocess queue
    │   ├── tui/                # Rich interactive Terminal UI
    │   ├── types.py            # Pydantic v2 data models
    │   └── utils/              # Crypto, slug, request helpers
    ├── tests/                  # Pytest unit & integration tests
    └── pyproject.toml          # Modern Python packaging configuration

⚖️ License & Disclaimer

This project is licensed under the GNU General Public License v3.0 (GPL-3.0). See the LICENSE file for complete details.

Developed and maintained by Maggi (admin@maggi.dev). Built strictly for educational and interoperability research purposes.