Login | Register (Invite Only)
Title: Page Telegram of Amfile.org
Description: Brown Hats Collective F' Around and Find Out user of the Interwebs and Project Developer for a Cause Toward Insuring a Future of Liberty without Illusion.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@=:---#@@@#%@@@*=+#@%====@@@@..:--@#====@-==#@@@+===#@%=-+@... -@@@@*@@@=+@%-*@ @@@.*@-.@@@.:@@==@:=@+ -..*@@@:# @:@=.=. #%.#@@@@ ::..@.%#.@@ %+ %@@% #@@-.@+ #@ @@@.*@+.@@@:.@@.#@%*@*.@.-*@@%@#.@.@=.%..#% *@@@@ %:+:+:@@=@@ #+ %@@+..@@= %: @@ @@@..-.=@@:* %@.%#=+@+..:@@@@@@*.@@@=..:@@@ %@%%% :.@@+-@:=#@ ...@@@:+ @@+ :- @@ @@@.+@@@@@.- =@.#@.-@*.@:=@@@@@+ @@@+:@-:@% @@*=@ @=%#+-@-.#@ @*.%@@.- #@=. + @@ @@@.+@@@@+.@..@:*%.*@*.@%.@@@@%- +@@=:@%.@@.%@:=@ @@=*#:@::@@ *# =@--% -@:- * @@ @@-::#@@%::+::*@-:=%@::.::@@@@+-::@*:.:::@::...%:::::#@*:==@#==@+:*.:=::%:-=::=@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#-. .-#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*. .+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@- :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@: .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@: .++: .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@= :@@@@@@- -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@# =@@@@@@@@+ #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@: =@@@@@@@@@@+ .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@# .@@@@@@@@@@@@. *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@. %@@@@@@@@@@@@%. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@% -@@@@@@@@@@@@@@- #@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@= #@@@@@@@@@@@@@@% -@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@%##***#%@@@@+ %@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@* %@#:.. .:+@% *@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@= =. : -@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@: .@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@. .=%@@@@@@@+: .@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@# .%@@@@@@@@@@@@@- -@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@# .*@@@@@@@@@@@@@@@@%: -@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@%. .@@@@@@*%@@@@%#@@@@@@= *@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@. :@@@@@@@@:-@@*.%@@@@@@@+ %@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@+ :@@@@@@@@@@---.@@@@@@@@@@= :@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@. @@@@@@@@@@@. @@@@@@@@@@@: #@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@= #@@@+--#@@@@ #@@@@%#@@@@@. .@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@. :@%- .%@@- .@@@*. .+@@= #@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@# *+. .@@@#*@@@= .#@ -@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@- .# =@@-.@@%. += .@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. -@. @@. %@: #% %@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. #@- +% =% .@@. *@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@% %@% :+ .+ +@@. =@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@# @@@: .: .- .@@@: -@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@* .@@@% # .# =@@@: :@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@* .@@@@= -@ @- .@@@@: :@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@# @@@@@. .@@ @@. %@@@@: -@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@% %@@@@@: :@@@ @@@. .*@@@@@. =@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. #@@@@@@#+#@@@@ @@@@=.:%@@@@@@. *@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. :@@@@@@-..:*@@ @@#-..:%@@@@@# %@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@- .@@@@@: .@ @. .@@@@@- .@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@# *@@@% @. .@ *@@@@ -@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@. .@@@+ @- .@. -@@@= #@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@+ +@@%. .@* :@- .*@@%. .@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@. %@@@- *@% #@%. :%@@@. %@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@* .@@@@%=-+@@@. @@@*--#@@@@- -@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@: .@@@@@@@@@@*=@@@@@@@@@@: @@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@. .%@@@@@@@@@@@@@@@@@@@- .#@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@%. +@@@@@@@@@@@@@@@@#. +@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@%. .+@@@@@@@@@@@@%: +@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@%. -*%@@@@@#=. .*@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@: .%@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@#. +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+. .=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=. .-%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%###%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PLS/M3U On Anything Player</title>
<script src="https://cdn.jsdelivr.net/npm/jsmediatags@latest/dist/jsmediatags.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<style>
body {
font-family: 'Courier New', Consolas, monospace;
color: #FFC107;
background-color: #000000;
max-width: 600px;
margin: 20px auto;
}
h1, p, span, div {
font-family: 'Courier New', Consolas, monospace;
color: #FFC107;
}
input, button {
font-family: 'Courier New', Consolas, monospace;
color: #FFC107;
background-color: #000000;
border: 1px solid #FFC107;
padding: 5px;
margin: 5px;
}
input {
width: 100%;
box-sizing: border-box;
}
button:hover {
background-color: #FFC107;
color: #000000;
}
#controls { margin-top: 10px; }
#metadata {
margin-top: 10px;
padding: 10px;
border: 1px solid #FFC107;
}
#player, #video-player { max-width: 100%; }
.popup {
display: none;
position: fixed;
top: 20%;
left: 20%;
width: 60%;
max-height: 60%;
overflow-y: auto;
background: #000000;
border: 1px solid #FFC107;
padding: 10px;
color: #FFC107;
}
.popup ul {
list-style: none;
padding: 0;
}
.popup li {
cursor: pointer;
padding: 5px;
}
.popup li:hover {
background: #FFC107;
color: #000000;
}
.popup button {
position: sticky;
top: 0;
float: right;
}
</style>
</head>
<body>
<h1>PLS/M3U Playlist Player</h1>
<p>Enter a PLS, M3U, or M3U8 playlist URL (HTTP or HTTPS) or provide it in the URL (e.g., ?pls=https://example.com/playlist.m3u8). Supports audio, video, and live streams. Single-track playlists play automatically.</p>
<input id="pls-url" type="text" placeholder="Enter PLS/M3U URL">
<button onclick="loadPlaylist()">Load Playlist</button>
<button onclick="togglePlaylistWindow()">Show Playlist</button>
<button onclick="toggleRecentPlaylists()">Show Recent Playlists</button>
<div id="player-container">
<audio id="player" controls style="display: none;"></audio>
<video id="video-player" controls style="display: none;"></video>
</div>
<div id="controls">
<button id="prev">Previous</button>
<button id="playpause">Play</button>
<button id="next">Next</button>
<button onclick="changeSpeed(0.25)">Speed +</button>
<button onclick="changeSpeed(-0.25)">Speed -</button>
<span>Speed: <span id="speed">1.00</span>x</span>
</div>
<div id="metadata">Metadata will appear here.</div>
<div id="playlist-window" class="popup">
<button onclick="togglePlaylistWindow()">Close</button>
<ul id="playlist-list"></ul>
</div>
<div id="recent-playlists" class="popup">
<button onclick="toggleRecentPlaylists()">Close</button>
<ul id="recent-playlists-list"></ul>
</div>
<script>
let tracks = [];
let currentIndex = 0;
const audioPlayer = document.getElementById('player');
const videoPlayer = document.getElementById('video-player');
const playPauseBtn = document.getElementById('playpause');
const speedSpan = document.getElementById('speed');
const metadataDiv = document.getElementById('metadata');
const playlistList = document.getElementById('playlist-list');
const recentPlaylistsList = document.getElementById('recent-playlists-list');
const plsInput = document.getElementById('pls-url');
let currentPlayer = audioPlayer;
// Check for ?pls= query parameter on page load
window.onload = () => {
const params = new URLSearchParams(window.location.search);
const plsUrl = params.get('pls');
if (plsUrl) {
if (plsUrl.startsWith('http://') || plsUrl.startsWith('https://')) {
plsInput.value = plsUrl;
loadPlaylist();
} else {
alert('Invalid playlist URL in query parameter. Please use http:// or https://');
}
}
fetchRecentPlaylists();
};
async function loadPlaylist() {
const url = plsInput.value;
if (!url) {
alert('Please enter a playlist URL or provide it in the URL (?pls=...).');
return;
}
if (!url.startsWith('http://') && !url.startsWith('https://')) {
alert('URL must start with http:// or https://');
return;
}
try {
// Save the playlist URL to the server
await fetch('save_playlist.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url })
});
// Fetch and parse the playlist
const response = await fetch(url, { mode: 'cors' });
if (!response.ok) throw new Error(`Failed to fetch playlist: ${response.statusText}`);
const text = await response.text();
const extension = url.split('.').pop().toLowerCase();
tracks = extension === 'pls' ? parsePLS(text) : parseM3U(text);
if (tracks.length === 0) {
alert('No tracks found in playlist.');
return;
}
// Update browser URL with ?pls=
history.pushState({}, '', `?pls=${encodeURIComponent(url)}`);
updatePlaylistWindow();
// Auto-play if only one track
if (tracks.length === 1) {
playTrack(0);
} else {
document.getElementById('playlist-window').style.display = 'block';
playTrack(0);
}
fetchRecentPlaylists();
} catch (error) {
console.error('Playlist load error:', error);
alert(`Error loading playlist: ${error.message}. Check if the server allows CORS or is online.`);
}
}
function parsePLS(text) {
const lines = text.split('\n');
let numEntries = 0;
const trackMap = {};
lines.forEach(line => {
line = line.trim();
if (!line || line.startsWith('[')) return;
const [key, value] = line.split('=').map(part => part.trim());
if (!key || !value) return;
if (key === 'NumberOfEntries') {
numEntries = parseInt(value, 10);
return;
}
const match = key.match(/^(File|Title|Length)(\d+)$/);
if (match) {
const [, type, numStr] = match;
const num = parseInt(numStr, 10);
if (!trackMap[num]) trackMap[num] = {};
if (type === 'File') trackMap[num].url = value;
else if (type === 'Title') trackMap[num].title = value;
else if (type === 'Length') trackMap[num].length = parseInt(value, 10);
}
});
const trackList = [];
for (let i = 1; i <= numEntries; i++) {
if (trackMap[i] && trackMap[i].url) {
trackList.push({
url: trackMap[i].url,
title: trackMap[i].title || `Track ${i}`,
length: trackMap[i].length || -1
});
}
}
return trackList;
}
function parseM3U(text) {
const lines = text.split('\n');
const trackList = [];
let currentTrack = {};
lines.forEach(line => {
line = line.trim();
if (!line || line.startsWith('#EXTM3U')) return;
if (line.startsWith('#EXTINF:')) {
const [, duration, title] = line.match(/#EXTINF:(-?\d+),(.*)/) || [, -1, 'Unknown'];
currentTrack = { title: title.trim(), length: parseInt(duration, 10) };
} else if (line.startsWith('http://') || line.startsWith('https://')) {
currentTrack.url = line;
trackList.push({ ...currentTrack, title: currentTrack.title || 'Unknown', length: currentTrack.length || -1 });
currentTrack = {};
}
});
return trackList;
}
function updatePlaylistWindow() {
playlistList.innerHTML = '';
tracks.forEach((track, index) => {
const li = document.createElement('li');
li.textContent = track.title;
li.onclick = () => playTrack(index);
playlistList.appendChild(li);
});
}
function togglePlaylistWindow() {
const win = document.getElementById('playlist-window');
win.style.display = win.style.display === 'none' ? 'block' : 'none';
document.getElementById('recent-playlists').style.display = 'none';
}
async function fetchRecentPlaylists() {
try {
const response = await fetch('save_playlist.php');
const data = await response.json();
recentPlaylistsList.innerHTML = '';
data.forEach(item => {
const li = document.createElement('li');
li.textContent = `${item.url} (${new Date(item.timestamp).toLocaleString()})`;
li.onclick = () => {
plsInput.value = item.url;
loadPlaylist();
toggleRecentPlaylists();
};
recentPlaylistsList.appendChild(li);
});
} catch (error) {
console.error('Error fetching recent playlists:', error);
}
}
function toggleRecentPlaylists() {
const win = document.getElementById('recent-playlists');
win.style.display = win.style.display === 'none' ? 'block' : 'none';
document.getElementById('playlist-window').style.display = 'none';
}
function playTrack(index) {
if (index < 0 || index >= tracks.length) return;
currentIndex = index;
const track = tracks[index];
const isVideo = track.url.match(/\.(mp4|m3u8)$/i);
const isHLS = track.url.endsWith('.m3u8');
audioPlayer.style.display = isVideo ? 'none' : 'block';
videoPlayer.style.display = isVideo ? 'block' : 'none';
currentPlayer = isVideo ? videoPlayer : audioPlayer;
if (isHLS && typeof Hls !== 'undefined' && Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(track.url);
hls.attachMedia(videoPlayer);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
videoPlayer.play().catch(error => {
console.error('HLS playback error:', error);
alert('Playback error: ' + error.message + '. Ensure the stream is active and CORS is enabled.');
});
});
hls.on(Hls.Events.ERROR, (event, data) => {
console.error('HLS error:', data);
alert('HLS stream error: ' + data.type + ' - ' + data.details);
});
} else {
currentPlayer.src = track.url;
currentPlayer.play().catch(error => {
console.error('Playback error:', error);
alert('Playback error: ' + error.message + '. Check if the stream is accessible.');
});
}
playPauseBtn.textContent = 'Pause';
updateMetadata();
if (!isVideo) {
try {
jsmediatags.read(track.url, {
onSuccess: (tag) => {
const tags = tag.tags;
metadataDiv.innerHTML = `
Title: ${tags.title || track.title}<br>
Artist: ${tags.artist || 'Unknown'}<br>
Album: ${tags.album || 'Unknown'}<br>
Length: ${track.length > 0 ? track.length + ' seconds' : 'Unknown'}
`;
},
onError: () => updateMetadata()
});
} catch (e) {
updateMetadata();
}
} else {
updateMetadata();
}
}
function updateMetadata() {
const track = tracks[currentIndex];
metadataDiv.innerHTML = `
Title: ${track.title}<br>
Length: ${track.length > 0 ? track.length + ' seconds' : 'Unknown'}
`;
}
playPauseBtn.addEventListener('click', () => {
if (currentPlayer.paused) {
currentPlayer.play();
playPauseBtn.textContent = 'Pause';
} else {
currentPlayer.pause();
playPauseBtn.textContent = 'Play';
}
});
document.getElementById('next').addEventListener('click', () => {
playTrack(currentIndex + 1);
});
document.getElementById('prev').addEventListener('click', () => {
playTrack(currentIndex - 1);
});
audioPlayer.addEventListener('ended', () => {
playTrack(currentIndex + 1);
});
videoPlayer.addEventListener('ended', () => {
playTrack(currentIndex + 1);
});
function changeSpeed(delta) {
currentPlayer.playbackRate = Math.max(0.25, currentPlayer.playbackRate + delta);
speedSpan.textContent = currentPlayer.playbackRate.toFixed(2);
}
</script>
</body>
</html> Language: html