Files
syncfilm/public/index.html
T

239 lines
8.0 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>SyncFilm</title>
<script src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="video-player">
<input type="file" id="video-file" accept="video/*">
<video id="video"></video>
<div class="video-controls">
<button id="play-btn">Lecture</button>
<button id="pause-btn">Pause</button>
<button id="restart-btn">Recommencer</button>
<button id="forward-btn">+10s</button>
<button id="backward-btn">-10s</button>
<input type="range" id="volume-bar" min="0" max="1" step="0.01" value="1">
<button id="mute-btn">Mute</button>
</div>
<div class="video-time-bar">
<input type="range" id="seek-bar" min="0" value="0" step="0.01" disabled>
<span id="time-label">00:00 / 00:00</span>
</div>
</div>
<div id="ws-status">Connecté au WebSocket</div>
<div id="users">
<h2>Liste des personnes connectées</h2>
<ul></ul>
</div>
<script>
const socket = io();
let users = [];
let myFilename = null;
const video = document.getElementById('video');
const seekBar = document.getElementById('seek-bar');
const timeLabel = document.getElementById('time-label');
const volumeBar = document.getElementById('volume-bar');
const muteBtn = document.getElementById('mute-btn');
const wsStatus = document.getElementById('ws-status');
const videoPlayer = document.getElementById('video-player');
// Gestion de la liste des utilisateurs
socket.on('users', function(userList) {
users = userList;
const ul = document.querySelector('#users ul');
ul.innerHTML = '';
userList.forEach(function(user) {
const filename = user.filename ? user.filename : 'Aucun fichier sélectionné';
const li = document.createElement('li');
li.textContent = `ID: ${user.id} — Fichier: ${filename}`;
ul.appendChild(li);
if (user.id === socket.id) {
myFilename = user.filename || null;
}
});
updateSeekBarState();
pauseVideo();
});
// Sélection du fichier vidéo
document.getElementById('video-file').addEventListener('change', function(event) {
const file = event.target.files[0];
if (file) {
const url = URL.createObjectURL(file);
video.src = url;
video.load();
myFilename = file.name;
socket.emit('videoSelected', file.name);
} else {
myFilename = null;
socket.emit('videoSelected', null);
}
});
function allUsersHaveSameFile() {
if (!myFilename) return false;
return users.length > 0 && users.every(u => u.filename && u.filename === myFilename);
}
socket.on('connect', () => {
wsStatus.textContent = 'Connecté au WebSocket';
wsStatus.style.color = '#50fa7b';
if (video.src && video.src.startsWith('blob:') && myFilename) {
socket.emit('videoSelected', myFilename);
}
});
socket.on('disconnect', () => {
wsStatus.textContent = 'Déconnecté du WebSocket';
wsStatus.style.color = '#ff5555';
pauseVideo();
});
function pauseVideo() {
video.pause();
}
function formatTime(seconds) {
const min = Math.floor(seconds / 60);
const sec = Math.floor(seconds % 60);
return `${min.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}`;
}
video.addEventListener('loadedmetadata', function() {
seekBar.max = video.duration;
seekBar.value = 0;
updateSeekBarState();
updateTimeLabel();
volumeBar.value = video.volume;
volumeBar.disabled = video.muted;
});
video.addEventListener('timeupdate', function() {
seekBar.value = video.currentTime;
updateTimeLabel();
});
seekBar.addEventListener('input', function() {
updateTimeLabel();
if (allUsersHaveSameFile()) {
socket.emit('videoCommand', { action: 'seek', time: parseFloat(seekBar.value) });
}
});
function updateTimeLabel() {
const current = formatTime(video.currentTime);
const total = formatTime(video.duration || 0);
timeLabel.textContent = `${current} / ${total}`;
}
function updateSeekBarState() {
seekBar.disabled = !allUsersHaveSameFile();
}
document.getElementById('play-btn').onclick = function() {
if (allUsersHaveSameFile()) {
socket.emit('videoCommand', { action: 'play', time: video.currentTime });
}
};
document.getElementById('pause-btn').onclick = function() {
if (allUsersHaveSameFile()) {
socket.emit('videoCommand', { action: 'pause', time: video.currentTime });
}
};
document.getElementById('restart-btn').onclick = function() {
if (allUsersHaveSameFile()) {
socket.emit('videoCommand', { action: 'restart' });
}
};
document.getElementById('forward-btn').onclick = function() {
if (allUsersHaveSameFile()) {
socket.emit('videoCommand', {
action: 'forward',
time: video.currentTime,
paused: video.paused
});
}
};
document.getElementById('backward-btn').onclick = function() {
if (allUsersHaveSameFile()) {
socket.emit('videoCommand', {
action: 'backward',
time: video.currentTime,
paused: video.paused
});
}
};
socket.on('videoCommand', function(cmd) {
if (!allUsersHaveSameFile()) return;
switch (cmd.action) {
case 'play':
video.currentTime = cmd.time;
video.play();
break;
case 'pause':
video.currentTime = cmd.time;
video.pause();
break;
case 'restart':
video.currentTime = 0;
video.play();
break;
case 'forward':
video.currentTime = cmd.time + 10;
if (cmd.paused) video.pause(); else video.play();
break;
case 'backward':
video.currentTime = Math.max(0, cmd.time - 10);
if (cmd.paused) video.pause(); else video.play();
break;
case 'seek':
video.currentTime = cmd.time;
break;
}
});
volumeBar.addEventListener('input', function() {
if (!video.muted) {
video.volume = parseFloat(volumeBar.value);
}
});
muteBtn.onclick = function() {
video.muted = !video.muted;
volumeBar.disabled = video.muted;
muteBtn.textContent = video.muted ? "Unmute" : "Mute";
};
video.addEventListener('volumechange', function() {
volumeBar.value = video.volume;
volumeBar.disabled = video.muted;
muteBtn.textContent = video.muted ? "Unmute" : "Mute";
});
// Gestion de l'affichage automatique des contrôles
let controlsTimeout;
function showControls() {
videoPlayer.classList.remove('hide-controls');
clearTimeout(controlsTimeout);
controlsTimeout = setTimeout(() => {
if (video.src) videoPlayer.classList.add('hide-controls');
}, 3000);
}
videoPlayer.addEventListener('mousemove', showControls);
document.addEventListener('mousemove', showControls);
videoPlayer.addEventListener('mouseleave', () => {
if (video.src) videoPlayer.classList.add('hide-controls');
});
video.addEventListener('loadeddata', showControls);
videoPlayer.addEventListener('focusin', showControls);
videoPlayer.addEventListener('click', showControls);
document.getElementById('video-file').addEventListener('change', showControls);
</script>
</body>
</html>