diff --git a/index.html b/index.html index 9b6b317..62c8718 100644 --- a/index.html +++ b/index.html @@ -29,9 +29,9 @@
-
diff --git a/server.js b/server.js index 42d34eb..b78bcb5 100644 --- a/server.js +++ b/server.js @@ -1,19 +1,48 @@ const express = require('express'); +const fs = require('fs'); const path = require('path'); const app = express(); const PORT = 3000; -// Middleware для обслуживания статических файлов из папки "src" и корня приложения -app.use('/src', express.static(path.join(__dirname, 'src'))); +// Путь к видеофайлу +const videoPath = path.join(__dirname, 'movie.mp4'); // Замените 'movie.mp4' на ваш фильм +const serverStartTime = Date.now(); // Время запуска сервера + +// Маршрут для главной страницы app.use('/', express.static(path.join(__dirname, ''))); -// Главная страница -app.get('/', (req, res) => { - res.sendFile(path.join(__dirname, 'index.html')); +// Маршрут для видео +app.get('/video', (req, res) => { + const range = req.headers.range; + if (!range) { + return res.status(400).send('Requires Range header'); + } + + const videoSize = fs.statSync(videoPath).size; + const CHUNK_SIZE = 10 ** 6; // 1MB + const start = Number(range.replace(/\D/g, '')); + const end = Math.min(start + CHUNK_SIZE, videoSize - 1); + + const videoStream = fs.createReadStream(videoPath, { start, end }); + + res.writeHead(206, { + 'Content-Range': `bytes ${start}-${end}/${videoSize}`, + 'Accept-Ranges': 'bytes', + 'Content-Length': end - start + 1, + 'Content-Type': 'video/mp4', + }); + + videoStream.pipe(res); +}); + +// API для получения текущего времени воспроизведения +app.get('/current-time', (req, res) => { + const elapsedTime = (Date.now() - serverStartTime) / 1000; // Время с момента запуска сервера в секундах + res.json({ currentTime: elapsedTime }); }); // Запуск сервера app.listen(PORT, '0.0.0.0', () => { - console.log(`Server is running on http://0.0.0.0:${PORT}`); + console.log(`Server is running on http://localhost:${PORT}`); }); diff --git a/src/main.js b/src/main.js index 22ed758..40a3ca9 100644 --- a/src/main.js +++ b/src/main.js @@ -1,84 +1,110 @@ -document.addEventListener('DOMContentLoaded', () => { - const video = document.getElementById('video'); - const playPauseBtn = document.getElementById('playPauseBtn'); - const muteBtn = document.getElementById('muteBtn'); - const fullscreenBtn = document.getElementById('fullscreenBtn'); - const progressBar = document.querySelector('.progress-bar'); - const volumeSlider = document.querySelector('.volume-slider'); - const videoContainer = document.querySelector('.video-frame'); - - // Play/Pause - function togglePlay() { - if (video.paused) { - video.play(); - playPauseBtn.innerHTML = ''; - } else { - video.pause(); - playPauseBtn.innerHTML = ''; +document.addEventListener('DOMContentLoaded', async () => { + const video = document.getElementById('video'); + const playPauseBtn = document.getElementById('playPauseBtn'); + const muteBtn = document.getElementById('muteBtn'); + const fullscreenBtn = document.getElementById('fullscreenBtn'); + const progressBar = document.querySelector('.progress-bar'); + const volumeSlider = document.querySelector('.volume-slider'); + const videoContainer = document.querySelector('.video-frame'); + + // Получение текущего времени воспроизведения с сервера + async function fetchCurrentTime() { + try { + const response = await fetch('/current-time'); + if (!response.ok) { + throw new Error('Failed to fetch current time'); } + const data = await response.json(); + return data.currentTime; // Сервер возвращает время в секундах + } catch (error) { + console.error('Error fetching current time:', error); + return 0; // Если ошибка, начать воспроизведение с начала } - - // Update progress bar - function updateProgress() { - const progress = (video.currentTime / video.duration) * 100; - progressBar.value = progress; + } + + // Синхронизация времени видео с сервером + async function syncVideo() { + const currentTime = await fetchCurrentTime(); // Получаем время от сервера + video.currentTime = currentTime; // Устанавливаем текущее время видео + } + + // Событие, когда метаданные видео загружены + video.addEventListener('loadedmetadata', async () => { + await syncVideo(); // Синхронизация видео с сервера + video.play(); // Запускаем видео + }); + + // Play/Pause + function togglePlay() { + if (video.paused) { + video.play(); + playPauseBtn.innerHTML = ''; + } else { + video.pause(); + playPauseBtn.innerHTML = ''; } - - // Set video time based on progress bar - function setVideoProgress() { - video.currentTime = (progressBar.value * video.duration) / 100; + } + + // Обновление прогресса + function updateProgress() { + const progress = (video.currentTime / video.duration) * 100; + progressBar.value = progress; + } + + // Установка времени видео через прогресс-бар + function setVideoProgress() { + video.currentTime = (progressBar.value * video.duration) / 100; + } + + // Громкость + function updateVolume() { + video.volume = volumeSlider.value; + updateVolumeIcon(); + } + + function toggleMute() { + video.muted = !video.muted; + updateVolumeIcon(); + } + + function updateVolumeIcon() { + const icon = muteBtn.querySelector('i'); + if (video.muted || video.volume === 0) { + icon.className = 'fas fa-volume-mute'; + volumeSlider.value = 0; + } else { + icon.className = 'fas fa-volume-up'; + volumeSlider.value = video.volume; } - - // Volume controls - function updateVolume() { - video.volume = volumeSlider.value; - updateVolumeIcon(); + } + + // Fullscreen + function toggleFullscreen() { + if (!document.fullscreenElement) { + videoContainer.requestFullscreen(); + fullscreenBtn.innerHTML = ''; + } else { + document.exitFullscreen(); + fullscreenBtn.innerHTML = ''; } - - function toggleMute() { - video.muted = !video.muted; - updateVolumeIcon(); + } + + // Слушатели событий + playPauseBtn.addEventListener('click', togglePlay); + video.addEventListener('click', togglePlay); + video.addEventListener('timeupdate', updateProgress); + progressBar.addEventListener('change', setVideoProgress); + muteBtn.addEventListener('click', toggleMute); + volumeSlider.addEventListener('input', updateVolume); + fullscreenBtn.addEventListener('click', toggleFullscreen); + + // Поддержка клавиш на клавиатуре + document.addEventListener('keydown', (e) => { + if (e.code === 'Space') { + e.preventDefault(); + togglePlay(); } - - function updateVolumeIcon() { - const icon = muteBtn.querySelector('i'); - if (video.muted || video.volume === 0) { - icon.className = 'fas fa-volume-mute'; - volumeSlider.value = 0; - } else { - icon.className = 'fas fa-volume-up'; - volumeSlider.value = video.volume; - } - } - - // Fullscreen - function toggleFullscreen() { - if (!document.fullscreenElement) { - videoContainer.requestFullscreen(); - fullscreenBtn.innerHTML = ''; - } else { - document.exitFullscreen(); - fullscreenBtn.innerHTML = ''; - } - } - - // Event listeners - playPauseBtn.addEventListener('click', togglePlay); - video.addEventListener('click', togglePlay); - video.addEventListener('timeupdate', updateProgress); - progressBar.addEventListener('change', setVideoProgress); - muteBtn.addEventListener('click', toggleMute); - volumeSlider.addEventListener('input', updateVolume); - fullscreenBtn.addEventListener('click', toggleFullscreen); - - // Keyboard controls - document.addEventListener('keydown', (e) => { - if (e.code === 'Space') { - e.preventDefault(); - togglePlay(); - } - }); - - // Log ready state - console.log('Video player initialized'); - }); \ No newline at end of file + }); + + console.log('Video player initialized and synced with the server.'); +});