Skip to content

Repository files navigation

English|简体中文


NOTE: We have set new update goals and will continue releasing updates in my spare time outside of study. Starting with V9.5.0, we have for the first time introduced a Windows version that includes built‑in PyCorsLocalProxy. If you need a reliable cross‑origin solution, you can use either the Android version with built‑in local CORS service or the new Windows version.


Bismuth Player —— A Video Player Shell as Beautiful as "Bismuth"

A meticulously designed web-based video streaming application featuring customizable video sources, elegant animations, and a robust caching mechanism

Version React TypeScript Vite

Description

This project is essentially AI-generated. I was responsible for issue detection and optimization direction guidance. Models used: Doubao, Kimi, GLM-5.3-Flash/5/5-Turbo/4.7/4.6/4.6V/4.5, Deepseek-R1/Chat (provided assistance during project inception)


🚀 Online Deployment

Live Demo

Visit Demo to try it now

Self-Hosting

Choose any of the following platforms and click the button to quickly create your own Bismuth Player instance:

Deploy with Vercel Deploy to Netlify Deploy to Cloudflare

☁️ Cloudflare Pages is supported out of the box: a wrangler.toml is provided at the repo root, and _redirects (SPA fallback) & _headers (security headers + long-term asset caching) ship in public/. Just click the button above to deploy — no extra configuration needed.

Local Deployment

More


Other Versions

Material Design version created by Minimax Agent : View Here


✨ Features

🎨 Exquisite Interface

  • Dark Theme - Eye-friendly dark color scheme
  • Gradient Design - Elegant purple-to-pink gradients
  • Serif Font - Clear and beautiful Chinese typography
  • Responsive Layout - Perfectly adapted for mobile and desktop

🎬 Core Functionality

  • Custom Video Sources - Support for multiple Apple CMS API sources (JSON format)
  • Built-in Player (SimPlayer) - Integrated lightweight player supporting MP4/WebM/HLS with screenshot, PiP, speed control, and progress memory
  • External Player Support - Fallback iframe-based player for custom player URLs
  • Two-level Category Navigation — Dynamic categories loaded from API with top-level tabs and sub-category chips (leveraging Apple CMS type_pid hierarchy)
  • Favorites System — ❤️ button on detail page to save favorites; dedicated Favorites tab with full management (view, play, remove, clear all)
  • 🔞 Ethics Content Filter — Optional toggle in Video Source Settings to hide ethics categories and filter ethics videos from all lists
  • Search Function - Quickly find the content you want
  • Playback History - Automatically tracks viewing progress with one-click continue (accessible via homepage top-right button)
  • Episode Selection - Clear episode selection interface with scrollable episode grid and current episode pulse highlight

🚀 Performance Optimization

  • API Caching - Intelligent caching of API responses to reduce network requests
  • Lazy Image Loading - Load images on demand to save bandwidth
  • Skeleton Screen Loading - Elegant loading state display
  • Page Transition Animations - Smooth transition effects

💫 Animation Effects

  • Splash Screen - Elegant app startup animation
  • Page Transitions - Slide in/out page transitions
  • Image Loading - Fade-in animation for images
  • Interaction Feedback - Button hover and click animations

🛠️ Tech Stack

Technology Version Purpose
React 19.2 Frontend Framework
TypeScript 5.9 Type Safety
Vite 7.2 Build Tool
Tailwind CSS 3.4 Styling Framework
shadcn/ui - UI Component Library
hls.js 1.6 HLS Streaming
Lucide React 0.562 Icon Library

📦 Quick Start

Requirements

  • Node.js >= 20.19 (required by Vite 7; LTS 20/22/24 recommended)
  • npm or bun

Install Dependencies

npm install
# or
bun install

Development Mode

npm run dev
# or
bun run dev

Build for Production

npm run build
# or
bun run build

Preview Build

npm run preview
# or
bun run preview

⚙️ Configuration

Adding Video Sources

  1. Go to the "Settings" page
  2. Click the "Add" button
  3. Fill in the video source information:
    • ID: Unique identifier (e.g., mysource)
    • Name: Display name (e.g., My Source)
    • API URL: Apple CMS API address

Player Configuration

Custom player addresses can be configured in the settings page, supporting any player that accepts URL parameters.

CORS Proxy

If you encounter CORS issues, you can configure a CORS proxy address in the settings. You can also disable the CORS proxy entirely to request sources directly.

Cache Management

  • Enable/Disable API caching
  • View cache statistics
  • Clear cache

📱 Interface Preview

Mobile

  • Bottom navigation bar
  • Compact card layout
  • Gesture-friendly interactions

Desktop

  • Fixed left sidebar
  • Widescreen grid layout
  • Hover preview effects

🔧 API Support

Supports standard Apple CMS API format:

  • List Endpoint: ?ac=videolist&pg=1
  • Detail Endpoint: ?ac=videolist&ids=123
  • Search Endpoint: ?ac=videolist&wd=keyword

📁 Project Structure

Bismuth-Player/
├── src/
│   ├── components/       # Reusable components
│   │   ├── ui/          # shadcn/ui components
│   │   ├── SimPlayer.tsx
│   │   ├── BottomNav.tsx
│   │   └── VideoCard.tsx
│   ├── pages/           # Page components
│   │   ├── HomePage.tsx
│   │   ├── SearchPage.tsx
│   │   ├── DetailPage.tsx
│   │   ├── PlayerPage.tsx
│   │   ├── HistoryPage.tsx
│   │   ├── SettingsPage.tsx
│   │   └── settings/       # Settings sub-pages
│   │       ├── VideoSourcePage.tsx
│   │       ├── PlayerSettingsPage.tsx
│   │       ├── CorsProxyPage.tsx
│   │       ├── CacheSettingsPage.tsx
│   │       └── AboutPage.tsx
│   ├── services/        # Service layer
│   │   ├── api.ts       # API requests
│   │   ├── cache.ts     # Caching service
│   │   └── storage.ts   # Local storage
│   ├── types/           # TypeScript types
│   ├── App.tsx          # Main app component
│   ├── App.css          # Global styles
│   └── main.tsx         # Entry file
├── public/              # Static assets
├── package.json
├── vite.config.ts
└── README.md

🎯 Version Updates

Full changelog: CHANGELOG.md

V9.6.0

  • ✨ Standalone Filter page — homepage shows all content by default; a "筛选" button next to the search box opens a dedicated page with two-level category rows & infinite scroll
  • ✨ History & Favorites source annotation — every card shows its origin source; cross-source playback fetches from the annotated source without switching the global one
  • ✨ Deleted-source fallback — dedicated error notice when the annotated source is gone; entries get a 30-minute grace window (re-adding the same source ID restores them) before auto-cleanup
  • 🐛 Fixed identity key for history/favorites (vod_id + sourceId) so entries from different sources with the same numeric ID no longer collide

V9.5.1

  • 🐛 Fixed favicon 404 — index.html referenced the non-existent /vite.svg (Vite template leftover); now points to real app icons
  • 🐛 Corrected Node.js requirement — Vite 7 actually requires >= 20.19; updated both READMEs and added an engines field to package.json
  • ⚡ Code-splitting — manualChunks splits the 902 KB bundle into hls/react/vendor; hls.js loads on demand, cutting first-payload JS by ~59% (gzip)
  • 📦 Added GitHub Pages auto-publish workflow — builds and deploys on every push to main, with manual trigger support
  • ☁️ Added Cloudflare Pages one-click deploy support — wrangler.toml + _redirects (SPA fallback) + _headers (security headers & long-term caching); all three deploy buttons (Vercel/Netlify/Cloudflare) work out of the box

V9.5.0

  • 🐛 Fixed episode list not scrollable on player page — added flex-1 max-h-[45vh] on mobile so episode grid scrolls independently with many episodes
  • 🐛 Fixed resume playback bug — PlayerPage useEffect missing initialEpisode dependency
  • ✨ Added 🔞 Ethics content filter — toggle in Video Source Settings to hide ethics categories and filter ethics videos
  • ✨ Added Favorites system — ❤️ button on detail page + dedicated Favorites tab with full management
  • 📱 Navigation redesign — History moved to homepage top-right button; bottom nav now 4 items (Home/Search/Favorites/Settings)
  • 📱 Global scrollbar styling + current episode pulse animation

V9.4.0

  • 🐛 Fixed build failure — removed 49 unused shadcn/ui zombie components and restored the missing index.html Vite entry file (was incorrectly gitignored)
  • 🐛 Fixed categories always falling back to hardcoded list — getCategories() now requests the base URL directly (Apple CMS omits class field when ?ac=videolist parameter is present)
  • 🐛 Fixed inconsistent localStorage key naming — video_sources/current_source_id renamed to bismuth_ prefix with automatic one-time migration of legacy data
  • 🐛 Fixed pagination field type inconsistency — safeApiResponse() normalizes all pagination fields with Number() to prevent string-comparison bugs
  • 🐛 Fixed sub-category "All" tab showing empty results — clicking a top-level category now auto-selects its first sub-category (Apple CMS top-level categories contain no direct videos)
  • ✨ Added two-level category navigation — leverages type_pid hierarchy: top-level categories as tabs + sub-categories as chips
  • 🔧 Updated .gitignore to track /index.html (critical fix for build reproducibility)

V9.3.0

  • 🐛 Fixed HomePage not refreshing after adding first video source or switching source
  • 🐛 Fixed SimPlayer crossOrigin conflict on iOS causing HLS playback failures
  • 🐛 Fixed API response not validated — malformed responses caused TypeError crashes
  • 🐛 Fixed components.json pointing to wrong Tailwind config file
  • 🔧 Updated version fallback to V9.3.0

V9.2.1

  • 🐛 Fixed VideoCard referencing removed imageError after v9.2.0 cleanup
  • 🐛 Replaced native loading="lazy" with IntersectionObserver to stop background image loading
  • 🐛 Fixed img.src clearing on unmount triggering console error
  • 🐛 Fixed HomePage hasMore referencing undefined limit variable causing infinite fetch loop
  • 🧹 Removed unused CACHE_TTL.search dead code

V9.2

  • 🐛 Fixed parsePlayUrls not handling multi-source $$$ separator
  • 🐛 Fixed iOS Safari HLS event listener memory leak and error handler race condition
  • 🐛 Fixed DetailPage skeleton screen not resetting on video switch
  • 🐛 Fixed PlayerPage episode not syncing with prop
  • 🐛 Fixed fetchWithRetry non-OK response error reporting and connection pool exhaustion
  • 🐛 Fixed version number fallback mismatch
  • ✨ Added volume slider to SimPlayer (hover to reveal)
  • ✨ Improved pagination accuracy using API metadata
  • 🧹 Removed unused _viewKey and imageError states
  • ⚡ Optimized re-render performance in App, PlayerPage, and SimPlayer
  • 📁 Added .gitignore, removed build artifacts from repository
V9.1 and earlier

V9.1

  • 🐛 Fixed settings page crash — ArrowLeft icon missing from import caused "ArrowLeft is not defined" runtime error
  • 🐛 Fixed critical CORS proxy double-wrapping bug
  • 🐛 Fixed Toast notifications invisible
  • 🐛 Fixed auto-resume setting not working
  • 🧹 Removed dead carousel.tsx import dependencies

V9.0

  • 🏗️ Settings page redesigned — each setting category now has its own dedicated page
  • ✨ Added proxy priority reordering
  • ✨ Enhanced cache settings page
  • 🔧 Unified storage key naming convention

V8.3

  • 🐛 Fixed iOS Safari HLS playback stuttering and CORS preflight overhead on iOS

V8.2

  • 🐛 Fixed fullscreen button not responding on iOS Safari

V8.1

  • 🐛 Fixed progress bar not responding to clicks and drags
  • ✨ Added "Check for Updates" feature

V8

  • ✨ Integrated SimPlayer as built-in player
  • ✨ Built-in player features: screenshot, PiP, speed control, progress memory
  • ✨ CORS proxy toggle

V7

  • ✨ Added splash screen, page transitions, skeleton screens
  • 🐛 Removed PWA functionality

V6 ~ V3

  • Various UI improvements and bug fixes

💡 Inspiration

This project was inspired by LibreTV. I found LibreTV useful but requiring a backend, so I wanted to create a backend-free version. Thus, this project was born through my conversations with AIs... Thanks to that project for the creative inspiration.


📄 License

This project is open-sourced under the Apache License 2.0.


🙏 Disclaimer

Bismuth Player is solely a playback tool shell and does not provide any video content or resources.

  • This application does not store, host, or distribute any video content
  • All content comes from third-party video sources configured by users themselves
  • Users must ensure that the content sources used are legal and compliant
  • Users bear full legal responsibility for using illegal sources
  • The developer is not responsible for any third-party content or user behavior

By using this application, you indicate that you have read and agree to the above terms.


Made with 💜 by Eq52

About

基于苹果CMS 的影视播放器

Resources

Stars

44 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages