Nettoyage massif côté frontend, grosse passe perf, app mobile v2.5.3
(écran qui ne s'éteint plus + fix build), extracteur Uqload HLS sur
extensions/userscript, redirection réseau-bloqué via passerelle
explicative et cast cross-receiver/cross-browser.
Nettoyage Firebase & code mort
- Drop firebase + @firebase/firestore (package.json + vite.config
optimizeDeps + alias)
- Suppression src/config/firebase.ts (jamais utilisé)
- Suppression services morts : adminService, commentService, logService,
notificationService + composants liés (AdminLogin, CommentSection,
CommentItem, ReactionBar) + types/Comment.ts
- Suppression scripts non-utilisés : bundle-report.mjs, publish-app.mjs
- Net : -3 449 lignes
Perf carrousels & TMDB images
- useTmdbImages : 1 seul fetch TMDB pour logo + poster (au lieu de 2),
prefetch idle au mount du carousel + dedup via inflight map (0 doublon
entre prefetch et hooks), include_image_language=fr,en,null pour
récupérer les versions FR-prioritisées
- EmblaCarousel : pré-décode des posters off-DOM (img.decode) en idle
pour éliminer le coût de décode pendant le scroll horizontal, priority
cap statique (eager + fetchpriority=high pour les N premières cards
selon viewport), suppression du tracking visibleSlides (state churn)
- content-visibility:auto sur slides hors viewport (skip layout/paint
natif), exclu des slides Top 10 pour ne pas clipper le digit débordant
- will-change:transform pré-promotion compositing layer (PC only via
hover:hover)
- Embla duration 25 → 15 (snap plus rapide, moins de frames composées)
- Boutons nav carousel : suppression backdrop-blur (cher), bg opaque
- LazyImage : width/height attrs pour éviter CLS + alléger placeholder
Top progress bar (style YouTube)
- TopProgressBar : asymptote vers 85% pendant chunk loads, fill 100%
smooth + fade out à la fin, 120ms grace period pour suppress flash
sur chunks cachés
- lazyWithRetry tracke les loads actifs + dispatch chunk:load:start /
chunk:load:end events sur window
- Routes loaders supportent { silent: true } pour skip le tracking sur
les prefetch (PrefetchLink hover + IDLE_PREFETCH au mount)
SW redirect → passerelle movix.health explicative
- buildMirrorUrl() factorise la construction d'URL miroir avec contexte
- handleNavigation passe ?from=&reason=unreachable&error=&via= à la
gateway pour qu'elle affiche une popup explicative au user au lieu
d'un redirect silencieux
- MOVIX_FORCE_REDIRECT message handler passe reason=api-errors
- blockDetection.ts transmet la dernière erreur axios au SW
- index.html : cache-bust du Cast SDK URL (cb=Date.now()) pour éviter
qu'un SDK stale ne reste coincé en cache navigateur/SW
Cast (Chromecast + AirPlay + Remote Playback API)
- loadMediaOnCastWithFallback : retry sur 3 MIME HLS différents
(application/vnd.apple.mpegurl, x-mpegurl, x-mpegURL) — certains
receivers rejettent le premier choix selon firmware
- Subtitles externes attachés au cast (CastSubtitleTrack) via
chrome.cast.media.Track + TextTrackStyle par défaut (50% black
background, edge outline) lisible sur la majorité des TV
- isRemotePlaybackSupported : fallback W3C Remote Playback API pour
Firefox / Edge avec cast extension bloquée / Brave avec shields →
device discovery + picker via video.remote.prompt()
- initializeAirPlay supporte désormais les deux paths (WebKit AirPlay
pour Safari + Remote Playback pour les autres)
- Détection castSdkBlocked : si le SDK Cast ne charge pas en 5s
(adblock, FAI, shield), affiche un message d'erreur explicite au
lieu du générique "aucun device trouvé"
- 7 nouvelles strings i18n FR + EN pour les états cast :
castUnavailable, castUnavailableNoDevices,
castUnavailableUnsupportedBrowser, castUnavailableSdkBlocked,
castUnavailableHelpChromecast, castUnavailableHelpAirPlay,
castUnavailableSeeHelp
App mobile Android v2.5.3 (versionCode 12)
- AndroidManifest : android:keepScreenOn="true" sur MainActivity →
l'écran ne s'éteint plus pendant le visionnage (avant le user devait
toucher l'écran toutes les 30s pour pas que le téléphone se lock en
plein film)
- build.gradle : exclude androidx.legacy:legacy-support-core-utils
(tiré transitivement par mediarouter → palette) qui embarquait ses
propres androidx.autofill.R$attr → "duplicate class" au mergeDexRelease
contre le module androidx.autofill:autofill:1.1.0 d'appcompat
- gradle.properties : android.nonTransitiveRClass=true pour empêcher
chaque lib de regénérer ses R classes transitivement (même cause
racine du duplicate class)
- version.json bumped 2.5.2 → 2.5.3, nouvel APK (-17KB), release notes
FR : "Correction extraction du lecteur Uqload" + "L'écran ne s'éteint
plus lors de l'utilisation de l'app"
- apkUrl repointé sur le repo Movix-STMG (au lieu de movixcorp)
Userscript + Extensions Chrome/Firefox — Uqload HLS
- extractUqload : préfère désormais le master.m3u8 multi-bitrate (qualité
adaptative) au v.mp4 single-quality. Regex tente d'abord
/master\.m3u8/, sinon n'importe quel .m3u8, et fallback sur l'ancien
pattern v.mp4 si rien trouvé. Les 3 cibles (Chrome MV3, Firefox MV2,
Tampermonkey) sont synchronisées sur la même logique.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| API | ||
| app | ||
| baddomain | ||
| cloudflareproxy | ||
| extension | ||
| functions | ||
| others | ||
| PreMid | ||
| public | ||
| RivestreamCloudflareProxy | ||
| scripts | ||
| server | ||
| src | ||
| userscript | ||
| wasm/watchparty-sync | ||
| .dockerignore | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| Dockerfile | ||
| eslint.config.js | ||
| index.html | ||
| LICENSE | ||
| manifest.json | ||
| movix.png | ||
| next.config.js | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.js | ||
| README.md | ||
| tailwind.config.js | ||
| tsconfig.app.json | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| vite.config.ts | ||
Movix
Le 1er site de streaming open source made in France et 100% vibecodé.
React | Vite | TypeScript | Node.js | MySQL | Redis | Socket.IO | Python | Rust
Licence : Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) · LICENSE
Movix est un monorepo produit pour une plateforme de streaming communautaire. Le frontend, l'API principale, la WatchParty, les proxies, les outils navigateur et plusieurs briques d'infra vivent dans le même dépôt parce qu'ils évoluent ensemble.
Ce n'est pas un simple duo "frontend + backend". Une feature peut très vite traverser plusieurs couches à la fois : interface React, persistance locale, sync backend, extraction vidéo, proxy Python et parfois extension navigateur.
Ce que contient le repo
| Zone | Rôle | Documentation |
|---|---|---|
src/ |
Frontend Vite + React + TypeScript | Frontend |
API/Mainapi/ |
Backend principal clusterisé | Main API |
API/watchpartyAPI/ |
Service temps réel WatchParty | WatchParty API |
API/proxiesembed/ |
Proxy aiohttp pour embeds, flux et DRM | Proxies Embed |
API/miscs/ |
Micro-service Flask pour certains 403 | bypass403 |
extension/ + userscript/ |
Outils navigateur Movix | Movix OS |
app/ |
App mobile React Native (Android OK, iOS non testé) | App mobile |
wasm/watchparty-sync/ |
Moteur Rust/WASM de la Sync Pro | WatchParty Sync WASM |
cloudflareproxy/ |
Worker Cloudflare CORS/proxy | Cloudflare Proxy |
Architecture du monorepo
movix-main/
|-- src/ # Frontend principal
|-- public/ # Assets statiques et artefacts WASM publiés
|-- API/
| |-- Mainapi/ # Backend actif
| |-- watchpartyAPI/ # Temps réel WatchParty
| |-- proxiesembed/ # Proxy Python haute charge
| `-- miscs/ # Micro-services annexes
|-- extension/ # Extension Chrome / Firefox
|-- userscript/ # Variante Tampermonkey
|-- app/ # App mobile React Native (Android/iOS)
|-- wasm/watchparty-sync/ # Sync Pro en Rust/WASM
|-- cloudflareproxy/ # Worker Cloudflare
|-- functions/ # Handlers serverless annexes
|-- PreMid/ # Présence PreMiD
`-- RivestreamCloudflareProxy/ # Variante de worker pour Rivestream
Démarrage rapide
Prérequis
- Node.js 18+ et npm
- Python 3.10+ pour les services Python
- MySQL et Redis pour
API/Mainapi - Rust +
wasm-bindgenseulement si tu touches la Sync Pro WASM - React Native CLI + Android Studio (et Xcode + CocoaPods sur Mac) seulement si tu touches l'app mobile
app/— iOS n'a pas été testé, voirapp/README.md
Installer les dépendances utiles
npm install
cd API/Mainapi
npm install
API/watchpartyAPI/ n'a pas son propre package.json : il consomme les dépendances du node_modules racine.
Configurer les .env avant de lancer quoi que ce soit
Ne saute pas cette étape. Une bonne partie du monorepo dépend des variables d'environnement pour les URLs, la base de données, Redis, les proxys, TMDB, Turnstile et plusieurs intégrations de lecture.
# Frontend
cp .env.example .env
# API principale
cp API/Mainapi/.env.example API/Mainapi/.env
# WatchParty
cp API/watchpartyAPI/.env.example API/watchpartyAPI/.env
# Proxy embed
cp API/proxiesembed/.env.example API/proxiesembed/.env
# bypass403
cp API/miscs/.env.example API/miscs/.env
Lancer le minimum utile en local
# Frontend - http://localhost:3000
npm run dev
# Backend principal - http://localhost:25565
cd API/Mainapi
npm run dev
# WatchParty - http://localhost:25566
node API/watchpartyAPI/watchparty.js
Services optionnels selon la zone que tu touches :
# Proxy embed
cd API/proxiesembed
pip install -r requirements.txt
python server.py
# bypass403
cd API/miscs
pip install flask requests python-dotenv
python bypass403.py
Configuration
Les fichiers d'exemple ou de config existants sont déjà dans le repo :
- Frontend :
.env.example - API principale :
API/Mainapi/.env.example - WatchParty :
API/watchpartyAPI/.env.example - Proxy embed :
API/proxiesembed/.env.example - bypass403 :
API/miscs/.env.example
Les variables frontend les plus importantes sont VITE_MAIN_API, VITE_WATCHPARTY_API, VITE_PROXY_BASE_URL, VITE_API_PROXY_BASE_URL, VITE_PROXIES_EMBED_API et VITE_SITE_URL.
Pour un premier lancement local, configure au minimum :
/.envAPI/Mainapi/.envAPI/watchpartyAPI/.env
Comment s'orienter vite
- Feature frontend : commence par
src/App.tsx, puis la page cible danssrc/pages/. - Auth, profils, persistance : regarde
src/context/,src/App.tsx,API/Mainapi/routes/authRoutes.jsetAPI/Mainapi/routes/sync.js. - Lecture vidéo et proxies : recoupe
src/pages/Watch/, les composants player,API/Mainapi/liveTvRoutes.js,API/proxiesembed/et parfoisextension/. - WatchParty : vérifie à la fois
API/watchpartyAPI/watchparty.js,src/pages/WatchParty*.tsx,src/hooks/useWatchParty.ts,src/utils/watchparty*.tsetsrc/workers/watchpartySync.worker.ts. - Browser tooling : si tu modifies l'extension, compare toujours
extension/Chrome/etextension/Firefox/, puis vérifie si le userscript doit suivre. - Sync Rust/WASM : modifie
wasm/watchparty-sync/, puis rebuildpublic/wasm/watchparty-sync/.
Points importants avant de contribuer
- Le backend actif est
API/Mainapi/. Le vieux contenu directement sousAPI/n'est plus la référence. - Ce monorepo n'utilise pas de workspace tooling : chaque sous-projet garde ses scripts.
- Une partie importante de l'état produit vit dans
localStorageet dans la sync backend. Ne raisonne pas "base de données only". - Le lint frontend se lance à la racine avec
npm run lint. - Il n'y a pas de suite de tests globale fiable pour tout le repo. Vérifie au minimum les scripts touchés et le comportement manuel.
Documentation par module
- Frontend
- Services backend
- Main API
- WatchParty API
- Proxies Embed
- bypass403
- Movix OS
- Extension navigateur
- Userscript Tampermonkey
- App mobile React Native — Android fonctionnel, iOS non testé (aide recherchée)
- WatchParty Sync WASM
- Cloudflare Proxy
Licence
Ce projet est distribué sous licence Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0). Le texte complet est disponible dans LICENSE.
Avertissement
Ce projet est fourni uniquement à des fins éducatives, de recherche et de démonstration. Il n'encourage ni ne cautionne une utilisation illégale, le contournement de droits, ou toute violation des lois applicables. Chaque utilisateur est seul responsable de l'usage qu'il en fait.