Пользовательский HTML-видеоплеер со списком воспроизведения (пошаговый пример)

Добро пожаловать в учебник и пример того, как создать собственный видеоплеер со списком воспроизведения. Хотите создать свой собственный видеоплеер и добавить в него плейлист? К сожалению, все не так просто. Нативных реализаций списка воспроизведения видео в HTML и Javascript нет. Единственный способ создать плейлист — создать свой собственный. Читайте пример!
• Отредактируйте video.js и установите свой плейлист в let playlist = ...

ШАГ 1) HTML

video.html

<!DOCTYPE html>
<html>
<head>
<title>JS Video Player</title>
<!-- https://fonts.google.com/icons -->
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="video.css"/>
<script defer src="video.js"></script>
</head>
<body>
<div id="vWrap">
<!-- (A) ВИДЕО ТЕГ -->
<video id="vVid"></video>
<!-- (B) КНОПКА ВОСПРОИЗВЕДЕНИЯ/ПАУЗЫ -->
<button id="vPlay" disabled><span id="vPlayIco" class="material-icons">
play_arrow
</span></button>
<!-- (C) ВРЕМЯ -->
<div id="vCron">
<span id="vNow"></span> / <span id="vTime"></span>
</div>
<!-- (D) SEEK BAR -->
<input id="vSeek" type="range" min="0" value="0" step="1" disabled/>
<!-- (E) VOLUME SLIDE -->
<span id="vVolIco" class="material-icons">volume_up</span>
<input id="vVolume" type="range" min="0" max="1" value="1" step="0.1" disabled/>
<!-- (F) PLAYLIST -->
<div id="vList"></div>
</div>
</body>
</html>

Для этого пользовательского видеоплеера есть 6 компонентов.
A. <video id="vVid"> Сам тег видео.
B. <button id="vPlay"> Кнопка воспроизведения и паузы.
C. <span id="vNow"></span> – Текущее время воспроизведения. <span id="vTime"></span> – Общее время текущего видео.
D. <input id="vSeek"> Ползунок времени поиска, это в секундах.
E. <input id="vVolume"> Ползунок громкости, это значение от 0,0 (без звука) до 1,0 (самый громкий).
F. <div id="vList"> Для списка воспроизведения видео мы будем использовать Javascript для его создания.

ШАГ 2) ИНИЦИАЛИЗАЦИЯ ВИДЕОПРОИГРЫВАТЕЛЯ

video.js

window.addEventListener("DOMContentLoaded", () => {
// (A) PLAYER INIT
// (A1) ПЛЕЙЛИСТ - МЕНЯЙТЕ НА СОБСТВЕННЫЙ!
let playlist = [
{name: "Video A", src: "dikaya-priroda-afriki-safari-zapovedniki-tanzaniya.mp4"},
{name: "Video B", src: "priroda-uzbekistana-voshojdeniye-na-pik-ohotnichey-aukashha.mp4"},
{name: "Video C", src: "siciliya-priroda-vulkany-i-rodina-italyanskoy-mafii..mp4"}
];
// (A2) ВИДЕОПРОИГРЫВАТЕЛЬ И ПОЛУЧИТЕ УПРАВЛЕНИЕ HTML
const video = document.getElementById("vVid"),
vPlay = document.getElementById("vPlay"),
vPlayIco = document.getElementById("vPlayIco"),
vNow = document.getElementById("vNow"),
vTime = document.getElementById("vTime"),
vSeek = document.getElementById("vSeek"),
vVolume = document.getElementById("vVolume"),
vVolIco = document.getElementById("vVolIco"),
vList = document.getElementById("vList");
// (A3) СОЗДАТЬ ПЛЕЙЛИСТ
for (let i in playlist) {
let row = document.createElement("div");
row.className = "vRow";
row.innerHTML = playlist[i]["name"];
row.addEventListener("click", () => { vidPlay(i); });
playlist[i]["row"] = row;
vList.appendChild(row);
}

• Первое, что мы делаем в Javascript — прежде чем продолжить, убедитесь, что загрузка HTML завершена. DOMContentLoaded.
• (A1) Должно playlistбыть понятно. Каждая видеозапись должна иметь название дорожки nameи источник src.
• (A2) Получите все элементы HTML.
• (A3) Прокрутите playlist, чтобы сгенерировать HTML. Просто обратите внимание, что нажатие на дорожку вызовет vidPlay().

ШАГ 3) ИГРОВОЙ МЕХАНИЗМ

video.js

// (B) PLAY МЕХАНИЗМ
// (B1) ФЛАГИ
var vidNow = 0, // текущее видео
vidStart = false, // автозапуск следующего видео
// (B2) ВОСПРОИЗВЕСТИ ВЫБРАННОЕ ВИДЕО
vidPlay = (idx, nostart) => {
vidNow = idx;
vidStart = nostart ? false : true;
video.src = playlist[idx]["src"];
for (let i in playlist) {
if (i == idx) { playlist[i]["row"].classList.add("now"); }
else { playlist[i]["row"].classList.remove("now"); }
}
};
// (B3) АВТОЗАПУСК ПРИ ДОСТАТОЧНОЙ БУФЕРНОСТИ
video.addEventListener("canplay", () => { if (vidStart) {
video.play();
vidStart = false;
}});
// (B4) АВТОЗАПУСК СЛЕДУЮЩЕГО ВИДЕО В ПЛЕЙЛИСТЕ
video.addEventListener("ended", () => {
vidNow++;
if (vidNow >= playlist.length) { vidNow = 0; }
vidPlay(vidNow);
});
// (B5) ПЕРВОЕ ВИДЕО НАСТРОЙКИ ИНИТ.
vidPlay(0, true);

• (B1) Мы используем 2 флага для управления play.
◦ vidNow отслеживает, какое видео сейчас воспроизводится в формате playlist.
◦ vidStart будет использоваться для управления автовоспроизведением в (B3).
• (B2) vidPlay() воспроизведёт выбранное видео. Например, vidPlay(1) будет воспроизводиться второе видео в формате playlist. Это работает путем установки video.src = playlist[N]["src"]. Опять же, обратите внимание vidStart здесь.
• (B3) Начать воспроизведение, как только текущее видео будет достаточно буферизовано, но только если vidStart установлено.
◦ В основном, canplay может быть вызвано двумя возможными способами. Когда мы меняем video.src = NEW VIDEO, или при восстановлении после плохого соединения.
◦ Когда у пользователя плохое подключение к Интернету, мы не хотим вызывать фрагментарное воспроизведение.
◦ Таким образом, наличие vidStart, чтобы убедиться, что автовоспроизведение применяется только после нажатия на элемент списка воспроизведения (или при автоматическом запуске следующего видео в списке).
• (B4) Когда текущее видео закончится, vidNow++ будет воспроизводиться следующее видео.

ШАГ 4) КНОПКА ВОСПРОИЗВЕДЕНИЯ/ПАУЗЫ

video.js

// (C) КНОПКА ВОСПРОИЗВЕДЕНИЯ/ПАУЗЫ
// (C1) АВТО НАСТРОЙКА ВОСПРОИЗВЕДЕНИЕ/ПАУЗА ТЕКСТ
video.addEventListener("play", () => {
vPlayIco.innerHTML = "pause";
});
video.addEventListener("pause", () => {
vPlayIco.innerHTML = "play_arrow";
});
// (C2) НАЖМИТЕ ДЛЯ ВОСПРОИЗВЕДЕНИЯ/ПАУЗЫ
vPlay.addEventListener("click", () => {
if (video.paused) { video.play(); }
else { video.pause(); }
});

• (C1) Автоматически обновлять значок воспроизведения/паузы в качестве воспроизведения/паузы видео. Кстати, здесь используются значки материалов Google.
• (C2) Нажмите, чтобы воспроизвести, если видео приостановлено, нажмите, чтобы приостановить, если видео воспроизводится.

ШАГ 5) ОТСЛЕЖИВАЙТЕ ВРЕМЯ

video.js

// (D) ТРЭК ПРОГРЕСС
// (D1) ВСПОМОГАТЕЛЬНАЯ ФУНКЦИЯ - ФОРМАТ ЧЧ:ММ:СС
var timeString = (secs) => {
// ЧАСЫ, МИНУТЫ, СЕКУНДЫ
let ss = Math.floor(secs),
hh = Math.floor(ss / 3600),
mm = Math.floor((ss - (hh * 3600)) / 60);
ss = ss - (hh * 3600) - (mm * 60);
// ВОЗВРАТ ФОРМАТИРОВАННОЕ ВРЕМЯ
if (hh > 0) { mm = mm<10 ? "0"+mm : mm; }
ss = ss<10 ? "0"+ss : ss;
return hh>0 ? `${hh}:${mm}:${ss}` : `${mm}:${ss}` ;
};
// (D2) ИНИЦИАЛИЗАЦИЯ УСТАНОВИТЬ ВРЕМЯ ОТСЛЕЖИВАНИЯ
video.addEventListener("loadedmetadata", () => {
vNow.innerHTML = timeString(0);
vTime.innerHTML = timeString(video.duration);
});
// (D3) ОБНОВЛЕНИЕ ВРЕМЕНИ В ВОСПРОИЗВЕДЕНИЕ
video.addEventListener("timeupdate", () => {
vNow.innerHTML = timeString(video.currentTime);
});

• (D1) В Javascript у видео есть 2 очень удобных свойства — video.durationи video.currentTime. Проблема в том, что они в секундах. Таким образом, нам нужна вспомогательная функция для форматирования «красивой временной строки».
• (D2) Обновить общее время воспроизведения при получении метаданных.
• (D3) Обновление текущего времени во время воспроизведения видео.

ШАГ 6) ПАНЕЛЬ ПРОГРЕССА ВРЕМЕНИ

video.js

// (E) ПРОГРЕСС БАР
video.addEventListener("loadedmetadata", () => {
// (E1) SET SEEK BAR MAX TIME
vSeek.max = Math.floor(video.duration);
// (E2) ВРЕМЯ ПРОГРЕСС БАРА ИЗМЕНЕНИЯ ПОЛЬЗОВАТЕЛЯ
var vSeeking = false; // ПОЛЬЗОВАТЕЛЬ ИЗМЕНЯЕТ ВРЕМЯ
vSeek.addEventListener("input", () => {
vSeeking = true; // ПРЕДОТВРАЩАЕТ КОНФЛИКЦИЮ С (E3)
});
vSeek.addEventListener("change", () => {
video.currentTime = vSeek.value;
if (!video.paused) { video.play(); }
vSeeking = false;
});
// (E3) ОБНОВЛЕНИЕ ПРОГРЕСС БАРА ПРИ ВОСПРОИЗВЕДЕНИЕ
video.addEventListener("timeupdate", () => {
if (!vSeeking) { vSeek.value = Math.floor(video.currentTime); }
});
});

• (E1) Установите maxвремя полосы прогресса при получении метаданных видео.
• (E2) Обновление video.currentTime, когда пользователь меняет прогресс бар.
• (E3) Обновляйте прогресс бар по мере воспроизведения видео.
• (E2 и E3) Флаг vSeeking немного сбивает с толку. Но в основном мы не хотим, чтобы (E3) обновлялся, пока пользователь вручную перетаскивает прогресс бар.

ШАГ 7) ОБЪЕМ

video.js

// (F) ОБЪЕМ
vVolume.addEventListener("change", () => {
video.volume = vVolume.value;
vVolIco.innerHTML = (vVolume.value==0 ? "volume_mute" : "volume_up");
});

ШАГ 8) ВКЛЮЧИТЕ/ОТКЛЮЧИТЕ ВСЕ УПРАВЛЕНИЕ

video.js

// (G) ВКЛЮЧИТЬ/ОТКЛЮЧИТЬ УПРАВЛЕНИЕ
video.addEventListener("canplay", () => {
vPlay.disabled = false;
vVolume.disabled = false;
vSeek.disabled = false;
});
video.addEventListener("waiting", () => {
vPlay.disabled = true;
vVolume.disabled = true;
vSeek.disabled = true;
});
});

Вы можете посмотреть или скачать готовый скрипт.
Посмотреть
Скачать

Обсуждение закрыто.