Ücretsiz araç - Hesap gerekmez

Ücretsiz M3U ve IPTV Oynatma Listesi Doğrulayıcı

M3U, M3U8 veya IPTV oynatma listenizi çevrimiçi olarak kontrol edin ve doğrulayın. Hataları, eksik başlıkları, geçersiz URL'leri ve yinelenen kanalları anında tespit eder.

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.

Anında Sonuçlar

Büyük playlist'lerde bile milisaniyeler içinde doğrulama.

Ayrıntılı rapor

#EXTM3U başlığının eksikliğini, geçersiz URL'leri, eksik group-title özelliklerini ve yinelenen kanalları kontrol eder.

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'); 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 = ''; }); var loading = document.getElementById('loading'); function processFile(file) { zone.style.display = 'none'; loading.style.display = ''; var reader = new FileReader(); reader.onload = function(e) { validateM3U(e.target.result, file.name); }; reader.readAsText(file, 'UTF-8'); } function validateM3U(content, filename) { var lines = content.split(/\r?\n/); var errors = [], warnings = []; var channelCount = 0; var urls = {}, names = {}; var i = 0; if (lines[0] && lines[0].trim().startsWith('#EXTM3U')) { i = 1; } else { errors.push({ line: 1, msg: 'Missing #EXTM3U header on line 1' }); } while (i < lines.length) { var line = lines[i].trim(); if (!line || line === '#EXTM3U') { i++; continue; } if (line.startsWith('#EXTINF:')) { channelCount++; var lineNum = i + 1; var nameMatch = line.match(/,(.+)$/); var name = nameMatch ? nameMatch[1].trim() : ''; if (!name) { warnings.push({ line: lineNum, msg: 'Channel #' + channelCount + ': missing name after comma in #EXTINF' }); } if (line.indexOf('group-title') === -1) { warnings.push({ line: lineNum, msg: 'Channel #' + channelCount + (name ? ' "' + name + '"' : '') + ': missing group-title attribute' }); } if (name) { var lname = name.toLowerCase(); if (names[lname] !== undefined) { warnings.push({ line: lineNum, msg: 'Duplicate channel name: "' + name + '" (also on line ' + names[lname] + ')' }); } else { names[lname] = lineNum; } } i++; while (i < lines.length && !lines[i].trim()) i++; var urlLine = lines[i] ? lines[i].trim() : ''; var urlLineNum = i + 1; if (!urlLine || urlLine.startsWith('#')) { errors.push({ line: lineNum, msg: 'Channel #' + channelCount + (name ? ' "' + name + '"' : '') + ': no stream URL found after #EXTINF' }); } else { if (!/^(https?|rtsp|rtp|udp|igmp|mms|rtmp):\/\//i.test(urlLine)) { warnings.push({ line: urlLineNum, msg: 'Channel #' + channelCount + (name ? ' "' + name + '"' : '') + ': unusual URL format' }); } if (urls[urlLine] !== undefined) { warnings.push({ line: urlLineNum, msg: 'Duplicate stream URL for "' + name + '" (also on line ' + urls[urlLine] + ')' }); } else { urls[urlLine] = urlLineNum; } } } i++; } showResults(filename, channelCount, errors, warnings); } function showResults(filename, channelCount, errors, warnings) { document.getElementById('resultsFilename').textContent = filename; var statsRow = document.getElementById('statsRow'); var dupeCount = warnings.filter(function(w) { return w.msg.indexOf('Duplicate') === 0; }).length; statsRow.textContent = ''; [ { val: channelCount.toLocaleString(), label: 'Channels', cls: '' }, { val: errors.length, label: 'Errors', cls: errors.length > 0 ? 'tool-stat--error' : '' }, { val: warnings.length, label: 'Warnings', cls: warnings.length > 0 ? 'tool-stat--warning' : '' }, { val: dupeCount, label: 'Duplicates', 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); }); var total = errors.length * 3 + warnings.length; var score = Math.max(0, Math.min(100, Math.round(100 - (total / Math.max(channelCount, 1)) * 200))); var scoreColor = score >= 80 ? 'var(--accent-success)' : score >= 50 ? 'var(--accent-warning)' : 'var(--accent-danger)'; document.getElementById('scoreText').textContent = score + '/100 - ' + (score >= 80 ? 'Good' : score >= 50 ? 'Fair' : 'Poor'); var fill = document.getElementById('scoreFill'); fill.style.width = '0%'; setTimeout(function() { fill.style.width = score + '%'; fill.style.background = scoreColor; }, 50); var issueList = document.getElementById('issueList'); issueList.textContent = ''; function renderGroup(items, type) { if (!items.length) return; var group = document.createElement('div'); group.className = 'tool-issue-group'; var header = document.createElement('div'); header.className = 'tool-issue-group-header tool-issue--' + type; header.textContent = (type === 'error' ? 'Errors' : 'Warnings') + ' (' + items.length + ')'; group.appendChild(header); var list = document.createElement('div'); list.className = 'tool-issue-list'; items.slice(0, 50).forEach(function(issue) { var item = document.createElement('div'); item.className = 'tool-issue-item'; var lineSpan = document.createElement('span'); lineSpan.className = 'tool-issue-line'; lineSpan.textContent = 'L' + issue.line; var msgSpan = document.createElement('span'); msgSpan.className = 'tool-issue-msg'; msgSpan.textContent = issue.msg; item.appendChild(lineSpan); item.appendChild(msgSpan); list.appendChild(item); }); if (items.length > 50) { var more = document.createElement('div'); more.className = 'tool-issue-more'; more.textContent = '… and ' + (items.length - 50) + ' more ' + type + 's'; list.appendChild(more); } group.appendChild(list); issueList.appendChild(group); } renderGroup(errors, 'error'); renderGroup(warnings, 'warning'); document.getElementById('successMsg').style.display = (errors.length + warnings.length === 0) ? '' : 'none'; loading.style.display = 'none'; results.style.display = ''; } })();