Skip to content

ColinGamez/StreamShogun

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

15 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

StreamShōgun

StreamShōgun

A modern desktop IPTV player built with Electron, React, and TypeScript.
Manage M3U playlists Β· Browse XMLTV programme guides Β· Watch HLS streams

CI License TypeScript Electron React Version


Features

Feature Description
M3U Playlist Parser Full-spec M3U/M3U8 parser with attribute extraction, EPG source discovery, and malformed-line tracking
XMLTV Programme Guide Parse XMLTV/EPG files, index by channel + time, and render a virtualised grid
HLS Playback Adaptive bitrate streaming via hls.js with auto-detect, retry, and clean teardown
Channel Zapper Quick prev/next navigation with keyboard shortcuts
SQLite Persistence Playlists, channels, EPG data, and favourites stored locally via better-sqlite3 (WAL mode)
Multi-Language English, Spanish, and Japanese out of the box
Dark Theme Dark-first design with CSS custom properties
Secure Architecture Context isolation, sandbox, no nodeIntegration, validated IPC bridge
Cross-Platform Windows (NSIS + portable), macOS (DMG), Linux (AppImage + deb)

Screenshots

Coming soon β€” replace these placeholders with actual screenshots.

Library Channels Guide Player
Library Channels Guide Player

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Electron Main Process                     β”‚
β”‚                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  main.ts β”‚  β”‚   ipc.ts     β”‚  β”‚  db/                       β”‚ β”‚
β”‚  β”‚  (app    β”‚  β”‚  (handlers + β”‚  β”‚  β”œβ”€ database.ts (init/WAL) β”‚ β”‚
β”‚  β”‚   life-  │──│   security   │──│  β”œβ”€ migrations.ts (v1)     β”‚ β”‚
β”‚  β”‚   cycle) β”‚  β”‚   validation)β”‚  β”‚  └─ repositories.ts (CRUD) β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                        β”‚                                         β”‚
β”‚                  preload.ts                                      β”‚
β”‚                  (contextBridge)                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                        β”‚ IPC (invoke/handle)                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                        β–Ό                                         β”‚
β”‚               Renderer Process (sandboxed)                       β”‚
β”‚                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  React 18 + Vite 5                                         β”‚ β”‚
β”‚  β”‚                                                             β”‚ β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚ β”‚
β”‚  β”‚  β”‚ Library  β”‚ β”‚ Channels  β”‚ β”‚  Guide  β”‚ β”‚   Player     β”‚  β”‚ β”‚
β”‚  β”‚  β”‚ (M3U/EPG β”‚ β”‚ (search,  β”‚ β”‚ (EPG    β”‚ β”‚ (HLS via     β”‚  β”‚ β”‚
β”‚  β”‚  β”‚  loader) β”‚ β”‚  groups,  β”‚ β”‚  grid,  β”‚ β”‚  hls.js,     β”‚  β”‚ β”‚
β”‚  β”‚  β”‚          β”‚ β”‚  favs)    β”‚ β”‚  detail)β”‚ β”‚  zapper)     β”‚  β”‚ β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚ β”‚
β”‚  β”‚                                                             β”‚ β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚  β”‚  β”‚  Zustand Store (app-store.ts)                          β”‚ β”‚ β”‚
β”‚  β”‚  β”‚  localStorage + DB-backed persistence                  β”‚ β”‚ β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                    @stream-shogun/core                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  types.ts  β”‚ β”‚ m3u-parser.ts β”‚ β”‚ xmltv-    β”‚ β”‚ epg-       β”‚ β”‚
β”‚  β”‚  (IPC ch., β”‚ β”‚ (39 tests)    β”‚ β”‚ parser.ts β”‚ β”‚ index.ts   β”‚ β”‚
β”‚  β”‚   iptv,    β”‚ β”‚               β”‚ β”‚ (57 tests)β”‚ β”‚            β”‚ β”‚
β”‚  β”‚   xmltv)   β”‚ β”‚               β”‚ β”‚           β”‚ β”‚            β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Project Structure

stream-shogun/
β”œβ”€β”€ .github/
β”‚   β”œβ”€β”€ ISSUE_TEMPLATE/          # Bug report & feature request templates
β”‚   β”œβ”€β”€ workflows/
β”‚   β”‚   β”œβ”€β”€ ci.yml               # Lint, typecheck, test, build
β”‚   β”‚   └── release.yml          # Tag-triggered multi-platform release
β”‚   β”œβ”€β”€ dependabot.yml           # Automated dependency updates
β”‚   └── PULL_REQUEST_TEMPLATE.md
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ desktop/                 # Electron main process
β”‚   β”‚   β”œβ”€β”€ build/               # App icons (electron-builder)
β”‚   β”‚   β”œβ”€β”€ scripts/             # Dev launcher
β”‚   β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”‚   β”œβ”€β”€ db/              # SQLite: database, migrations, repositories
β”‚   β”‚   β”‚   β”œβ”€β”€ ipc.ts           # IPC handlers with security validation
β”‚   β”‚   β”‚   β”œβ”€β”€ main.ts          # App lifecycle, window creation
β”‚   β”‚   β”‚   └── preload.ts       # contextBridge IPC surface
β”‚   β”‚   β”œβ”€β”€ electron-builder.yml # Packaging config (win/mac/linux)
β”‚   β”‚   β”œβ”€β”€ package.json
β”‚   β”‚   └── tsconfig.json
β”‚   └── ui/                      # React renderer
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ components/      # Sidebar, Welcome, EpgGrid, HlsPlayer, etc.
β”‚       β”‚   β”œβ”€β”€ hooks/           # useVirtualRows
β”‚       β”‚   β”œβ”€β”€ lib/             # bridge, i18n, persistence, sample-data
β”‚       β”‚   β”œβ”€β”€ pages/           # Library, Channels, Guide, Player
β”‚       β”‚   β”œβ”€β”€ stores/          # Zustand app store
β”‚       β”‚   β”œβ”€β”€ App.tsx          # Root shell
β”‚       β”‚   └── App.css          # Full application styles
β”‚       β”œβ”€β”€ package.json
β”‚       └── vite.config.ts
β”œβ”€β”€ packages/
β”‚   └── core/                    # Shared library
β”‚       β”œβ”€β”€ data/                # Test fixtures (M3U, XMLTV)
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ __demo__/        # Parser demo/test runners
β”‚       β”‚   β”œβ”€β”€ m3u-parser.ts    # M3U/M3U8 parser (39 tests)
β”‚       β”‚   β”œβ”€β”€ xmltv-parser.ts  # XMLTV parser (57 tests)
β”‚       β”‚   β”œβ”€β”€ epg-index.ts     # EPG time-range indexing
β”‚       β”‚   β”œβ”€β”€ types.ts         # IPC channels, app config types
β”‚       β”‚   β”œβ”€β”€ iptv-types.ts    # Channel, Playlist, EpgSource
β”‚       β”‚   └── xmltv-types.ts   # Programme, XmltvData
β”‚       β”œβ”€β”€ package.json
β”‚       └── tsconfig.json
β”œβ”€β”€ assets/                      # SVG icon source
β”œβ”€β”€ scripts/                     # Build utilities (clean, icon gen)
β”œβ”€β”€ .editorconfig
β”œβ”€β”€ .eslintrc.cjs
β”œβ”€β”€ .gitattributes
β”œβ”€β”€ .gitignore
β”œβ”€β”€ .prettierignore
β”œβ”€β”€ .prettierrc
β”œβ”€β”€ CHANGELOG.md
β”œβ”€β”€ CODE_OF_CONDUCT.md
β”œβ”€β”€ CONTRIBUTING.md
β”œβ”€β”€ LICENSE                      # MIT
β”œβ”€β”€ README.md
β”œβ”€β”€ SECURITY.md
β”œβ”€β”€ package.json                 # Workspace root
β”œβ”€β”€ pnpm-lock.yaml
β”œβ”€β”€ pnpm-workspace.yaml
└── tsconfig.base.json           # Shared strict TS config

Security Model

StreamShōgun follows the Electron Security Checklist:

Control Status Notes
contextIsolation βœ… Renderer cannot access Node.js APIs
nodeIntegration βœ… Off Disabled in all windows
sandbox βœ… Process-level sandboxing enabled
Preload bridge βœ… Only whitelisted IPC channels exposed
Input validation βœ… URL scheme checks, file size limits (25 MB fetch, 50 MB file)
Fetch timeout βœ… 30-second AbortController timeout
No remote module βœ… Not imported anywhere
WAL-mode SQLite βœ… Safe concurrent reads during writes

See SECURITY.md for the full security policy and vulnerability reporting process.

Prerequisites

Tool Version
Node.js β‰₯ 18.0.0
pnpm β‰₯ 9.0.0
Git Any recent version

Windows: A C++ build toolchain is required for better-sqlite3. Install the "Desktop development with C++" workload from Visual Studio Build Tools, or run:

npm install -g windows-build-tools

Installation

# Clone the repository
git clone https://github.com/stream-shogun/stream-shogun.git
cd stream-shogun

# Install all dependencies (including native modules)
pnpm install

Development

# Start the full dev environment (Vite HMR + Electron)
pnpm dev

# Or run the UI only in the browser (no Electron)
pnpm dev:ui
Script Description
pnpm dev Start Vite dev server + Electron
pnpm dev:ui Start Vite dev server only (browser)
pnpm test Run core library tests (96 tests)
pnpm typecheck TypeScript strict check across all packages
pnpm lint ESLint across the monorepo
pnpm lint:fix ESLint with auto-fix
pnpm format Prettier format all files
pnpm format:check Prettier check (CI-friendly)
pnpm clean Remove all build artifacts

Production Build

# Build all packages (core β†’ UI β†’ desktop)
pnpm build

# Platform-specific builds
pnpm build:win      # Windows (NSIS installer + portable)
pnpm build:mac      # macOS (DMG + zip)
pnpm build:linux    # Linux (AppImage + deb)

Build artifacts are written to apps/desktop/release/.

Custom Icons

Replace the placeholder icon before your first release:

# Place a 512Γ—512 PNG at:
apps/desktop/build/icon.png

# Or generate from the SVG source (requires sharp):
pnpm add -D sharp
node scripts/generate-icons.js

electron-builder will automatically convert the PNG to .ico (Windows) and .icns (macOS) at build time.

Packaging

The project uses electron-builder with config in apps/desktop/electron-builder.yml.

Platform Targets Output
Windows NSIS installer, portable .exe release/*.exe
macOS DMG, zip release/*.dmg
Linux AppImage, .deb release/*.AppImage, release/*.deb

Releasing

  1. Update version in package.json files and CHANGELOG.md.
  2. Commit: git commit -m "chore: release v0.2.0"
  3. Tag: git tag v0.2.0
  4. Push: git push origin main --tags

The release workflow will build for all platforms and create a draft GitHub Release with the artifacts.

Troubleshooting

Stream Playback Issues

Symptom Cause Fix
Black screen, no error Stream URL is not HLS StreamShōgun requires .m3u8 HLS streams
"CORS error" in console Server blocks cross-origin The stream server must send Access-Control-Allow-Origin headers
Stuttering / buffering Network bandwidth Check your connection; try a lower-quality stream
"Manifest parsing error" Malformed .m3u8 Verify the URL loads valid HLS in VLC or Safari
Audio but no video Unsupported codec (e.g. HEVC) hls.js supports H.264/AAC; HEVC requires native MSE support

Build Issues

Symptom Fix
better-sqlite3 build fails Install C++ build tools (see Prerequisites)
pnpm install blocks on native modules Ensure pnpm.onlyBuiltDependencies includes better-sqlite3
TypeScript errors after pulling Run pnpm --filter @stream-shogun/core build first to regenerate declarations
Electron white screen in production Verify apps/ui/dist/ exists and base: "./" is set in Vite config

Roadmap

  • VOD / catch-up playback support
  • Channel favourites sync across devices
  • Playlist auto-refresh on schedule
  • EPG reminders and notifications
  • Subtitle / teletext support
  • Picture-in-picture mode
  • Playlist import from Xtream Codes API
  • macOS and Linux native packaging refinements
  • Automated end-to-end tests (Playwright)
  • Plugin system for custom stream sources

Contributing

Contributions are welcome! Please read the Contributing Guide and our Code of Conduct before submitting a pull request.

License

MIT © StreamShōgun Contributors

Releases

Packages

Contributors

Languages