Spaces:
Running
Running
<html lang="fr"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>CinéAuto - Plateforme de Streaming Automatisé</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); | |
body { | |
font-family: 'Inter', sans-serif; | |
background-color: #0f172a; | |
color: white; | |
} | |
.movie-card { | |
transition: all 0.3s ease; | |
position: relative; | |
} | |
.movie-card:hover { | |
transform: translateY(-5px); | |
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3); | |
} | |
.poster-placeholder { | |
background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); | |
} | |
.loading-spinner { | |
animation: spin 1s linear infinite; | |
} | |
@keyframes spin { | |
0% { transform: rotate(0deg); } | |
100% { transform: rotate(360deg); } | |
} | |
#video-player { | |
width: 100%; | |
height: 70vh; | |
background-color: black; | |
} | |
.progress-container { | |
height: 5px; | |
background-color: #334155; | |
} | |
.progress-bar { | |
height: 100%; | |
background-color: #8b5cf6; | |
width: 0%; | |
} | |
.automation-panel { | |
background: rgba(15, 23, 42, 0.9); | |
backdrop-filter: blur(10px); | |
} | |
.genre-filter { | |
scrollbar-width: thin; | |
scrollbar-color: #8b5cf6 #1e293b; | |
} | |
.genre-filter::-webkit-scrollbar { | |
height: 6px; | |
} | |
.genre-filter::-webkit-scrollbar-track { | |
background: #1e293b; | |
} | |
.genre-filter::-webkit-scrollbar-thumb { | |
background-color: #8b5cf6; | |
border-radius: 6px; | |
} | |
</style> | |
</head> | |
<body class="min-h-screen"> | |
<!-- Navigation --> | |
<nav class="bg-gray-900 bg-opacity-90 backdrop-blur-md fixed w-full z-50 shadow-lg"> | |
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
<div class="flex items-center justify-between h-16"> | |
<div class="flex items-center"> | |
<div class="flex-shrink-0"> | |
<span class="text-2xl font-bold text-purple-400">CinéAuto</span> | |
</div> | |
<div class="hidden md:block ml-10"> | |
<div class="flex space-x-4"> | |
<a href="#" class="text-white px-3 py-2 rounded-md text-sm font-medium bg-purple-600">Accueil</a> | |
<a href="#" class="text-gray-300 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Bibliothèque</a> | |
<a href="#" class="text-gray-300 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Automatisation</a> | |
<a href="#" class="text-gray-300 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Serveurs</a> | |
</div> | |
</div> | |
</div> | |
<div class="hidden md:block"> | |
<div class="ml-4 flex items-center md:ml-6"> | |
<div class="relative mx-4"> | |
<input type="text" id="search-input" placeholder="Rechercher un film..." | |
class="bg-gray-800 text-white px-4 py-2 rounded-full w-64 focus:outline-none focus:ring-2 focus:ring-purple-500"> | |
<button id="search-btn" class="absolute right-3 top-2 text-gray-400 hover:text-white"> | |
<i class="fas fa-search"></i> | |
</button> | |
</div> | |
<button class="p-1 rounded-full text-gray-400 hover:text-white focus:outline-none"> | |
<i class="fas fa-user-circle text-xl"></i> | |
</button> | |
</div> | |
</div> | |
<div class="-mr-2 flex md:hidden"> | |
<button class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none"> | |
<i class="fas fa-bars"></i> | |
</button> | |
</div> | |
</div> | |
</div> | |
</nav> | |
<!-- Main Content --> | |
<main class="pt-24 pb-12"> | |
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
<!-- Player Section --> | |
<section class="mb-12 rounded-xl overflow-hidden shadow-2xl"> | |
<div id="video-player"> | |
<video id="video" class="w-full h-full" controls></video> | |
<div id="player-overlay" class="hidden absolute inset-0 bg-black bg-opacity-70 flex flex-col items-center justify-center"> | |
<div class="text-center p-6"> | |
<h2 class="text-2xl font-bold text-white mb-4">CinéAuto Player</h2> | |
<p class="text-gray-300 mb-6">Lecteur haute performance avec streaming adaptatif et automatisation intelligente</p> | |
<button id="start-demo" class="bg-purple-600 hover:bg-purple-700 text-white px-6 py-3 rounded-lg font-medium"> | |
<i class="fas fa-play mr-2"></i> Démarrer la démo | |
</button> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-800 p-4"> | |
<div class="flex justify-between items-center mb-2"> | |
<h2 id="current-movie-title" class="text-xl font-bold text-white">Aucun film sélectionné</h2> | |
<div class="flex items-center space-x-4"> | |
<button id="auto-next" class="text-purple-400 hover:text-purple-300"> | |
<i class="fas fa-robot"></i> Auto | |
</button> | |
<button id="quality-btn" class="text-gray-300 hover:text-white"> | |
<i class="fas fa-tachometer-alt"></i> 1080p | |
</button> | |
</div> | |
</div> | |
<div class="progress-container mb-2"> | |
<div id="progress-bar" class="progress-bar"></div> | |
</div> | |
<div class="flex justify-between text-sm text-gray-400"> | |
<span id="current-time">00:00:00</span> | |
<span id="duration">00:00:00</span> | |
</div> | |
</div> | |
</section> | |
<!-- Automation Panel --> | |
<section class="mb-12 automation-panel rounded-xl p-6 shadow-lg"> | |
<h2 class="text-2xl font-bold text-white mb-6">Panneau d'Automatisation</h2> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
<div class="bg-gray-800 p-4 rounded-lg"> | |
<h3 class="text-lg font-semibold text-white mb-3"><i class="fas fa-cog mr-2"></i>Paramètres</h3> | |
<div class="space-y-4"> | |
<div> | |
<label class="block text-sm text-gray-300 mb-1">Mode de lecture</label> | |
<select id="playback-mode" class="w-full bg-gray-700 text-white rounded px-3 py-2"> | |
<option value="sequential">Séquentiel</option> | |
<option value="random">Aléatoire</option> | |
<option value="by_genre">Par genre</option> | |
<option value="by_year">Par année</option> | |
</select> | |
</div> | |
<div> | |
<label class="block text-sm text-gray-300 mb-1">Qualité automatique</label> | |
<label class="inline-flex items-center"> | |
<input type="checkbox" id="adaptive-quality" class="form-checkbox h-5 w-5 text-purple-600" checked> | |
<span class="ml-2 text-gray-300">Adaptative</span> | |
</label> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-800 p-4 rounded-lg"> | |
<h3 class="text-lg font-semibold text-white mb-3"><i class="fas fa-server mr-2"></i>Serveurs</h3> | |
<div class="space-y-3"> | |
<div class="flex justify-between items-center"> | |
<span class="text-gray-300">Serveur Principal</span> | |
<span class="text-green-400 text-sm font-mono">En ligne</span> | |
</div> | |
<div class="flex justify-between items-center"> | |
<span class="text-gray-300">Serveur Secondaire</span> | |
<span class="text-green-400 text-sm font-mono">En ligne</span> | |
</div> | |
<div class="flex justify-between items-center"> | |
<span class="text-gray-300">Serveur Cloud</span> | |
<span class="text-green-400 text-sm font-mono">En ligne</span> | |
</div> | |
<div class="mt-4"> | |
<button id="optimize-servers" class="w-full bg-purple-600 hover:bg-purple-700 text-white py-2 rounded"> | |
<i class="fas fa-sync-alt mr-2"></i> Optimiser les serveurs | |
</button> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-800 p-4 rounded-lg"> | |
<h3 class="text-lg font-semibold text-white mb-3"><i class="fas fa-bolt mr-2"></i>Actions Rapides</h3> | |
<div class="grid grid-cols-2 gap-3"> | |
<button id="play-btn" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-3 rounded text-sm"> | |
<i class="fas fa-play mr-1"></i> Démarrer | |
</button> | |
<button id="pause-btn" class="bg-gray-700 hover:bg-gray-600 text-white py-2 px-3 rounded text-sm"> | |
<i class="fas fa-pause mr-1"></i> Pause | |
</button> | |
<button id="random-btn" class="bg-purple-600 hover:bg-purple-700 text-white py-2 px-3 rounded text-sm"> | |
<i class="fas fa-random mr-1"></i> Aléatoire | |
</button> | |
<button id="add-to-list" class="bg-green-600 hover:bg-green-700 text-white py-2 px-3 rounded text-sm"> | |
<i class="fas fa-plus mr-1"></i> Liste | |
</button> | |
<button id="favorite-btn" class="bg-yellow-600 hover:bg-yellow-700 text-white py-2 px-3 rounded text-sm"> | |
<i class="fas fa-star mr-1"></i> Favoris | |
</button> | |
<button id="stop-btn" class="bg-red-600 hover:bg-red-700 text-white py-2 px-3 rounded text-sm"> | |
<i class="fas fa-times mr-1"></i> Stop | |
</button> | |
</div> | |
</div> | |
</div> | |
</section> | |
<!-- Filters --> | |
<section class="mb-6 bg-gray-800 rounded-lg p-4"> | |
<div class="flex flex-wrap items-center justify-between gap-4"> | |
<div class="flex items-center space-x-4"> | |
<h3 class="text-lg font-semibold text-white">Filtres :</h3> | |
<select id="year-filter" class="bg-gray-700 text-white rounded px-3 py-2 text-sm"> | |
<option value="">Toutes les années</option> | |
<option value="2023">2023</option> | |
<option value="2022">2022</option> | |
<option value="2021">2021</option> | |
<option value="2020">2020</option> | |
<option value="2010-2019">2010-2019</option> | |
<option value="2000-2009">2000-2009</option> | |
<option value="1990-1999">1990-1999</option> | |
<option value="1980-1989">1980-1989</option> | |
<option value="1970-1979">1970-1979</option> | |
</select> | |
<select id="rating-filter" class="bg-gray-700 text-white rounded px-3 py-2 text-sm"> | |
<option value="0">Toutes les notes</option> | |
<option value="9">9+</option> | |
<option value="8">8+</option> | |
<option value="7">7+</option> | |
<option value="6">6+</option> | |
</select> | |
</div> | |
<div class="flex items-center space-x-2"> | |
<span class="text-sm text-gray-300">Trier par :</span> | |
<select id="sort-by" class="bg-gray-700 text-white rounded px-3 py-2 text-sm"> | |
<option value="popularity.desc">Popularité</option> | |
<option value="vote_average.desc">Note</option> | |
<option value="release_date.desc">Date de sortie</option> | |
<option value="revenue.desc">Box-office</option> | |
</select> | |
</div> | |
</div> | |
<div class="mt-4 genre-filter flex space-x-3 overflow-x-auto py-2"> | |
<button class="genre-tag px-3 py-1 bg-gray-700 hover:bg-purple-600 text-white rounded-full text-sm whitespace-nowrap" data-id="">Tous</button> | |
<!-- Genres will be loaded here --> | |
</div> | |
</section> | |
<!-- Movie Library --> | |
<section class="mb-12"> | |
<div class="flex justify-between items-center mb-6"> | |
<h2 class="text-2xl font-bold text-white"> | |
<span id="library-title">Bibliothèque de Films</span> | |
<span id="movie-count" class="text-gray-400 text-lg ml-2">(Chargement...)</span> | |
</h2> | |
<div class="flex space-x-3"> | |
<button id="refresh-btn" class="px-4 py-2 bg-gray-800 hover:bg-gray-700 text-white rounded-lg"> | |
<i class="fas fa-sync-alt mr-2"></i>Actualiser | |
</button> | |
<button id="random-movie-btn" class="px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-lg"> | |
<i class="fas fa-random mr-2"></i>Aléatoire | |
</button> | |
</div> | |
</div> | |
<div id="loading-indicator" class="flex justify-center items-center py-12"> | |
<div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-purple-500"></div> | |
</div> | |
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-6" id="movie-library"> | |
<!-- Movie cards will be loaded here --> | |
</div> | |
<div id="load-more-container" class="mt-8 text-center hidden"> | |
<button id="load-more-btn" class="px-6 py-3 bg-gray-800 hover:bg-gray-700 text-white rounded-lg font-medium"> | |
<i class="fas fa-arrow-down mr-2"></i> Charger plus de films | |
</button> | |
</div> | |
</section> | |
</div> | |
</main> | |
<!-- Footer --> | |
<footer class="bg-gray-900 text-gray-400 py-8"> | |
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
<div class="grid grid-cols-1 md:grid-cols-4 gap-8"> | |
<div> | |
<h3 class="text-white text-lg font-semibold mb-4">CinéAuto</h3> | |
<p class="text-sm">Plateforme de streaming automatisé avec lecteur haute performance et gestion intelligente des serveurs.</p> | |
</div> | |
<div> | |
<h3 class="text-white text-lg font-semibold mb-4">Technologies</h3> | |
<ul class="space-y-2 text-sm"> | |
<li><span class="text-purple-400">HLS.js</span> - Streaming adaptatif</li> | |
<li><span class="text-purple-400">WebRTC</span> - P2P optimisé</li> | |
<li><span class="text-purple-400">AI</span> - Recommandations</li> | |
</ul> | |
</div> | |
<div> | |
<h3 class="text-white text-lg font-semibold mb-4">Performances</h3> | |
<ul class="space-y-2 text-sm"> | |
<li><i class="fas fa-bolt text-yellow-400 mr-2"></i>Latence minimale</li> | |
<li><i class="fas fa-tachometer-alt text-green-400 mr-2"></i>4K Ultra HD</li> | |
<li><i class="fas fa-server text-blue-400 mr-2"></i>15 serveurs mondiaux</li> | |
</ul> | |
</div> | |
<div> | |
<h3 class="text-white text-lg font-semibold mb-4">Support</h3> | |
<div class="flex space-x-4"> | |
<a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-discord"></i></a> | |
<a href="#" class="text-gray-400 hover:text-white"><i class="fas fa-envelope"></i></a> | |
<a href="#" class="text-gray-400 hover:text-white"><i class="fas fa-question-circle"></i></a> | |
</div> | |
</div> | |
</div> | |
<div class="border-t border-gray-800 mt-8 pt-8 text-sm text-center"> | |
<p>© 2023 CinéAuto. Système automatisé de streaming haute performance.</p> | |
<p class="mt-2 text-xs text-gray-600">Cette application utilise l'API TMDb mais n'est pas approuvée ou certifiée par TMDb.</p> | |
</div> | |
</div> | |
</footer> | |
<script> | |
// Configuration | |
const TMDB_API_KEY = 'fb437b10727a5a4eb8d9134e29c82ae0'; | |
const TMDB_ACCESS_TOKEN = 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJmYjQzN2IxMDcyN2E1YTRlYjhkOTEzNGUyOWM4MmFlMCIsIm5iZiI6MTY4MDYzNzkxMC44NjUsInN1YiI6IjY0MmM3ZmQ2OGI5NTllMDBmNDRkNzNhMCIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.Nhl261Ha3z0Ujg5vM1PpFoZBiTGjlXQ1g9VFPh6dVvs'; | |
const BASE_URL = 'https://api.themoviedb.org/3'; | |
const IMAGE_BASE_URL = 'https://image.tmdb.org/t/p/w500'; | |
const BACKDROP_BASE_URL = 'https://image.tmdb.org/t/p/original'; | |
// Elements | |
const video = document.getElementById('video'); | |
const videoPlayer = document.getElementById('video-player'); | |
const playerOverlay = document.getElementById('player-overlay'); | |
const progressBar = document.getElementById('progress-bar'); | |
const currentTime = document.getElementById('current-time'); | |
const duration = document.getElementById('duration'); | |
const autoNextBtn = document.getElementById('auto-next'); | |
const movieLibrary = document.getElementById('movie-library'); | |
const currentMovieTitle = document.getElementById('current-movie-title'); | |
const loadingIndicator = document.getElementById('loading-indicator'); | |
const loadMoreContainer = document.getElementById('load-more-container'); | |
const loadMoreBtn = document.getElementById('load-more-btn'); | |
const movieCount = document.getElementById('movie-count'); | |
const libraryTitle = document.getElementById('library-title'); | |
const searchInput = document.getElementById('search-input'); | |
const searchBtn = document.getElementById('search-btn'); | |
const refreshBtn = document.getElementById('refresh-btn'); | |
const randomMovieBtn = document.getElementById('random-movie-btn'); | |
const genreFilterContainer = document.querySelector('.genre-filter'); | |
const yearFilter = document.getElementById('year-filter'); | |
const ratingFilter = document.getElementById('rating-filter'); | |
const sortBy = document.getElementById('sort-by'); | |
const startDemoBtn = document.getElementById('start-demo'); | |
// Player controls | |
const playBtn = document.getElementById('play-btn'); | |
const pauseBtn = document.getElementById('pause-btn'); | |
const randomBtn = document.getElementById('random-btn'); | |
const addToListBtn = document.getElementById('add-to-list'); | |
const favoriteBtn = document.getElementById('favorite-btn'); | |
const stopBtn = document.getElementById('stop-btn'); | |
// State | |
let hls = new Hls(); | |
let autoPlayEnabled = true; | |
let currentMovieIndex = 0; | |
let currentPage = 1; | |
let totalPages = 1; | |
let totalResults = 0; | |
let currentMovies = []; | |
let genres = []; | |
let currentGenre = ''; | |
let currentSearchQuery = ''; | |
let isSearching = false; | |
// Initialize player | |
function initPlayer(movie) { | |
// In a real app, you would use actual video sources | |
// For demo purposes, we'll use a placeholder | |
const demoVideoUrl = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8'; | |
if (Hls.isSupported()) { | |
hls.loadSource(demoVideoUrl); | |
hls.attachMedia(video); | |
hls.on(Hls.Events.MANIFEST_PARSED, function() { | |
video.play(); | |
playerOverlay.classList.add('hidden'); | |
}); | |
} else if (video.canPlayType('application/vnd.apple.mpegurl')) { | |
video.src = demoVideoUrl; | |
video.addEventListener('loadedmetadata', function() { | |
video.play(); | |
playerOverlay.classList.add('hidden'); | |
}); | |
} | |
currentMovieTitle.textContent = `${movie.title} (${movie.release_date ? movie.release_date.substring(0, 4) : 'N/A'})`; | |
// Update video player background with movie backdrop | |
if (movie.backdrop_path) { | |
videoPlayer.style.backgroundImage = `url(${BACKDROP_BASE_URL}${movie.backdrop_path})`; | |
videoPlayer.style.backgroundSize = 'cover'; | |
videoPlayer.style.backgroundPosition = 'center'; | |
} | |
} | |
// Format time | |
function formatTime(seconds) { | |
const h = Math.floor(seconds / 3600); | |
const m = Math.floor((seconds % 3600) / 60); | |
const s = Math.floor(seconds % 60); | |
return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`; | |
} | |
// Play next movie | |
function playNextMovie() { | |
const playbackMode = document.getElementById('playback-mode').value; | |
if (playbackMode === 'random') { | |
currentMovieIndex = Math.floor(Math.random() * currentMovies.length); | |
} else { | |
currentMovieIndex = (currentMovieIndex + 1) % currentMovies.length; | |
} | |
initPlayer(currentMovies[currentMovieIndex]); | |
} | |
// Load genres from TMDB | |
async function loadGenres() { | |
try { | |
const response = await fetch(`${BASE_URL}/genre/movie/list?api_key=${TMDB_API_KEY}&language=fr-FR`); | |
const data = await response.json(); | |
genres = data.genres; | |
// Add genre tags to filter | |
genres.forEach(genre => { | |
const genreTag = document.createElement('button'); | |
genreTag.className = 'genre-tag px-3 py-1 bg-gray-700 hover:bg-purple-600 text-white rounded-full text-sm whitespace-nowrap'; | |
genreTag.textContent = genre.name; | |
genreTag.dataset.id = genre.id; | |
genreTag.addEventListener('click', () => filterByGenre(genre.id, genre.name)); | |
genreFilterContainer.appendChild(genreTag); | |
}); | |
} catch (error) { | |
console.error('Error loading genres:', error); | |
} | |
} | |
// Filter by genre | |
function filterByGenre(genreId, genreName) { | |
currentGenre = genreId; | |
currentPage = 1; | |
isSearching = false; | |
currentSearchQuery = ''; | |
// Update UI | |
document.querySelectorAll('.genre-tag').forEach(tag => { | |
if (tag.dataset.id === genreId.toString()) { | |
tag.classList.add('bg-purple-600'); | |
tag.classList.remove('bg-gray-700'); | |
} else { | |
tag.classList.remove('bg-purple-600'); | |
tag.classList.add('bg-gray-700'); | |
} | |
}); | |
libraryTitle.textContent = genreName ? `Films ${genreName}` : 'Bibliothèque de Films'; | |
loadMovies(); | |
} | |
// Load movies from TMDB | |
async function loadMovies() { | |
loadingIndicator.classList.remove('hidden'); | |
movieLibrary.innerHTML = ''; | |
loadMoreContainer.classList.add('hidden'); | |
let url; | |
if (isSearching) { | |
url = `${BASE_URL}/search/movie?api_key=${TMDB_API_KEY}&language=fr-FR&query=${encodeURIComponent(currentSearchQuery)}&page=${currentPage}`; | |
} else if (currentGenre) { | |
url = `${BASE_URL}/discover/movie?api_key=${TMDB_API_KEY}&language=fr-FR&with_genres=${currentGenre}&page=${currentPage}`; | |
} else { | |
url = `${BASE_URL}/movie/popular?api_key=${TMDB_API_KEY}&language=fr-FR&page=${currentPage}`; | |
} | |
// Add filters | |
const yearValue = yearFilter.value; | |
const ratingValue = ratingFilter.value; | |
const sortValue = sortBy.value; | |
if (yearValue) { | |
if (yearValue.includes('-')) { | |
const [start, end] = yearValue.split('-'); | |
url += `&primary_release_date.gte=${start}-01-01&primary_release_date.lte=${end}-12-31`; | |
} else { | |
url += `&primary_release_year=${yearValue}`; | |
} | |
} | |
if (ratingValue > 0) { | |
url += `&vote_average.gte=${ratingValue}`; | |
} | |
if (sortValue) { | |
url += `&sort_by=${sortValue}`; | |
} | |
try { | |
const response = await fetch(url); | |
const data = await response.json(); | |
currentMovies = data.results; | |
totalPages = data.total_pages; | |
totalResults = data.total_results; | |
movieCount.textContent = `(${totalResults.toLocaleString()} disponibles)`; | |
if (currentMovies.length > 0) { | |
renderMovies(currentMovies); | |
if (currentPage < totalPages) { | |
loadMoreContainer.classList.remove('hidden'); | |
} | |
} else { | |
movieLibrary.innerHTML = ` | |
<div class="col-span-full text-center py-12"> | |
<i class="fas fa-film text-4xl text-gray-600 mb-4"></i> | |
<h3 class="text-xl text-white">Aucun film trouvé</h3> | |
<p class="text-gray-400 mt-2">Essayez de modifier vos filtres de recherche</p> | |
</div> | |
`; | |
} | |
} catch (error) { | |
console.error('Error loading movies:', error); | |
movieLibrary.innerHTML = ` | |
<div class="col-span-full text-center py-12"> | |
<i class="fas fa-exclamation-triangle text-4xl text-red-500 mb-4"></i> | |
<h3 class="text-xl text-white">Erreur de chargement</h3> | |
<p class="text-gray-400 mt-2">Impossible de charger les films. Veuillez réessayer.</p> | |
</div> | |
`; | |
} finally { | |
loadingIndicator.classList.add('hidden'); | |
} | |
} | |
// Render movies | |
function renderMovies(movies) { | |
movies.forEach((movie, index) => { | |
const movieCard = document.createElement('div'); | |
movieCard.className = 'movie-card bg-gray-800 rounded-lg overflow-hidden shadow-lg cursor-pointer'; | |
movieCard.innerHTML = ` | |
<div class="relative h-64"> | |
${movie.poster_path ? | |
`<img src="${IMAGE_BASE_URL}${movie.poster_path}" alt="${movie.title}" class="w-full h-full object-cover">` : | |
`<div class="poster-placeholder w-full h-full flex items-center justify-center"> | |
<i class="fas fa-film text-4xl text-gray-600"></i> | |
</div>` | |
} | |
<div class="absolute inset-0 bg-black bg-opacity-30 opacity-0 hover:opacity-100 transition flex items-center justify-center"> | |
<button class="play-btn bg-purple-600 hover:bg-purple-700 text-white rounded-full w-12 h-12 flex items-center justify-center"> | |
<i class="fas fa-play"></i> | |
</button> | |
</div> | |
${movie.vote_average ? ` | |
<div class="absolute top-2 left-2 bg-gray-900 bg-opacity-80 text-yellow-400 px-2 py-1 rounded text-xs font-bold"> | |
${movie.vote_average.toFixed(1)} <i class="fas fa-star"></i> | |
</div> | |
` : ''} | |
</div> | |
<div class="p-4"> | |
<h3 class="text-white font-medium truncate">${movie.title}</h3> | |
<div class="flex items-center mt-2"> | |
<span class="text-gray-400 text-sm"> | |
${movie.release_date ? movie.release_date.substring(0, 4) : 'N/A'} | |
</span> | |
<span class="text-gray-400 text-sm ml-auto"> | |
${movie.genre_ids && genres.length ? | |
genres.find(g => g.id === movie.genre_ids[0])?.name || '' : ''} | |
</span> | |
</div> | |
</div> | |
`; | |
movieCard.addEventListener('click', () => { | |
currentMovieIndex = index; | |
initPlayer(movie); | |
}); | |
movieLibrary.appendChild(movieCard); | |
}); | |
} | |
// Search movies | |
function searchMovies(query) { | |
currentSearchQuery = query.trim(); | |
isSearching = currentSearchQuery.length > 0; | |
currentPage = 1; | |
currentGenre = ''; | |
// Update UI | |
document.querySelectorAll('.genre-tag').forEach(tag => { | |
tag.classList.remove('bg-purple-600'); | |
tag.classList.add('bg-gray-700'); | |
}); | |
libraryTitle.textContent = isSearching ? `Résultats pour "${currentSearchQuery}"` : 'Bibliothèque de Films'; | |
loadMovies(); | |
} | |
// Event listeners | |
video.addEventListener('timeupdate', function() { | |
const progress = (video.currentTime / video.duration) * 100; | |
progressBar.style.width = progress + '%'; | |
currentTime.textContent = formatTime(video.currentTime); | |
duration.textContent = formatTime(video.duration); | |
if (autoPlayEnabled && video.currentTime > 0 && video.duration > 0 && | |
(video.duration - video.currentTime) < 1) { | |
playNextMovie(); | |
} | |
}); | |
autoNextBtn.addEventListener('click', function() { | |
autoPlayEnabled = !autoPlayEnabled; | |
this.classList.toggle('text-purple-400'); | |
this.classList.toggle('text-green-400'); | |
this.innerHTML = autoPlayEnabled ? '<i class="fas fa-robot"></i> Auto ON' : '<i class="fas fa-robot"></i> Auto OFF'; | |
}); | |
playBtn.addEventListener('click', () => video.play()); | |
pauseBtn.addEventListener('click', () => video.pause()); | |
stopBtn.addEventListener('click', () => { | |
video.pause(); | |
video.currentTime = 0; | |
}); | |
randomBtn.addEventListener('click', () => { | |
currentMovieIndex = Math.floor(Math.random() * currentMovies.length); | |
initPlayer(currentMovies[currentMovieIndex]); | |
}); | |
searchBtn.addEventListener('click', () => searchMovies(searchInput.value)); | |
searchInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') searchMovies(searchInput.value); | |
}); | |
refreshBtn.addEventListener('click', () => { | |
currentPage = 1; | |
loadMovies(); | |
}); | |
randomMovieBtn.addEventListener('click', () => { | |
currentMovieIndex = Math.floor(Math.random() * currentMovies.length); | |
initPlayer(currentMovies[currentMovieIndex]); | |
}); | |
loadMoreBtn.addEventListener('click', () => { | |
currentPage++; | |
loadMovies(); | |
}); | |
yearFilter.addEventListener('change', () => { | |
currentPage = 1; | |
loadMovies(); | |
}); | |
ratingFilter.addEventListener('change', () => { | |
currentPage = 1; | |
loadMovies(); | |
}); | |
sortBy.addEventListener('change', () => { | |
currentPage = 1; | |
loadMovies(); | |
}); | |
startDemoBtn.addEventListener('click', () => { | |
if (currentMovies.length > 0) { | |
initPlayer(currentMovies[0]); | |
} | |
}); | |
// Initialize | |
document.addEventListener('DOMContentLoaded', function() { | |
loadGenres(); | |
loadMovies(); | |
// Show player overlay initially | |
playerOverlay.classList.remove('hidden'); | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=docto41/cinestream-ia" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |