en
Feedback
Dostlar bir arada 😉

Dostlar bir arada 😉

Closed channel
348
Subscribers
-124 hours
-47 days
+630 days

Data loading in progress...

Similar Channels
No data
Any problems? Please refresh the page or contact our support manager.
Incoming and Outgoing Mentions
---
---
---
---
---
---
Attracting Subscribers
May '26
May '26
+11
in 0 channels
April '26
+23
in 0 channels
Get PRO
March '26
+21
in 0 channels
Get PRO
February '26
+17
in 0 channels
Get PRO
January '26
+29
in 0 channels
Get PRO
December '25
+23
in 0 channels
Get PRO
November '25
+6
in 0 channels
Get PRO
October '25
+8
in 0 channels
Get PRO
September '25
+1
in 0 channels
Get PRO
August '25
+18
in 0 channels
Get PRO
July '25
+50
in 0 channels
Get PRO
June '25
+300
in 0 channels
Date
Subscriber Growth
Mentions
Channels
19 May0
18 May0
17 May0
16 May0
15 May0
14 May0
13 May0
12 May0
11 May0
10 May+2
09 May0
08 May0
07 May+1
06 May0
05 May+1
04 May0
03 May+3
02 May+4
01 May0
Channel Posts
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 37mustafa783 🔐 Şifre: 92musyafabey2 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 16.08.2026 17:22 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=37mustafa783&password=92musyafabey2&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 382500 🔐 Şifre: 38250000 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 04.09.2026 20:49 🔗 Bağlantı: 0 / 2 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=382500&password=38250000&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 4mcy9FJKnH 🔐 Şifre: qARTVvMSrf 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 10.06.2026 12:02 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=4mcy9FJKnH&password=qARTVvMSrf&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 4W3dCNBZnV 🔐 Şifre: y6bfxPU5jy 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 18.07.2026 14:41 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=4W3dCNBZnV&password=y6bfxPU5jy&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 4rQTFAzYBz 🔐 Şifre: Fc9EeMgPv8 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 29.04.2027 21:19 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=4rQTFAzYBz&password=Fc9EeMgPv8&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 024yunus 🔐 Şifre: hande2424 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 26.04.2028 17:08 🔗 Bağlantı: 1 / 2 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=024yunus&password=hande2424&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 052ismetates1907 🔐 Şifre: 1907ismet052 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 24.04.2027 18:15 🔗 Bağlantı: 0 / 2 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=052ismetates1907&password=1907ismet052&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 05536409272 🔐 Şifre: QazWsx3428 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 24.05.2026 16:45 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=05536409272&password=QazWsx3428&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 055samet88 🔐 Şifre: 1903samet88 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 08.07.2026 19:48 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=055samet88&password=1903samet88&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 06an6420 🔐 Şifre: 2404-1705 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 25.04.2027 12:15 🔗 Bağlantı: 1 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=06an6420&password=2404-1705&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 07012025komsu 🔐 Şifre: pAdTCsXJcJ 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 06.01.2027 16:58 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=07012025komsu&password=pAdTCsXJcJ&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 13344 🔐 Şifre: 13344 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 12.11.2026 14:34 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=13344&password=13344&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 16veysel837 🔐 Şifre: 937dagin3626 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 04.07.2026 17:43 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=16veysel837&password=937dagin3626&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 1903omeryusuf55 🔐 Şifre: 55omeryusuf1903 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 19.02.2027 15:35 🔗 Bağlantı: 0 / 2 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=1903omeryusuf55&password=55omeryusuf1903&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 1905birol034 🔐 Şifre: 02052022arnavut 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 30.06.2026 00:00 🔗 Bağlantı: 0 / 2 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=1905birol034&password=02052022arnavut&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 2307tembd123 🔐 Şifre: JDsaQTrhHL 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 25.07.2026 15:27 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=2307tembd123&password=JDsaQTrhHL&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 👤 Kullanıcı / MAC: 2qQRFPLfd8 🔐 Şifre: RWJKywTAgY 👨‍💼 Oluşturan: DeaTHLesS 📅 Bitiş Tarihi: 21.02.2035 17:45 🔗 Bağlantı: 0 / 1 🌐 Host: http://keyiftv55.shop:8080 📺 M3U Link: http://keyiftv55.shop:8080/get.php?username=2qQRFPLfd8&password=RWJKywTAgY&type=m3u_plus ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
10
3
Pomak_since.m3u
1
4
Rexzxlad.m3u
1
5
if (currentChannelIndex >= 0 && channels[currentChannelIndex]) { handlePlaybackError(); // yeniden bağlan } }); // Kanal listesinde hızlı kaydırma için zaten overflow-auto ve yeterli yükseklik. // Uzun kanal listesi için max-height ayarı yok, %100. </script> <!-- HLS.js desteği için ek kütüphane (eğer native destek yoksa) --> <script src="https://cdn.jsdelivr.net/npm/hls.js@1.5.7/dist/hls.min.js"></script> </body> </html>
72
6
div.setAttribute('data-index', idx); div.setAttribute('tabindex', '0'); div.innerText = ch.name; div.addEventListener('click', (e) => { e.stopPropagation(); // linke basarken otomatik asansör gibi aç (hızlı kanal geçişi) loadChannel(idx, true); // odak kaydırma (hızlı liste içinde) div.focus(); }); // klavye ve kumanda desteği için Enter tuşu div.addEventListener('keydown', (e) => { if (e.key === 'Enter' e.key === ' ' e.key === 'Select') { e.preventDefault(); loadChannel(idx, true); div.focus(); } }); channelListDiv.appendChild(div); }); if (channels.length === 0) { channelListDiv.innerHTML = '<div style="padding:20px;color:#aaa;">Kanal bulunamadı</div>'; } } // KUMANDA VE KLavye desteği: Yukarı / Aşağı ile kanal listesinde hızlı gezinme, // ayrıca video oynatıcıda focus yönetimi. document.addEventListener('keydown', (e) => { const key = e.key; // yukarı/aşağı ok tuşları (kumanda ve klavye) if (key === 'ArrowUp') { e.preventDefault(); if (currentChannelIndex > 0) { loadChannel(currentChannelIndex - 1, true); // otomatik kaydırma asansör efekti const newActiveItem = document.querySelector(.channel-item[data-index='${currentChannelIndex}']); if (newActiveItem) newActiveItem.scrollIntoView({ behavior: 'smooth', block: 'center' }); } } else if (key === 'ArrowDown') { e.preventDefault(); if (currentChannelIndex < channels.length - 1) { loadChannel(currentChannelIndex + 1, true); const newActiveItem = document.querySelector(.channel-item[data-index='${currentChannelIndex}']); if (newActiveItem) newActiveItem.scrollIntoView({ behavior: 'smooth', block: 'center' }); } } else if (key === 'Enter' || key === 'Select') { // eğer odak kanal listesinde değilse, aktif kanalı yeniden yüklemeyi deneme if (document.activeElement && !document.activeElement.classList?.contains('channel-item')) { if (currentChannelIndex >= 0) { e.preventDefault(); loadChannel(currentChannelIndex, true); } } } else if (key === 'Escape' && document.fullscreenElement) { document.exitFullscreen(); } else if (key === 'f' || key === 'F') { toggleFullscreen(); } }); // Kanal listesi odağını yakala ve yukarı/aşağı daha hızlı geçiş için liste içinde scrolling // Ayrıca mouse tekerleği ile hızlı inip çıkma zaten overflow sayesinde olacak. // "Hızlı inme çıkma" için scroll hızı yüksek // CSS ile scroll-behavior smooth ancak fare tekerleği ile hızlı gezinme destekleniyor // Otomatik açılır asansör efekti: link tıklama anında video anında değişir (tamponsuz) // Bu mevcut loadChannel ile oluyor. // Zayıf internet için donma önlemi: video etiketine preload=none + buffer limit + hata yönetimi // Ayrıca sayfa yüklendiğinde m3u çekilecek. // Mobil / dokunmatik için video tıklama tam ekran (isteğe bağlı) ekstra videoElement.addEventListener('dblclick', () => { toggleFullscreen(); }); // Başlat fetchAndParseM3U(); // Ek olarak, ağ bağlantısı izleme: tekrar denemelerde kullanıcıya bildirim window.addEventListener('online', () => { console.log("Bağlantı yeniden sağlandı, mevcut kanal yeniden yükleniyor...");
66
7
loadChannel(sameIndex, true); } else { hideLoading(); isLoadingVideo = false; } }, 800); } function showLoading(show) { if (show) { loadingIndicator.style.display = 'flex'; } else { loadingIndicator.style.display = 'none'; } } function hideLoading() { loadingIndicator.style.display = 'none'; } // M3U dosyasını çek ve ayrıştır async function fetchAndParseM3U() { try { const response = await fetch(M3U_URL); if (!response.ok) throw new Error(HTTP ${response.status}); const m3uText = await response.text(); parseM3U(m3uText); } catch (err) { console.error("M3U yüklenemedi:", err); channelListDiv.innerHTML = <div style="padding:20px; color:red;">M3U listesi alınamadı. İnterneti kontrol edin.<br>Hata: ${err.message}</div>; // Demo yedek kanal ekle (gösteri amaçlı test) addDummyChannels(); } } function parseM3U(data) { const lines = data.split(/\r?\n/); let newChannels = []; let currentName = ""; for (let i = 0; i < lines.length; i++) { let line = lines[i].trim(); if (line.startsWith("#EXTINF:")) { // #EXTINF:-1 tvg-name="..." group-title="..." , KANAL ADI const nameMatch = line.match(/,(.*)$/); if (nameMatch && nameMatch[1]) { currentName = nameMatch[1].trim(); } else { currentName = "İsimsiz Kanal"; } } else if (line && !line.startsWith("#")) { // URL satırı if (currentName) { newChannels.push({ name: currentName, url: line }); currentName = ""; } else { // isim yoksa url'den dosya adı let fallbackName = "Kanal " + (newChannels.length+1); newChannels.push({ name: fallbackName, url: line }); } } } if (newChannels.length === 0) { addDummyChannels(); } else { channels = newChannels; renderChannelList(); // İlk kanalı otomatik aç (varsayılan) if (channels.length > 0) { loadChannel(0, true); } } } // Yedek demo kanallar (M3U geçici sorun olursa diye) function addDummyChannels() { channels = []; // Örnek test yayınları (halka açık test akışları, zayıf internete uygun değil ama örnek) channels.push({ name: "📺 Test 1 (TRT Haber)", url: "https://cdn-trtcanlitv.akamaized.net/channels/trthaber/playlist.m3u8" }); channels.push({ name: "🎥 Test 2 (NASA TV)", url: "https://ntvweblive-lh.akamaihd.net/i/rd_1@328788/master.m3u8" }); channels.push({ name: "🌍 Test 3 (Yaban TV)", url: "https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8" }); channels.push({ name: "🎬 Demo Kanal 4", url: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" }); channels.push({ name: "🎞️ Klasik Müzik", url: "https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8" }); renderChannelList(); if (channels.length) loadChannel(0, true); } // Kanalları listele - uzun liste, hızlı aşağı yukarı kaydırma function renderChannelList() { channelListDiv.innerHTML = ""; channels.forEach((ch, idx) => { const div = document.createElement('div'); div.className = 'channel-item';
40
8
maxMaxBufferLength: 20, startLevel: -1, // otomatik kalite seçimi abrEwmaDefaultEstimate: 500000, manifestLoadingTimeOut: 10000, manifestLoadingMaxRetry: 3, levelLoadingTimeOut: 8000, fragLoadingTimeOut: 10000, }); hls.loadSource(videoSrc); hls.attachMedia(videoElement); hls.on(Hls.Events.MANIFEST_PARSED, () => { if (autoPlay) { videoElement.play().then(() => { hideLoading(); isLoadingVideo = false; retryCount = 0; }).catch(err => { console.error("HLS oynatma başlatılamadı:", err); handlePlaybackError(); }); } }); hls.on(Hls.Events.ERROR, (event, data) => { if (data.fatal) { console.error("HLS fatal hatası:", data); switch(data.type) { case Hls.ErrorTypes.NETWORK_ERROR: // ağ hatasında tekrar dene - zayıf internet için kurtarma console.log("Ağ hatası, yeniden bağlanma denenecek"); handlePlaybackError(); break; case Hls.ErrorTypes.MEDIA_ERROR: handlePlaybackError(); break; default: handlePlaybackError(); break; } } else { // non-fatal hatayı görmezden gel, oynatmaya devam console.warn("HLS non-fatal:", data); hideLoading(); } }); hls.on(Hls.Events.BUFFER_APPENDING, () => { // tampon doluyorsa loading gizle hideLoading(); }); } catch (err) { console.error("HLS kurulum hatası:", err); hideLoading(); isLoadingVideo = false; } } else { // Hiçbir destek yoksa uyarı console.error("M3U8 oynatma desteklenmiyor"); channelNameBar.innerText = channel.name + " (destek yok)"; hideLoading(); isLoadingVideo = false; } } // Hata Yönetimi: Zayıf internet donma/kasmalarında otomatik yeniden bağlanma (oynatmayı devam ettir) function handlePlaybackError() { if (retryCount >= 3) { console.warn("3 kez başarısız oldu, kullanıcıya bilgi ver."); channelNameBar.innerText = channels[currentChannelIndex]?.name + " (Yüklenemedi, kanal geçiş yapın)"; hideLoading(); isLoadingVideo = false; retryCount = 0; return; } retryCount++; console.log(Yeniden bağlanma denemesi ${retryCount}...); showLoading(true); // mevcut kanalı tekrar yükle (küçük gecikme ile) setTimeout(() => { if (currentChannelIndex >= 0 && currentChannelIndex < channels.length) { // hızlı şekilde reload const sameIndex = currentChannelIndex; // önce mevcut medyayı temizle if (hls) { hls.destroy(); hls = null; } videoElement.pause(); videoElement.src = ''; videoElement.load();
27
9
// Ek olarak native HLS için hata yönetimi donmayı önlemek adına let hls = null; function initHLSIfNeeded() { if (Hls && Hls.isSupported()) { return true; } return false; } // Video oynatıcıyı temizle ve kanalı yükle (zayıf internet için "oynatmayı devam et" mekanizması) function loadChannel(index, autoPlay = true) { if (index < 0 || index >= channels.length) return false; if (isLoadingVideo) { // zaten yükleniyorsa kısmi önlem console.log("Yükleme zaten devam ediyor, tekrarı geciktir"); return false; } const channel = channels[index]; if (!channel || !channel.url) return false; currentChannelIndex = index; channelNameBar.innerText = channel.name; // UI'da aktif kanal vurgusu document.querySelectorAll('.channel-item').forEach((item, idx) => { if (idx === index) { item.classList.add('active'); item.focus(); // Otomatik kaydırma: aktif kanalı görünür yap (asansör efekti) item.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } else { item.classList.remove('active'); } }); // Yükleniyor göster showLoading(true); isLoadingVideo = true; // Önceki medya ve HLS temizliği if (hls) { hls.destroy(); hls = null; } videoElement.pause(); videoElement.removeAttribute('src'); videoElement.load(); const videoSrc = channel.url; // Native HLS desteği (Android TV, modern Chrome) const canPlayM3U8 = videoElement.canPlayType('application/vnd.apple.mpegurl') !== '' || videoElement.canPlayType('application/x-mpegURL') !== ''; if (canPlayM3U8) { // Native oynatma, hata durumunda yeniden dene (kasma/donma önleme) videoElement.src = videoSrc; videoElement.load(); if (autoPlay) { let playPromise = videoElement.play(); if (playPromise !== undefined) { playPromise.then(() => { console.log("Native oynatma başarılı"); hideLoading(); isLoadingVideo = false; retryCount = 0; }).catch(error => { console.error("Oynatma hatası (native):", error); handlePlaybackError(); }); } } // Hata dinleyicisi: ağ veya medya hatalarında yeniden bağlanma videoElement.onerror = (e) => { console.warn("Video hatası:", videoElement.error); if (videoElement.error && (videoElement.error.code === 2 || videoElement.error.code === 3)) { handlePlaybackError(); } hideLoading(); isLoadingVideo = false; }; videoElement.onloadeddata = () => { hideLoading(); isLoadingVideo = false; retryCount = 0; }; videoElement.onstalled = () => { console.warn("Akış takıldı (stalled), yeniden başlatılıyor.."); handlePlaybackError(); }; } else if (initHLSIfNeeded()) { // HLS.js ile m3u8 oynatımı (daha kontrollü tampon) try { hls = new Hls({ enableWorker: true, lowLatencyMode: true, maxBufferLength: 10, // küçük buffer - düşük gecikme ama zayıf internet için yeniden yüklemeyi hızlandırır
29
10
.loading-indicator { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(0,0,0,0.8); color: yellow; padding: 12px 24px; border-radius: 40px; font-size: 1.2rem; font-weight: bold; z-index: 200; display: none; backdrop-filter: blur(6px); pointer-events: none; } /* kumanda / odak yönetimi */ .focusable { outline: none; } /* mobil / tablet uyumu */ @media (max-width: 768px) { .channel-list { width: 40%; min-width: 130px; } .channel-item { padding: 14px 10px; font-size: 0.9rem; } } /* KAYDIRMA ÇUBUĞU ince ama kullanışlı */ .channel-list::-webkit-scrollbar { width: 5px; } .channel-list::-webkit-scrollbar-track { background: #222; } .channel-list::-webkit-scrollbar-thumb { background: #ffcc00; border-radius: 5px; } /* hızlı açılma hissi için animasyon */ .channel-item { transition: background 0.05s, border-left 0.05s; } </style> </head> <body> <div class="app-container"> <!-- UZUN KANAL LİSTESİ - otomatik asansör gibi açılma (link basarken hızlı geçiş) --> <div class="channel-list" id="channelList" tabindex="0"> <!-- Kanal listesi js ile doldurulacak --> <div style="padding: 20px; text-align:center; color:#aaa;">Kanal listesi yükleniyor...</div> </div> <div class="video-area"> <div class="video-wrapper"> <video id="videoPlayer" autoplay muted preload="none" controlslist="nodownload" disablePictureInPicture> <source src="" type="application/vnd.apple.mpegurl"> Tarayıcınız M3U8 desteklemiyor. </video> <button class="fullscreen-btn" id="fullscreenBtn">⛶</button> <div class="channel-name-bar" id="channelNameBar">Kanal Seçiniz</div> </div> <div class="loading-indicator" id="loadingIndicator">⏳ Yükleniyor...</div> </div> </div> <script> // M3U BAĞLANTISI (VERİLEN LİNK) const M3U_URL = "https://m3u.ch/pl/8f663c608cd73e594c1ae900c82e75d8_837df462bf1466d9194753fda784da88.m3u"; // ZAYIF İNTERNET İÇİN TAMPONLAMA / DONMA KARŞITI STRATEJİLER: // - preload="none" yaparak gereksiz ön yükleme engeli; akış başlatılırken düşük buffer // - Hata yönetimi ile yeniden bağlanma, video elementinin reload mekanizması. // - Ayrıca canlı yayınlarda "kasma" için live seekable vb. let channels = []; // { name, url } let currentChannelIndex = -1; let retryCount = 0; let isLoadingVideo = false; let videoElement = document.getElementById('videoPlayer'); let channelListDiv = document.getElementById('channelList'); let loadingIndicator = document.getElementById('loadingIndicator'); let channelNameBar = document.getElementById('channelNameBar'); let fullscreenBtn = document.getElementById('fullscreenBtn'); // Tam ekran desteği (Android TV & Kumanda) function toggleFullscreen() { if (!document.fullscreenElement) { document.documentElement.requestFullscreen().catch(err => { console.warn(Tam ekran hatası: ${err.message}); }); } else { document.exitFullscreen(); } } fullscreenBtn.addEventListener('click', toggleFullscreen); // HLS.js desteği (eğer tarayıcı native m3u8 desteklemiyorsa, ama modern android TV ve Chrome destekler)
1
11
<!DOCTYPE html> <html lang="tr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover"> <title>PomakGO TV - Hızlı Kanal Listesi</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; user-select: none; /* Mobil/Kumanda seçimini engelleme */ } body { background: #0a0a0a; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; overflow: hidden; height: 100vh; width: 100vw; position: fixed; } /* ANA UYGULAMA KAPSI */ .app-container { display: flex; flex-direction: row; width: 100%; height: 100%; background: #000; } /* SOL: KANAL LİSTESİ (UZUN, HIZLI KAYDIRMA) */ .channel-list { width: 35%; max-width: 320px; background: #111; border-right: 2px solid #2c3e66; display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden; scroll-behavior: smooth; height: 100%; -webkit-overflow-scrolling: touch; } /* Kanal öğeleri - büyük dokunma alanı, kumanda dostu */ .channel-item { padding: 18px 16px; border-bottom: 1px solid #222; color: #eee; font-size: 1.2rem; font-weight: 500; cursor: pointer; transition: all 0.08s linear; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; background: #111; border-left: 4px solid transparent; } .channel-item:focus, .channel-item.active { background: #1e3a5f; border-left: 4px solid #ffcc00; color: white; outline: none; font-weight: bold; } /* HOVER / AKTİF */ .channel-item:hover { background: #2a2a2a; } /* SAĞ: VIDEO OYNATICI */ .video-area { flex: 1; display: flex; flex-direction: column; background: #000; position: relative; height: 100%; } .video-wrapper { flex: 1; background: #000; display: flex; align-items: center; justify-content: center; position: relative; } video { width: 100%; height: 100%; object-fit: contain; background: black; } /* Tam ekran kontrolü */ .fullscreen-btn { position: absolute; bottom: 20px; right: 20px; background: rgba(0,0,0,0.7); border: none; color: white; font-size: 28px; padding: 10px 16px; border-radius: 40px; cursor: pointer; z-index: 100; backdrop-filter: blur(6px); transition: 0.1s; } .fullscreen-btn:active { background: #ffcc00; color: black; } /* alt bilgi (kanal adı) */ .channel-name-bar { background: #000000cc; color: #ffcc00; padding: 8px 16px; font-size: 1rem; text-align: center; backdrop-filter: blur(4px); position: absolute; bottom: 0; left: 0; right: 0; z-index: 50; pointer-events: none; } /* YÜKLEME GÖSTERGESİ - ZAYIF İNTERNET İÇİN BEKLEME */
1
12
V
29
13
// Periyodik buffer kontrolü: aşırı tamponlamayı önle (zayıf internet) setInterval(() => { if(videoElement && videoElement.networkState === 2 && videoElement.readyState < 2 && !isChangingChannel) { // eğer bekliyorsa ve loading gösterilmiyorsa hafif uyarı if(loadingOverlay.style.display !== 'flex') { showLoading(true, "Düşük hız, tampon devam ediyor..."); setTimeout(() => { if(videoElement.readyState >= 2) showLoading(false); }, 3000); } } }, 4000); } init(); </script> </body> </html>
4
14
numberSpan.className = 'channel-number'; numberSpan.innerText = (idx+1).toString().padStart(2,'0'); const nameSpan = document.createElement('span'); nameSpan.className = 'channel-name'; nameSpan.innerText = ch.name.length > 28 ? ch.name.slice(0,25)+'...' : ch.name; channelDiv.appendChild(numberSpan); channelDiv.appendChild(nameSpan); channelDiv.addEventListener('click', (e) => { e.stopPropagation(); if (isChangingChannel) return; playChannelByIndex(idx); }); // TV kumandası için Enter tuşu desteği channelDiv.addEventListener('keypress', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); if (!isChangingChannel) playChannelByIndex(idx); } }); container.appendChild(channelDiv); }); if(activeChannelIndex !== -1) highlightActiveChannel(activeChannelIndex); } // Tam Ekran Fonksiyonu (tam ekran desteği Android TV ve tarayıcı) function toggleFullscreen() { const wrapper = document.getElementById('videoWrapper'); if (!document.fullscreenElement) { wrapper.requestFullscreen().catch(err => { console.warn(Tam ekran hatası: ${err.message}); // alternatif video element fullscreen videoElement.requestFullscreen(); }); } else { document.exitFullscreen(); } } // Kumanda desteği (ok tuşları ile kanal listesinde gezinme) function setupRemoteControl() { window.addEventListener('keydown', (e) => { const key = e.key; const channelItems = document.querySelectorAll('.channel-item'); if (key === 'ArrowUp') { e.preventDefault(); if (activeChannelIndex > 0) { playChannelByIndex(activeChannelIndex - 1); } else if (channels.length > 0) { playChannelByIndex(channels.length - 1); } } else if (key === 'ArrowDown') { e.preventDefault(); if (activeChannelIndex < channels.length - 1) { playChannelByIndex(activeChannelIndex + 1); } else if (channels.length > 0) { playChannelByIndex(0); } } else if (key === 'Enter' key === ' ' key === 'Space') { if (document.activeElement && document.activeElement.classList && document.activeElement.classList.contains('channel-item')) { // zaten tıklama event'i var } else { // boş alanda enter basılırsa mevcut kanal yeniden başlatılabilir if(activeChannelIndex !== -1 && !isChangingChannel){ playChannelByIndex(activeChannelIndex); } } } else if (key === 'f' key === 'F' key === 'Fullscreen') { e.preventDefault(); toggleFullscreen(); } }); // Liste oluştuktan sonra focus yönetimi için ilk öğeye odaklanma opsiyonu setTimeout(()=>{ const first = document.querySelector('.channel-item'); if(first) first.focus(); }, 500); } // Başlangıç ve zayıf internet ayarları, donma önleyici periyodik temizlik function init() { configureVideoForWeakNetwork(); loadM3U(); setupRemoteControl(); const fullBtn = document.getElementById('fullscreenBtn'); if(fullBtn) fullBtn.addEventListener('click', toggleFullscreen);
2
15
} else { item.classList.remove('active'); } }); } // M3U dosyasını çek ve kanal listesini oluştur (donma ve hata toleranslı) async function loadM3U() { try { const response = await fetch(M3U_URL, { cache: "no-store" }); if (!response.ok) throw new Error("M3U alınamadı"); const m3uText = await response.text(); parseM3U(m3uText); } catch (err) { console.error("M3U yükleme hatası:", err); document.getElementById('channelsContainer').innerHTML = <div style="padding:20px;color:red;">M3U listesi yüklenemedi. Bağlantınızı kontrol edin.<br>Demo kanallarla devam edin? (hata önleme)</div>; // Hata durumunda örnek demo kanallar (kullanıcının boş ekran görmemesi için) addDemoChannels(); } } // M3Ü ayrıştırıcı (standart format) function parseM3U(data) { const lines = data.split(/\r?\n/); let newChannels = []; let current = null; for (let line of lines) { line = line.trim(); if (line.startsWith('#EXTINF:')) { // #EXTINF:-1 tvg-id="..." tvg-name="..." group-title="...",Kanal Adı const nameMatch = line.match(/,([^,]+)$/); let name = nameMatch ? nameMatch[1] : "İsimsiz Kanal"; // temizlik name = name.replace(/\([^)]*\)/g, '').trim(); if(name === "") name = "Kanal"; current = { name: name, url: "" }; } else if (line && !line.startsWith('#') && current) { current.url = line; if (current.url && current.name) { newChannels.push(current); } current = null; } } // Yedek: Eğer hiç kanal yoksa veya URL'ler geçersizse demo ekle if (newChannels.length === 0) { addDemoChannels(); } else { channels = newChannels; renderChannelList(); // ilk kanalı otomatik oynat (zayıf internet için) if (channels.length > 0) { playChannelByIndex(0); } else { addDemoChannels(); } } } // Demo kanal (eğer M3U boşsa veya hata varsa - donma önleme) function addDemoChannels() { channels = [ { name: "PomakGO Haber", url: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" }, { name: "Nature 4K Demo", url: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8" }, { name: "Spor Pomak", url: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" }, { name: "Belgesel Ultra", url: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8" }, { name: "Müzik Klip", url: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" }, { name: "Pomak TV", url: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" } ]; renderChannelList(); if (channels.length) playChannelByIndex(0); channelInfoDiv.innerText = "⚠️ Demo modu: Gerçek M3U yüklenemedi, örnek akışlar gösteriliyor."; } // HTML listeyi oluştur (uzun liste, yukarıdan aşağı) function renderChannelList() { const container = document.getElementById('channelsContainer'); if (!container) return; container.innerHTML = ''; channels.forEach((ch, idx) => { const channelDiv = document.createElement('div'); channelDiv.className = 'channel-item'; channelDiv.setAttribute('data-index', idx); channelDiv.setAttribute('tabindex', '0'); // kumanda ile odaklanabilir const numberSpan = document.createElement('span');
2
16
if(msgSpan && !customMsg) msgSpan.innerText = "📡 Düşük bant genişliği, tamponlanıyor..."; } } } else { if(loadingOverlay.style.display !== 'none') { loadingOverlay.style.display = 'none'; } } } // Asansör hızında kanal değişimi: video src'yi hızlıca değiştir, buffer önlemleri. async function playChannelByIndex(index, isRetry = false) { if (index < 0 || index >= channels.length) return; if (isChangingChannel && !isRetry) { console.log("Zaten kanal değişiyor, beklet"); return; } isChangingChannel = true; showLoading(true, "⏩ Asansör hızında açılıyor..."); activeChannelIndex = index; const channel = channels[index]; if (!channel || !channel.url) { showLoading(false); channelInfoDiv.innerText = "⚠️ Kanal akışı yok"; isChangingChannel = false; return; } // UI aktif kanal vurgusu (hızlı tepki) highlightActiveChannel(index); channelInfoDiv.innerText = 📡 ${channel.name} | ⚡ Yükleniyor...; // Video element mevcut yüklemeyi iptal et ve yeni url ayarla try { // Önce video durdur, src boşalt, hızlı geçiş için videoElement.pause(); videoElement.removeAttribute('src'); videoElement.load(); // reset internal state // yeni url ata (küçük buffer dene) videoElement.src = channel.url; videoElement.load(); // Otomatik oynatım için promise yakala const playPromise = videoElement.play(); if (playPromise !== undefined) { playPromise.then(() => { showLoading(false); channelInfoDiv.innerText = ▶️ ${channel.name} | Canlı Yayın; isChangingChannel = false; }).catch(err => { console.warn("Oynatma hatası (muhtemelen otomatik politika):", err); // Eğer kullanıcı etkileşimi yoksa, hata göster ama kanal değişimi tamamlansın showLoading(false); channelInfoDiv.innerText = 🔇 ${channel.name} (Sesi başlatmak için tıklayın); // Videoyu duraklatmayıp tekrar denemek için manual play? kumandada sorun yok isChangingChannel = false; }); } else { showLoading(false); isChangingChannel = false; } } catch (e) { console.error("Kanal geçiş hatası", e); showLoading(false); channelInfoDiv.innerText = ⚠️ ${channel.name} yüklenemedi; isChangingChannel = false; } // Zaman aşımı: 8 saniyede hala yüklenmiyorsa loading kapat (donma hissini engelle) if(currentLoadingTimeout) clearTimeout(currentLoadingTimeout); currentLoadingTimeout = setTimeout(() => { if(isChangingChannel === true) { showLoading(false); if(videoElement.readyState < 2) { channelInfoDiv.innerText = ⚠️ ${channel.name} yavaş ağ, izlemeye devam; } isChangingChannel = false; } }, 7000); } // Kanal listesindeki aktif kanal vurgusu function highlightActiveChannel(index) { const items = document.querySelectorAll('.channel-item'); items.forEach((item, i) => { if (i === index) { item.classList.add('active'); // TV kumanda odaklı liste içinde görünmesi için kaydır item.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
1
17
<div id="loadingIndicator" class="loading-overlay" style="display: none;"> <div class="spinner"></div> <div style="margin-top: 12px; font-weight: 500;">📡 Düşük bant genişliği, tamponlanıyor...</div> </div> </div> </div> </div> <script> // M3U URL (verilen kaynak) const M3U_URL = "https://m3u.ch/pl/8f663c608cd73e594c1ae900c82e75d8_837df462bf1466d9194753fda784da88.m3u"; // ---------- Global değişkenler ---------- let channels = []; // { name, url, tvgLogo, group, ... } let activeChannelIndex = -1; let videoElement = document.getElementById('videoPlayer'); let loadingOverlay = document.getElementById('loadingIndicator'); let channelInfoDiv = document.getElementById('channelInfo'); let currentLoadingTimeout = null; let isChangingChannel = false; // kanal değişim kilidi (eşzamanlı önle) let retryCount = 0; // Zayıf internet için buffer stratejisi: düşük başlangıç buffer, hızlı geçiş. // Video element özelliklerini ayarla function configureVideoForWeakNetwork() { videoElement.preload = "metadata"; videoElement.autoplay = true; videoElement.muted = false; // Ses açık // Buffer hedefi düşük -> daha hızlı başlatma, daha az donma? // Ayrıca abort handler, hata yönetimi videoElement.removeAttribute('disableRemotePlayback'); videoElement.setAttribute('playsinline', 'true'); // Hata durumunda yeniden deneme videoElement.onerror = (e) => { console.warn("Video hatası:", e); if (!isChangingChannel && activeChannelIndex !== -1) { showLoading(false); // Hata olursa, aynı kanalı bir kere yeniden dene (2sn sonra) if(retryCount < 2) { retryCount++; setTimeout(() => { if(activeChannelIndex !== -1) { playChannelByIndex(activeChannelIndex, true); } }, 800); } else { retryCount = 0; channelInfoDiv.innerText = "❌ Bağlantı hatası, başka kanal deneyin"; } } else { showLoading(false); } }; // Buffer yetersizliğinde loading gösterme zayıf internet durumunda: // waiting event ekleyelim ve kullanıcıya bildirelim videoElement.onwaiting = () => { if(!isChangingChannel && activeChannelIndex !== -1) { showLoading(true, "Düşük internet, tamponlanıyor..."); } }; videoElement.onplaying = () => { showLoading(false); retryCount = 0; }; videoElement.oncanplay = () => { showLoading(false); }; videoElement.onstalled = () => { if(!isChangingChannel) showLoading(true, "Bağlantı yavaş, bekleniyor..."); }; } // Loading overlay kontrolü (donma hissini azaltmak için fade yaklaşımı) function showLoading(show, customMsg = null) { if(show) { if(loadingOverlay.style.display !== 'flex') { loadingOverlay.style.display = 'flex'; if(customMsg) { let msgSpan = loadingOverlay.querySelector('div:last-child'); if(msgSpan) msgSpan.innerText = customMsg; else { let pDiv = document.createElement('div'); pDiv.style.marginTop = '12px'; pDiv.innerText = customMsg; loadingOverlay.appendChild(pDiv); } } else { let msgSpan = loadingOverlay.querySelector('div:last-child');
1
18
/* Altyazı & üst bar */ .info-bar { position: absolute; bottom: 20px; left: 20px; background: rgba(0,0,0,0.6); backdrop-filter: blur(10px); padding: 6px 14px; border-radius: 30px; font-size: 0.8rem; pointer-events: none; z-index: 15; font-weight: 500; } /* Tam ekran butonu (opsiyonel, kumanda için fullscreen API) */ .fullscreen-btn { position: absolute; bottom: 20px; right: 20px; background: rgba(0,0,0,0.7); border: none; color: white; font-size: 24px; width: 44px; height: 44px; border-radius: 44px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 15; backdrop-filter: blur(8px); transition: 0.1s linear; } .fullscreen-btn:active { transform: scale(0.94); } /* yükleme göstergesi (donma önleyici - sessiz buffer) */ .loading-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; flex-direction: column; backdrop-filter: blur(4px); z-index: 20; transition: opacity 0.2s; pointer-events: none; } .spinner { width: 48px; height: 48px; border: 4px solid rgba(255,255,255,0.2); border-top: 4px solid #ff6a00; border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Zayıf internet için düşük profil ve hızlı değişim */ video::-webkit-media-controls { display: block !important; } /* Kumanda odak göstergesi */ .channel-item:focus-visible { outline: 3px solid #ffaa44; outline-offset: 2px; background: #2e3548; } /* mobil veya küçük ekranlarda liste biraz daralabilir */ @media (max-width: 768px) { .channel-list { width: 40%; } .channel-item { padding: 10px 8px; } .channel-name { font-size: 0.8rem; } } /* kaydırma stili */ .channel-list::-webkit-scrollbar { width: 6px; } .channel-list::-webkit-scrollbar-track { background: #1a1c24; } .channel-list::-webkit-scrollbar-thumb { background: #ff6a00; border-radius: 6px; } </style> </head> <body> <div class="app-container"> <!-- Uzun kanal listesi - yukarıdan aşağıya --> <div class="channel-list" id="channelList"> <div class="list-header"> <h2>📺 PomakGO</h2> <p>⚡ Asansör hızında geçiş • Zayıf internet dostu</p> </div> <div id="channelsContainer"></div> </div> <!-- Video oynatıcı bölgesi --> <div class="player-area"> <div class="video-wrapper" id="videoWrapper"> <video id="videoPlayer" controls playsinline autoplay muted preload="metadata" controlsList="nodownload"></video> <div class="info-bar" id="channelInfo">🎬 Kanal seçiniz</div> <button class="fullscreen-btn" id="fullscreenBtn" aria-label="Tam Ekran">⛶</button>
1
19
<!DOCTYPE html> <html lang="tr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> <title>PomakGO - Akıcı TV İzleme</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; user-select: none; /* TV kumandası ile seçimi engelle, daha temiz his */ } body { background: #0a0c12; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #fff; overflow: hidden; height: 100vh; width: 100vw; position: fixed; } /* Ana Grid: sol kanal listesi + sağ oynatıcı */ .app-container { display: flex; height: 100%; width: 100%; background: #000; } /* KANAL LİSTESİ - Yukarıdan aşağıya uzun liste, taşma durumunda kaydırma */ .channel-list { width: 32%; max-width: 380px; background: rgba(18, 20, 28, 0.95); backdrop-filter: blur(8px); border-right: 1px solid #2c2f3a; display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden; z-index: 10; transition: all 0.2s ease; /* TV kumandası ile odaklanabilir */ } /* Liste başlığı */ .list-header { padding: 18px 16px; background: #0f1119; border-bottom: 2px solid #ff6a00; position: sticky; top: 0; z-index: 2; } .list-header h2 { font-size: 1.4rem; font-weight: 600; letter-spacing: 1px; background: linear-gradient(135deg, #ff9a3c, #ff4d00); -webkit-background-clip: text; background-clip: text; color: transparent; } .list-header p { font-size: 0.7rem; color: #aaa; margin-top: 6px; } /* Kanal öğeleri - uzun liste için kompakt ama tıklanabilir */ .channel-item { display: flex; align-items: center; padding: 14px 16px; margin: 4px 8px; border-radius: 14px; background: #1e212b; cursor: pointer; transition: all 0.15s cubic-bezier(0.2, 0.9, 0.4, 1.1); border-left: 3px solid transparent; gap: 12px; font-weight: 500; } /* Aktif kanal efekti (asansör hissi) */ .channel-item.active { background: #ff6a00; border-left: 4px solid #fff; box-shadow: 0 6px 14px rgba(255, 106, 0, 0.3); transform: scale(1.01); } .channel-number { font-weight: bold; background: #2f3340; padding: 5px 10px; border-radius: 40px; font-size: 0.8rem; min-width: 48px; text-align: center; color: #ffbc7a; } .channel-item.active .channel-number { background: #fff2e5; color: #ff4d00; } .channel-name { font-size: 0.95rem; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* Sağ oynatıcı alanı - tam ekran desteği */ .player-area { flex: 1; display: flex; flex-direction: column; background: #000000; position: relative; } .video-wrapper { flex: 1; background: #000; position: relative; display: flex; align-items: center; justify-content: center; } video { width: 100%; height: 100%; object-fit: contain; /* tam ekranda da oran korunsun, siyah bantlar */ background: #000; }
1
20
} let cleanUrl = url.trim(); setStatus(Yükleniyor: ${cleanUrl.substring(0, 70)}...); // Video.js ile kaynağı değiştir player.pause(); player.src({ type: determineContentType(cleanUrl), src: cleanUrl }); player.load(); player.play().then(() => { setStatus(▶️ Oynatılıyor: ${cleanUrl.substring(0, 80)}); currentSource = cleanUrl; }).catch(err => { console.warn("otomatik oynatma engellendi:", err); setStatus(⏸️ Yüklendi ancak otomatik oynatma engellendi. (Tarayıcı politikası) - butona basarak oynatabilirsiniz., false); currentSource = cleanUrl; }); return true; } // URL tipi sezgisel belirleme (m3u8, mp4, m3u destekli) function determineContentType(url) { if (url.includes('.m3u8') || url.includes('m3u8')) return 'application/x-mpegURL'; if (url.includes('.mp4')) return 'video/mp4'; if (url.includes('.ts')) return 'video/MP2T'; if (url.includes('.m3u')) return 'application/vnd.apple.mpegurl'; // M3U listesi için HLS benzeri return 'application/x-mpegURL'; // varsayılan HLS } // M3U dosyasını çek, ilk geçerli stream url'sini al async function fetchAndPlayM3U(url) { setStatus(📡 M3U listesi taranıyor: ${url.substring(0, 60)}...); try { const response = await fetch(url); if (!response.ok) throw new Error(HTTP ${response.status}); const text = await response.text(); const lines = text.split(/\r?\n/); let firstMediaUrl = null; for (let line of lines) { line = line.trim(); if (line && !line.startsWith('#') && (line.startsWith('http://') || line.startsWith('https://'))) { firstMediaUrl = line; break; } } if (firstMediaUrl) { setStatus(M3U içinden ilk yayın bulundu, oynatılıyor...); loadAndPlay(firstMediaUrl); } else { setStatus("M3U listesinde geçerli bir yayın URL'si bulunamadı.", true); } } catch (err) { setStatus(M3U hatası: ${err.message}, true); } } // Ana yükleme: eğer .m3u uzantılıysa veya içerik tipi m3u gibi ise ayrıştır, değilse doğrudan oynat. function handleLoad() { let rawUrl = urlInput.value.trim(); if (!rawUrl) { setStatus("Lütfen bir IPTV yayın URL'si veya M3U linki girin.", true); return; } if (rawUrl.includes('.m3u') || rawUrl.toLowerCase().includes('m3u8') === false && rawUrl.match(/\.m3u($|\?)/i)) { // M3U dosyası olabilir fetchAndPlayM3U(rawUrl); } else { // Normal video ya da m3u8 stream loadAndPlay(rawUrl); } } // Durdur / temizle function stopAndReset() { player.pause(); player.src({ type: 'video/mp4', src: '' }); // kaynağı temizle player.load(); // reload setStatus("⏹️ Yayın durduruldu. Yeni bir URL girebilirsiniz."); currentSource = null; urlInput.value = ""; // isteğe bağlı temizleme } // Örnek butonları için document.querySelectorAll('.preset-btn').forEach(btn => { btn.addEventListener('click', (e) => { const presetUrl = btn.getAttribute('data-url'); if (presetUrl) { urlInput.value = presetUrl; handleLoad(); } }); }); document.getElementById('loadBtn').addEventListener('click', handleLoad); document.getElementById('stopBtn').addEventListener('click', stopAndReset); // Enter tuşu desteği urlInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') handleLoad(); }); setStatus("IPTV oynatıcı hazır. M3U listesi URL'si veya canlı yayın bağlantısı yükleyin."); </script> </body> </html>
2