Ücretsiz araç - Hesap gerekmez

Ücretsiz M3U ve IPTV Yinelenen Kanal Kaldırıcı

M3U, M3U8 veya IPTV oynatma listenizi saniyeler içinde yinelenen kanalları kaldırarak çevrimiçi temizleyin. Ad, URL veya her ikisiyle eşleştirin. Anında temiz bir dosya indirin.

M3U dosyanızı buraya sürükleyin

veya

.m3u ve .m3u8 desteklenir - Tarayıcınızda yerel olarak işlenir - Sunucularımıza asla yüklenmez

100% Özel

Dosyanız hiçbir zaman tarayıcınızı terk etmez. Tüm işlemler yereldir.

Esnek eşleştirme

Yinelenen kanalları akış URL'si, kanal adı veya her ikisiyle eşleştirin. İlk kaydı tutar.

Anında indirme

Temizlenmiş M3U dosyanızı hemen indirin. Bekleme yok, e-posta yok, kayıt gerekmez.

Playlist'inizle daha fazlasını yapmak ister misiniz?

Kanalları filtrelemek, özel playlist oluşturmak için ücretsiz M3U Maker hesabı oluşturun.

(function() { var zone = document.getElementById('uploadZone'); var fileInput = document.getElementById('fileInput'); var results = document.getElementById('results'); var resetBtn = document.getElementById('resetBtn'); var browseBtn = document.getElementById('browseBtn'); var reprocessBtn = document.getElementById('reprocessBtn'); var downloadBtn = document.getElementById('downloadBtn'); var matchUrl = document.getElementById('matchUrl'); var matchName = document.getElementById('matchName'); var parsedChannels = []; var originalHeader = '#EXTM3U'; var currentFilename = ''; browseBtn.addEventListener('click', function(e) { e.stopPropagation(); fileInput.click(); }); zone.addEventListener('click', function() { fileInput.click(); }); zone.addEventListener('dragover', function(e) { e.preventDefault(); zone.classList.add('drag-over'); }); zone.addEventListener('dragleave', function() { zone.classList.remove('drag-over'); }); zone.addEventListener('drop', function(e) { e.preventDefault(); zone.classList.remove('drag-over'); if (e.dataTransfer.files[0]) processFile(e.dataTransfer.files[0]); }); fileInput.addEventListener('change', function() { if (fileInput.files[0]) processFile(fileInput.files[0]); }); resetBtn.addEventListener('click', function() { results.style.display = 'none'; loading.style.display = 'none'; zone.style.display = ''; fileInput.value = ''; parsedChannels = []; }); reprocessBtn.addEventListener('click', function() { showResults(); }); downloadBtn.addEventListener('click', function() { downloadClean(); }); var loading = document.getElementById('loading'); function processFile(file) { currentFilename = file.name; zone.style.display = 'none'; loading.style.display = ''; var reader = new FileReader(); reader.onload = function(e) { parseM3U(e.target.result); }; reader.readAsText(file, 'UTF-8'); } function parseM3U(content) { var lines = content.split(/\r?\n/); parsedChannels = []; originalHeader = '#EXTM3U'; var i = 0; if (lines[0] && lines[0].trim().startsWith('#EXTM3U')) { originalHeader = lines[0].trim(); i = 1; } while (i < lines.length) { var line = lines[i].trim(); if (!line) { i++; continue; } if (line.startsWith('#EXTINF:')) { var extinf = line; var nameMatch = line.match(/,(.+)$/); var name = nameMatch ? nameMatch[1].trim() : ''; i++; while (i < lines.length && !lines[i].trim()) i++; var url = lines[i] ? lines[i].trim() : ''; if (url && !url.startsWith('#')) { parsedChannels.push({ extinf: extinf, name: name, url: url }); } } i++; } loading.style.display = 'none'; results.style.display = ''; document.getElementById('resultsFilename').textContent = currentFilename; showResults(); } function showResults() { var byUrl = matchUrl.checked; var byName = matchName.checked; if (!byUrl && !byName) { matchUrl.checked = true; byUrl = true; } var seenUrls = {}, seenNames = {}; var kept = [], dupes = []; parsedChannels.forEach(function(ch) { var isDupe = false; var dupeType = ''; if (byUrl && ch.url && seenUrls[ch.url]) { isDupe = true; dupeType = 'url'; } if (byName && ch.name && seenNames[ch.name.toLowerCase()]) { isDupe = true; dupeType = dupeType ? dupeType + '+name' : 'name'; } if (isDupe) { dupes.push({ ch: ch, type: dupeType }); } else { kept.push(ch); if (byUrl && ch.url) seenUrls[ch.url] = true; if (byName && ch.name) seenNames[ch.name.toLowerCase()] = true; } }); // Stats var statsRow = document.getElementById('statsRow'); statsRow.textContent = ''; [ { val: parsedChannels.length.toLocaleString(), label: 'Total channels', cls: '' }, { val: dupes.length, label: 'Duplicates found', cls: dupes.length > 0 ? 'tool-stat--warning' : '' }, { val: kept.length.toLocaleString(), label: 'Unique channels', cls: kept.length > 0 ? 'tool-stat--success' : '' }, { val: dupes.length > 0 ? Math.round(dupes.length / parsedChannels.length * 100) + '%' : '0%', label: 'Reduction', cls: '' } ].forEach(function(s) { var div = document.createElement('div'); div.className = 'tool-stat ' + s.cls; var val = document.createElement('span'); val.className = 'tool-stat-value'; val.textContent = s.val; var lbl = document.createElement('span'); lbl.className = 'tool-stat-label'; lbl.textContent = s.label; div.appendChild(val); div.appendChild(lbl); statsRow.appendChild(div); }); // Dupes list var dupeSection = document.getElementById('dupeSection'); var nodupeMsg = document.getElementById('nodupeMsg'); var downloadBar = document.getElementById('downloadBar'); if (dupes.length > 0) { document.getElementById('dupeGroupHeader').textContent = 'Duplicate channels to be removed (' + dupes.length + ')'; var dupeList = document.getElementById('dupeList'); dupeList.textContent = ''; dupes.slice(0, 100).forEach(function(d) { var item = document.createElement('div'); item.className = 'tool-dupe-item'; var badge = document.createElement('span'); badge.className = 'tool-dupe-badge tool-dupe-badge--' + (d.type === 'url' ? 'url' : 'name'); badge.textContent = d.type === 'url' ? 'URL' : d.type === 'name' ? 'Name' : 'URL+Name'; item.appendChild(badge); var info = document.createElement('div'); info.className = 'tool-dupe-info'; var nameEl = document.createElement('div'); nameEl.className = 'tool-dupe-name'; nameEl.textContent = d.ch.name || '(no name)'; var urlEl = document.createElement('div'); urlEl.className = 'tool-dupe-url'; urlEl.textContent = d.ch.url; info.appendChild(nameEl); info.appendChild(urlEl); item.appendChild(info); dupeList.appendChild(item); }); if (dupes.length > 100) { var more = document.createElement('div'); more.className = 'tool-issue-more'; more.textContent = '… and ' + (dupes.length - 100) + ' more duplicates'; dupeList.appendChild(more); } dupeSection.style.display = ''; nodupeMsg.style.display = 'none'; document.getElementById('downloadInfo').textContent = kept.length.toLocaleString() + ' channels, ' + dupes.length + ' duplicates removed'; downloadBar.style.display = ''; downloadBtn._kept = kept; } else { dupeSection.style.display = 'none'; nodupeMsg.style.display = ''; downloadBar.style.display = 'none'; } } function downloadClean() { var kept = downloadBtn._kept; if (!kept) return; var lines = [originalHeader]; kept.forEach(function(ch) { lines.push(ch.extinf); lines.push(ch.url); lines.push(''); }); var blob = new Blob([lines.join('\n')], { type: 'audio/x-mpegurl' }); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); var base = currentFilename.replace(/\.[^.]+$/, ''); a.download = base + '-cleaned.m3u'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(a.href); } })();