I played around with your code a bit to get it to play playlist files.I'd like to do everything through a self-created HTML website, written to support local file playback (mp3 audio/mp4 video). It's also should be possible to play radio streams. This wouldn't require a media player like VLC/WMP, etc., since the interface is the HTML page and the Rainmeter WebView plugin itself. I'm truly grateful for any support.![]()
![]()
![]()
![]()
Another tool would be to read the metadata via HTML.
-Cover
-Title
-Artist
ezgif-8bbcc64189f743.gif
1. Due to CORS, it is necessary to start a local server with python.
python -m http.server 8000
Also, the html file should be in the directory where the M3U is.
Example:
Let the M3U file be under the D:\MP3 folder
Code:
cd D:\MP3python -m http.server 8000
Code:
http://localhost:8000/PLAYER.html
HTML CODE
Code:
<!DOCTYPE html><html lang="de"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>HLS Media Player</title> <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> <style> :root { --text-color: #007BCF; --background-color: #f7f7f7; --border-color: #ddd; } body { font-family: Arial, sans-serif; margin: 0; background-color: transparent; } .player-wrapper { position: relative; display: inline-block; width: 300px; /* Einheitliche Breite für Media Player */ } #mediaPlayer { display: block; width: 100%; /* Passt sich der Breite des Wrappers an */ height: auto; margin-top: 20px; } .file-input-container { position: relative; display: flex; align-items: center; margin-top: 25px; } .file-input-container label { cursor: pointer; color: var(--text-color); font-size: 24px; width: 25px; height: 25px; display: inline-flex; align-items: center; justify-content: center; margin-right: 5px; } #fileName { position: absolute; top: -20px; left: 0; color: var(--text-color); font-size: 14px; width: 300px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; } .hidden-input { display: none; } .url-input-container { display: none; position: relative; margin-left: 10px; align-items: center; } .url-input-container input { margin-left: 10px; width: 250px; font-size: 14px; color: var(--text-color); border: 1px solid var(--text-color); padding: 2px; } .url-input-container button { margin-left: 5px; font-size: 14px; background-color: var(--text-color); color: white; border: none; cursor: pointer; } /* Oynatma listesi stili */ .playlist-container { width: 300px; max-height: 200px; overflow-y: auto; margin-top: 10px; background-color: var(--background-color); border: 1px solid var(--border-color); display: none; } .playlist-item { padding: 5px 10px; cursor: pointer; font-size: 14px; border-bottom: 1px solid var(--border-color); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .playlist-item:hover, .playlist-item.active { background-color: rgba(0, 123, 207, 0.1); } .playlist-controls { display: flex; justify-content: space-between; margin-top: 5px; } .playlist-button { background-color: var(--text-color); border: none; color: white; padding: 3px 5px; font-size: 12px; cursor: pointer; border-radius: 3px; } </style></head><body> <div class="player-wrapper"> <!-- Media Player --> <video id="mediaPlayer" controls></video> <!-- Dosya Seçimi --> <div class="file-input-container"> <span id="fileName">Bitte Datei auswählen</span> <label for="fileInput" title="Medya Dosyası Seç">📁</label> <input type="file" id="fileInput" class="hidden-input" accept="audio/*,video/*"> <label for="playlistInput" title="Oynatma Listesi Seç">📋</label> <input type="file" id="playlistInput" class="hidden-input" accept=".m3u,.m3u8,.pls"> <label id="magnetLinkButton" title="URL Giriş" style="cursor: pointer;">🔗</label> <label id="togglePlaylistButton" title="Oynatma Listesini Göster/Gizle" style="cursor: pointer;">📑</label> </div> <!-- URL Girişi --> <div class="url-input-container" id="urlInputContainer"> <input type="text" id="urlInput" placeholder="Webstream URL eingeben"> <button id="playUrlButton">▶</button> </div> <!-- Oynatma Listesi --> <div class="playlist-container" id="playlistContainer"> <div id="playlistItems"></div> <div class="playlist-controls"> <button class="playlist-button" id="prevButton">⏮ Önceki</button> <button class="playlist-button" id="clearPlaylistButton">🗑️ Temizle</button> <button class="playlist-button" id="nextButton">Sonraki ⏭</button> </div> </div> </div> <script> // DOM Elementleri const fileInput = document.getElementById('fileInput'); const playlistInput = document.getElementById('playlistInput'); const mediaPlayer = document.getElementById('mediaPlayer'); const fileNameElement = document.getElementById('fileName'); const urlInputContainer = document.getElementById('urlInputContainer'); const urlInput = document.getElementById('urlInput'); const playUrlButton = document.getElementById('playUrlButton'); const magnetLinkButton = document.getElementById('magnetLinkButton'); const togglePlaylistButton = document.getElementById('togglePlaylistButton'); const playlistContainer = document.getElementById('playlistContainer'); const playlistItemsContainer = document.getElementById('playlistItems'); const prevButton = document.getElementById('prevButton'); const nextButton = document.getElementById('nextButton'); const clearPlaylistButton = document.getElementById('clearPlaylistButton'); // Oynatma listesi state'i let playlist = []; let currentPlaylistIndex = -1; let currentHls = null; // HLS Stream oynatma const playHlsStream = (url) => { if (currentHls) { currentHls.destroy(); currentHls = null; } if (Hls.isSupported()) { const hls = new Hls(); hls.loadSource(url); hls.attachMedia(mediaPlayer); hls.on(Hls.Events.MANIFEST_PARSED, () => { mediaPlayer.play(); }); currentHls = hls; } else if (mediaPlayer.canPlayType('application/vnd.apple.mpegurl')) { mediaPlayer.src = url; mediaPlayer.addEventListener('loadedmetadata', () => { mediaPlayer.play(); }); } else { alert('HLS bu tarayıcı tarafından desteklenmiyor.'); } }; // M3U/M3U8 oynatma listesini işle const parseM3UPlaylist = (content) => { const lines = content.split(/\r?\n/); const entries = []; let title = ""; for (let i = 0; i < lines.length; i++) { const line = lines[i].trim(); if (line === "#EXTM3U" || line === "") continue; if (line.startsWith("#EXTINF:")) { const titleMatch = line.match(/,(.+)$/); if (titleMatch) { title = titleMatch[1]; } else { title = "Parça " + (entries.length + 1); } continue; } if (!line.startsWith('#') && line !== "") { let url = line; if (url.startsWith('file://')) { try { const filePath = url.replace('file://', ''); url = 'http://localhost:8000/' + encodeURIComponent(filePath); } catch (e) { console.error('URL kodlama hatası:', e); } } entries.push({ title: title || `Parça ${entries.length + 1}`, url: url }); title = ""; } } return entries; }; // Medya oynatma const playMedia = (source, isLocal = false) => { if (currentHls) { currentHls.destroy(); currentHls = null; } try { if (isLocal) { mediaPlayer.src = URL.createObjectURL(source); mediaPlayer.play().catch(e => { console.error("Oynatma hatası:", e); fileNameElement.textContent = "Oynatma hatası: " + e.message; }); } else if (source.toLowerCase().includes('.m3u8')) { playHlsStream(source); } else { mediaPlayer.src = source; mediaPlayer.play().catch(e => { console.error("Oynatma hatası:", e); fileNameElement.textContent = "Oynatma hatası: " + e.message; }); } } catch (e) { console.error("Medya oynatılırken hata:", e); fileNameElement.textContent = "Oynatma hatası: " + e.message; } }; // Oynatma listesi yükle playlistInput.addEventListener('change', (event) => { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { const content = e.target.result; let entries = []; if (file.name.toLowerCase().endsWith('.pls')) { entries = parsePLSPlaylist(content); } else { // .m3u, .m3u8 entries = parseM3UPlaylist(content); } if (entries.length > 0) { playlist = entries; fileNameElement.textContent = `Oynatma Listesi: ${file.name}`; renderPlaylist(); playlistContainer.style.display = 'block'; // İlk parçayı oynat playPlaylistItem(0); } else { alert('Oynatma listesi boş veya geçersiz.'); } }; reader.readAsText(file); }); // PLS oynatma listesini işle const parsePLSPlaylist = (content) => { const lines = content.split(/\r?\n/); const entries = []; const fileRegex = /^File(\d+)=(.+)$/; const titleRegex = /^Title(\d+)=(.+)$/; const files = {}; const titles = {}; for (let i = 0; i < lines.length; i++) { const line = lines[i].trim(); const fileMatch = line.match(fileRegex); if (fileMatch) { const index = fileMatch[1]; files[index] = fileMatch[2]; continue; } const titleMatch = line.match(titleRegex); if (titleMatch) { const index = titleMatch[1]; titles[index] = titleMatch[2]; continue; } } // Dosya sayısını bul for (const index in files) { entries.push({ title: titles[index] || `Parça ${index}`, url: files[index] }); } return entries; }; // Oynatma listesi yükle playlistInput.addEventListener('change', (event) => { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { const content = e.target.result; let entries = []; if (file.name.toLowerCase().endsWith('.pls')) { entries = parsePLSPlaylist(content); } else { // .m3u, .m3u8 entries = parseM3UPlaylist(content); } if (entries.length > 0) { playlist = entries; fileNameElement.textContent = `Oynatma Listesi: ${file.name}`; renderPlaylist(); playlistContainer.style.display = 'block'; // İlk parçayı oynat playPlaylistItem(0); } else { alert('Oynatma listesi boş veya geçersiz.'); } }; reader.readAsText(file); }); // Oynatma listesini güncelle const renderPlaylist = () => { playlistItemsContainer.innerHTML = ''; playlist.forEach((item, index) => { const element = document.createElement('div'); element.className = 'playlist-item'; if (index === currentPlaylistIndex) { element.className += ' active'; } element.textContent = item.title; element.title = item.url; element.addEventListener('click', () => { playPlaylistItem(index); }); playlistItemsContainer.appendChild(element); }); }; // Oynatma listesindeki öğeyi oynat const playPlaylistItem = (index) => { if (index >= 0 && index < playlist.length) { currentPlaylistIndex = index; const item = playlist[index]; fileNameElement.textContent = item.title; playMedia(item.url); renderPlaylist(); } }; // Sıradaki parçayı oynat const playNext = () => { if (playlist.length > 0) { let nextIndex = currentPlaylistIndex + 1; if (nextIndex >= playlist.length) { nextIndex = 0; } playPlaylistItem(nextIndex); } }; // Önceki parçayı oynat const playPrev = () => { if (playlist.length > 0) { let prevIndex = currentPlaylistIndex - 1; if (prevIndex < 0) { prevIndex = playlist.length - 1; } playPlaylistItem(prevIndex); } }; // Oynatıcı sonlandığında sonraki parçaya geç mediaPlayer.addEventListener('ended', () => { playNext(); }); // Magnet Link butonu: URL girişi göster/gizle magnetLinkButton.addEventListener('click', () => { urlInputContainer.style.display = urlInputContainer.style.display === 'none' ? 'flex' : 'none'; }); // Oynatma listesi göster/gizle togglePlaylistButton.addEventListener('click', () => { playlistContainer.style.display = playlistContainer.style.display === 'none' ? 'block' : 'none'; }); // URL'den oynat butonu playUrlButton.addEventListener('click', () => { const url = urlInput.value.trim(); if (url) { fileNameElement.textContent = "Web akışı oynatılıyor"; playMedia(url); urlInputContainer.style.display = 'none'; // URL'i oynatma listesine ekle (isteğe bağlı) const urlName = url.split('/').pop() || "Web akışı"; playlist.push({ title: urlName, url: url }); currentPlaylistIndex = playlist.length - 1; renderPlaylist(); playlistContainer.style.display = 'block'; } }); // URL giriş alanı Enter tuşu kontrolü urlInput.addEventListener('keypress', (event) => { if (event.key === 'Enter') { playUrlButton.click(); } }); // Önceki parça butonu prevButton.addEventListener('click', () => { playPrev(); }); // Sonraki parça butonu nextButton.addEventListener('click', () => { playNext(); }); // Oynatma listesini temizle butonu clearPlaylistButton.addEventListener('click', () => { playlist = []; currentPlaylistIndex = -1; renderPlaylist(); fileNameElement.textContent = "Oynatma listesi temizlendi"; }); // Klavye kısayolları document.addEventListener('keydown', (event) => { // Space tuşu: Oynat/Duraklat if (event.code === 'Space' && document.activeElement !== urlInput) { event.preventDefault(); if (mediaPlayer.paused) { mediaPlayer.play(); } else { mediaPlayer.pause(); } } // Sağ ok: Sonraki parça if (event.code === 'ArrowRight' && event.altKey) { event.preventDefault(); playNext(); } // Sol ok: Önceki parça if (event.code === 'ArrowLeft' && event.altKey) { event.preventDefault(); playPrev(); } }); // URL'den oynatma listesi yükleme fonksiyonu (daha sonra eklenebilir) const loadPlaylistFromUrl = (url) => { fetch(url) .then(response => response.text()) .then(content => { let entries = []; if (url.toLowerCase().endsWith('.pls')) { entries = parsePLSPlaylist(content); } else { // .m3u, .m3u8 entries = parseM3UPlaylist(content); } if (entries.length > 0) { playlist = entries; fileNameElement.textContent = `Oynatma Listesi: ${url.split('/').pop()}`; renderPlaylist(); playlistContainer.style.display = 'block'; // İlk parçayı oynat playPlaylistItem(0); } else { alert('Oynatma listesi boş veya geçersiz.'); } }) .catch(error => { console.error('Oynatma listesi yüklenirken hata:', error); alert('Oynatma listesi yüklenemedi.'); }); }; // Sürükle bırak desteği ekle const dropZone = document.querySelector('.player-wrapper'); ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { dropZone.addEventListener(eventName, (e) => { e.preventDefault(); e.stopPropagation(); }, false); }); dropZone.addEventListener('dragover', () => { dropZone.style.backgroundColor = 'rgba(0, 123, 207, 0.1)'; }, false); dropZone.addEventListener('dragleave', () => { dropZone.style.backgroundColor = 'transparent'; }, false); dropZone.addEventListener('drop', (e) => { dropZone.style.backgroundColor = 'transparent'; if (e.dataTransfer.files.length) { const file = e.dataTransfer.files[0]; // Dosya tipine göre işle if (file.name.toLowerCase().match(/\.(m3u|m3u8|pls)$/)) { // Playist dosyası playlistInput.files = e.dataTransfer.files; playlistInput.dispatchEvent(new Event('change')); } else if (file.type.startsWith('audio/') || file.type.startsWith('video/')) { // Medya dosyası fileInput.files = e.dataTransfer.files; fileInput.dispatchEvent(new Event('change')); } } }, false); </script></body></html>
Statistics: Posted by tass_co — Today, 12:22 am