byuik
2 February 2025
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IPTV Player</title>
<link href="https://vjs.zencdn.net/7.20.3/video-js.css" rel="stylesheet" />
<script src="https://vjs.zencdn.net/7.20.3/video.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-hls/5.15.0/videojs-contrib-hls.min.js"></script>
<style>
#iptv-player {
width: 600px;
margin: 0 auto;
}
video, select, input, button {
width: 100%;
box-sizing: border-box;
}
select, input, button {
margin-top: 10px;
padding: 10px;
font-size: 16px;
}
#current-stream {
margin-top: 10px;
font-size: 18px;
text-align: center;
font-weight: bold;
}
</style>
</head>
<body>
<div id="iptv-player">
<video id="video-player" class="video-js vjs-default-skin" controls autoplay width="600" height="400">
Ваш браузер не поддерживает воспроизведение видео.
</video>
<div id="current-stream">Текущий поток: Не выбран</div>
<select id="stream-selector">
<option value="">Загрузка потоков...</option>
</select>
<input type="text" id="manual-url" placeholder="Введите ссылку на поток" />
<div style="display: flex; gap: 10px; justify-content: center;">
<button onclick="playManualStream()">Воспроизвести</button>
<button onclick="prevStream()">Назад</button>
<button onclick="nextStream()">Вперед</button>
</div>
</div>
<script>
const videoPlayer = videojs("video-player", {
techOrder: ["html5", "hls"],
html5: { hls: { overrideNative: true } }
});
const streamSelector = document.getElementById("stream-selector");
const manualUrlInput = document.getElementById("manual-url");
const currentStreamText = document.getElementById("current-stream");
const m3uUrl = "https://api.allorigins.win/raw?url=" + encodeURIComponent("https://tva.org.ua/ip/kino-plus.m3u");
let streams = [];
let currentStreamIndex = 0;
async function loadM3U(url) {
try {
const response = await fetch(url, { mode: 'cors' });
if (!response.ok) throw new Error("Ошибка загрузки M3U файла");
const text = await response.text();
return parseM3U(text);
} catch (error) {
console.error("Ошибка загрузки M3U:", error);
alert("Не удалось загрузить список потоков.");
return [];
}
}
function parseM3U(m3uContent) {
const lines = m3uContent.split("\n");
const parsedStreams = [];
let currentName = "";
lines.forEach((line, index) => {
line = line.trim();
if (line.startsWith("#EXTINF")) {
const nameMatch = line.match(/,(.+)$/);
if (nameMatch) currentName = nameMatch[1];
} else if (line && !line.startsWith("#")) {
parsedStreams.push({ name: currentName || "Без названия", url: line.trim() });
currentName = "";
}
});
return parsedStreams;
}
function populateStreamSelector() {
streamSelector.innerHTML = "";
streams.forEach((stream, index) => {
const option = document.createElement("option");
option.value = stream.url;
option.textContent = `${index + 1}. ${stream.name}`;
streamSelector.appendChild(option);
});
}
async function getStreamType(url) {
try {
const response = await fetch(url, { method: 'HEAD' });
const contentType = response.headers.get("Content-Type");
if (contentType.includes("mpegurl")) return "application/x-mpegURL";
if (contentType.includes("mp2t")) return "video/mp2t";
if (contentType.includes("mp4")) return "video/mp4";
return "video/mp4";
} catch {
return "video/mp4";
}
}
async function playStream(url, index) {
if (!url) return;
console.log(`Попытка воспроизведения: ${url}`);
currentStreamIndex = index;
currentStreamText.textContent = `Текущий поток: ${index + 1}. ${streams[index] ? streams[index].name : "Неизвестный поток"}`;
const type = await getStreamType(url);
videoPlayer.src({ type, src: url });
videoPlayer.play().catch(error => console.error("Ошибка воспроизведения потока:", error));
}
function playManualStream() {
const manualUrl = manualUrlInput.value.trim();
if (manualUrl) {
playStream(manualUrl, -1);
} else {
alert("Введите корректный URL потока.");
}
}
function prevStream() {
if (currentStreamIndex > 0) {
currentStreamIndex--;
playStream(streams[currentStreamIndex].url, currentStreamIndex);
}
}
function nextStream() {
if (currentStreamIndex < streams.length - 1) {
currentStreamIndex++;
playStream(streams[currentStreamIndex].url, currentStreamIndex);
}
}
streamSelector.addEventListener("change", () => {
const selectedUrl = streamSelector.value;
const index = streams.findIndex(stream => stream.url === selectedUrl);
playStream(selectedUrl, index);
});
(async function init() {
streams = await loadM3U(m3uUrl);
if (streams.length > 0) {
populateStreamSelector();
playStream(streams[0].url, 0);
} else {
alert("Список потоков пуст.");
}
})();
</script>
</body>
</html>
Теги
- Войдите или зарегистрируйтесь, чтобы оставлять комментарии