ZoyaPatel

Player A simple, accessible and customisable media player for Video, Audio, Mux, YouTube and Vimeo

Mumbai


 

<link href="https://cdn.plyr.io/3.7.8/plyr.css" rel="stylesheet" />

<script src="https://cdn.plyr.io/3.7.8/plyr.polyfilled.js"></script>

<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>

<style>

  :root {

    --plyr-color-main: #ff9800;

    --bg-dark: #212832;

    --bg-darker: #151b23;

    --btn-bg: #2a3441;

    --btn-hover: #3b485a;

    --scroll-track: #1a2028;

    --scroll-thumb: #455266;

  }

  .custom-player-wrapper {

    background-color: var(--bg-dark);

    border-radius: 8px;

    padding: 6px;

    font-family: system-ui, sans-serif;

    color: #fff;

    width: 100%;

    box-sizing: border-box;

    margin: 15px auto;

    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.25);

  }

  .player-screen {

    position: relative;

    width: 100%;

    padding-top: 56.25%;

    background: #000;

    border-radius: 6px;

    overflow: hidden;

    margin-bottom: 12px;

  }

  .player-logo {

    position: absolute;

    top: 15px;

    right: 15px;

    width: 20%;

    max-width: 146px;

    min-width: 90px;

    height: auto;

    z-index: 60;

    pointer-events: none;

    opacity: 0.85;

    display: none;

    filter: drop-shadow(0px 2px 5px rgba(0, 0, 0, 0.5));

  }

  #embed-player, .plyr-wrapper, #ad-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; }

  .plyr { width: 100%; height: 100%; }

  #ad-layer { z-index: 50; background: #000; }

  #ad-video { width: 100%; height: 100%; object-fit: contain; background: #000; }

  .ad-badge {

    position: absolute; top: 12px; left: 12px;

    background: #fbc02d; color: #000;

    padding: 4px 8px; font-size: 11px;

    font-weight: 700; border-radius: 4px;

    z-index: 52; text-transform: uppercase;

    letter-spacing: 0.5px;

  }

  .ad-click-area { position: absolute; top: 0; left: 0; width: 100%; height: 80%; cursor: pointer; z-index: 51; display: flex; align-items: center; justify-content: center; }

  .ad-link-icon { background: rgba(33, 40, 50, 0.85); border: 2px solid var(--plyr-color-main); color: #fff; padding: 12px 24px; border-radius: 30px; font-size: 15px; font-weight: 700; display: flex; align-items: center; gap: 8px; pointer-events: none; transition: all 0.2s ease; backdrop-filter: blur(4px); box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5); }

  .ad-click-area:hover .ad-link-icon { background: var(--plyr-color-main); color: #000; transform: scale(1.05); }

  .skip-btn { position: absolute; bottom: 12px; right: 12px; background: rgba(33, 40, 50, 0.9); color: white; border: 1px solid var(--scroll-thumb); padding: 8px 16px; border-radius: 6px; z-index: 52; cursor: not-allowed; font-weight: 600; font-size: 13px; transition: all 0.3s ease; }

  .skip-btn.ready { cursor: pointer; background: var(--plyr-color-main); border-color: var(--plyr-color-main); color: #000; box-shadow: 0 4px 12px rgba(255, 152, 0, 0.4); }

  .skip-btn.ready:hover { filter: brightness(1.1); }

  .playlist-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(54px, 1fr)); gap: 6px; margin-bottom: 12px; max-height: 126px; overflow-y: auto; padding-right: 4px; }

  .playlist-grid::-webkit-scrollbar { width: 6px; }

  .playlist-grid::-webkit-scrollbar-track { background: var(--scroll-track); border-radius: 4px; }

  .playlist-grid::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: 4px; }

  .playlist-grid::-webkit-scrollbar-thumb:hover { background: var(--plyr-color-main); }

  .ep-btn { background-color: var(--btn-bg); color: #fff; border: 1px solid transparent; padding: 8px 4px; border-radius: 4px; cursor: pointer; font-weight: 600; text-align: center; transition: all 0.2s ease; font-size: 12px; }

  .ep-btn:hover { background-color: var(--btn-hover); }

  .ep-btn.active { background-color: var(--bg-darker); border-color: var(--plyr-color-main); color: var(--plyr-color-main); }

  .playlist-nav { display: flex; justify-content: center; align-items: center; gap: 15px; background-color: var(--bg-darker); padding: 10px; border-radius: 6px; flex-wrap: wrap; }

  .playlist-nav button { background-color: var(--btn-bg); color: #fff; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: 700; transition: background 0.2s; }

  .playlist-nav button:hover { background-color: var(--btn-hover); }

  .playlist-nav span { font-size: 14px; font-weight: 700; color: #aaa; }

</style>

<script>

//<![CDATA[

  const globalAdSettings = { 

    mp4: "https://bigf.bigo.sg/asia_live/V4s7/1hS2IX.mp4",

    link: "https://affiliate.w88u2.com/Track.aspx?affiliateid=35730",

    logo: "https://blogger.googleusercontent.com/img/a/AVvXsEimG6JfDJN5FpDCYz5zLXz1CGruZmJpAFkXRz1mRJnyoINM4XA6MleRg9lfeQ0o3nidjfm6AwZrVqxjedwIPyqxgRc1CJFZwF7Ta4piADTCEV3OQHRwPURDiRkX7Frq4d6ySJYKZ1ZSkAmrYVPEmHyfjqfOT5j4iR9dsBlK922t9qDSeToeEWcTyW7O5FQ=s510"

  };

  let currentPlaylist = [];

  let currentEpIndex = 0;

  let hlsInstance = null;

  let plyrInstance = null;

  let skipTimer = null;

  function initTvPopPlaylist(containerId, playlistData) {

    const container = document.getElementById(containerId);

    if (!container) return;

    container.innerHTML = `

      <div class="custom-player-wrapper">

        <div class="player-screen">

           <img id="player-watermark-${containerId}" src="${globalAdSettings.logo}" class="player-logo" alt="Watermark" />

           <iframe id="embed-player" src="" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen referrerpolicy="strict-origin-when-cross-origin" style="display:none; z-index: 1;"></iframe>

           <div id="plyr-wrapper" class="plyr-wrapper" style="display:none; z-index: 2;">

              <video id="main-html5-player" playsinline controls oncontextmenu="return false;"></video>

           </div>

           <div id="ad-layer" style="display:none;">

              <video id="ad-video" playsinline muted oncontextmenu="return false;"></video> 

              <div class="ad-badge">Sponsored</div>

              <div class="ad-click-area" onclick="window.open(globalAdSettings.link, '_blank')">

                 <div class="ad-link-icon">&#128279; Visit Link</div>

              </div>

              <button id="skip-btn" class="skip-btn" onclick="skipAd('${containerId}')">Skip Ad (5)</button>

           </div>

        </div>

        <div class="playlist-grid" id="playlist-grid"></div>

        <div class="playlist-nav">

           <button id="btn-prev">&#9664; PREV</button>

           <span id="page-indicator">00 / 00</span>

           <button id="btn-next">NEXT &#9654;</button>

        </div>

      </div>

    `;

    currentPlaylist = playlistData;

    const grid = container.querySelector('#playlist-grid');

    currentPlaylist.forEach((item, index) => {

      const btn = document.createElement('button');

      btn.className = 'ep-btn';

      btn.id = 'ep-btn-' + containerId + '-' + index;

      btn.innerHTML = item.ep;

      btn.onclick = () => processEpisodeClick(containerId, index);

      grid.appendChild(btn);

    });

    container.querySelector('#btn-prev').onclick = () => processEpisodeClick(containerId, currentEpIndex - 1);

    container.querySelector('#btn-next').onclick = () => processEpisodeClick(containerId, currentEpIndex + 1);

    plyrInstance = new Plyr(container.querySelector('#main-html5-player'), { 

      controls: ['play-large', 'play', 'rewind', 'fast-forward', 'progress', 'current-time', 'duration', 'mute', 'volume', 'pip', 'fullscreen'], 

      seekTime: 10 

    });

    if (currentPlaylist.length > 0) processEpisodeClick(containerId, 0);

  }

  function processEpisodeClick(containerId, index) {

    if (index < 0 || index >= currentPlaylist.length) return;

    currentEpIndex = index;

    const container = document.getElementById(containerId);

    container.querySelectorAll('.ep-btn').forEach(b => b.classList.remove('active'));

    container.querySelector('#ep-btn-' + containerId + '-' + index).classList.add('active');

    container.querySelector('#page-indicator').innerText = String(index + 1).padStart(2, '0') + ' / ' + currentPlaylist.length;

    container.querySelector('#ad-video').pause();

    plyrInstance.pause();

    if (globalAdSettings.mp4 && globalAdSettings.mp4.trim() !== "") {

        playAd(containerId, index);

    } else {

        loadMainVideo(containerId, index);

    }

  }

  function playAd(containerId, targetIndex) {

    const container = document.getElementById(containerId);

    const adLayer = container.querySelector('#ad-layer');

    const adVideo = container.querySelector('#ad-video');

    const skipBtn = container.querySelector('#skip-btn');

    const iframeLayer = container.querySelector('#embed-player');

    const plyrLayer = container.querySelector('#plyr-wrapper');

    const watermark = container.querySelector(`#player-watermark-${containerId}`);

    iframeLayer.style.display = 'none'; iframeLayer.src = ''; 

    plyrLayer.style.display = 'none'; watermark.style.display = 'none'; 

    adLayer.style.display = 'block';

    skipBtn.classList.remove('ready'); 

    adVideo.src = globalAdSettings.mp4; 

    adVideo.play().catch(e => console.log("Autoplay prevented:", e));

    let timeLeft = 5; 

    skipBtn.innerText = "Skip Ad (" + timeLeft + ")"; 

    clearInterval(skipTimer);

    skipTimer = setInterval(() => {

      timeLeft--;

      if (timeLeft <= 0) { 

          clearInterval(skipTimer); 

          skipBtn.innerText = "Skip Ad \u25B6"; 

          skipBtn.classList.add('ready'); 

      } else { 

          skipBtn.innerText = "Skip Ad (" + timeLeft + ")"; 

      }

    }, 1000);

    adVideo.onended = () => { skipBtn.classList.add('ready'); skipAd(containerId); };

  }

  function skipAd(containerId) {

    const container = document.getElementById(containerId);

    const skipBtn = container.querySelector('#skip-btn');

    if (!skipBtn.classList.contains('ready')) return; 

    clearInterval(skipTimer); 

    container.querySelector('#ad-video').pause(); 

    container.querySelector('#ad-layer').style.display = 'none';

    loadMainVideo(containerId, currentEpIndex);

  }

  function loadMainVideo(containerId, index) {

    const container = document.getElementById(containerId);

    const item = currentPlaylist[index];

    const iframeLayer = container.querySelector('#embed-player');

    const plyrLayer = container.querySelector('#plyr-wrapper');

    const videoHtml5 = container.querySelector('#main-html5-player');

    const adLayer = container.querySelector('#ad-layer');

    const watermark = container.querySelector(`#player-watermark-${containerId}`);

    adLayer.style.display = 'none';

    watermark.style.display = 'block';

    if (hlsInstance) { hlsInstance.destroy(); hlsInstance = null; }

    if (item.type === 'embed') {

      plyrLayer.style.display = 'none'; 

      iframeLayer.style.display = 'block'; 

      iframeLayer.src = item.src;

    } else {

      iframeLayer.style.display = 'none'; 

      iframeLayer.src = ''; 

      plyrLayer.style.display = 'block';

      if (item.type === 'm3u8') {

        if (Hls.isSupported()) {

          hlsInstance = new Hls(); hlsInstance.loadSource(item.src); hlsInstance.attachMedia(videoHtml5);

          hlsInstance.on(Hls.Events.MANIFEST_PARSED, () => plyrInstance.play());

        } else if (videoHtml5.canPlayType('application/vnd.apple.mpegurl')) { 

          videoHtml5.src = item.src; plyrInstance.play();

        }

      } else { 

          videoHtml5.src = item.src; plyrInstance.play(); 

      }

    }

  }

  // --- C. Bulletproof Parser ---

  document.addEventListener("DOMContentLoaded", () => {

    document.querySelectorAll('.tvpop_player').forEach((container, index) => {

      // 1. Get raw HTML and completely strip out Blogger's annoying <br> or <p> tags

      let rawText = container.innerHTML.replace(/<[^>]*>?/gm, '').trim();

      let rawUrls = [];

      const matchSecret = rawText.match(/\[tvpop_playlist secret="([\s\S]*?)"\]/);

      const matchPlain = rawText.match(/\[tvpop_playlist src="([\s\S]*?)"\]/);

      if (matchSecret && matchSecret[1]) {

        try { 

            // Decode and split, removing any invisible spaces

            rawUrls = atob(matchSecret[1].trim()).split(',').map(u => u.replace(/\s+/g, '')).filter(u => u); 

        } 

        catch(e) { console.error("Could not decode secret links."); }

      } else if (matchPlain && matchPlain[1]) {

        rawUrls = matchPlain[1].split(',').map(u => u.replace(/\s+/g, '')).filter(u => u);

      }

      if (rawUrls.length > 0) {

        const playlistData = rawUrls.map((url, i) => {

           let finalUrl = url;

           let videoType = 'embed'; 

           if (finalUrl.includes('dailymotion.com/video/')) {

               finalUrl = 'https://www.dailymotion.com/embed/video/' + finalUrl.split('dailymotion.com/video/')[1].split('?')[0];

           } else if (finalUrl.includes('youtube.com/watch?v=')) {

               finalUrl = 'https://www.youtube-nocookie.com/embed/' + finalUrl.split('v=')[1].split('&')[0];

           } else if (finalUrl.includes('youtu.be/')) {

               finalUrl = 'https://www.youtube-nocookie.com/embed/' + finalUrl.split('youtu.be/')[1].split('?')[0];

           } else if (finalUrl.includes('youtube.com/embed/')) {

               finalUrl = finalUrl.replace('youtube.com', 'youtube-nocookie.com');

           }

           if (finalUrl.includes('.m3u8') || finalUrl.includes('.hls')) videoType = 'm3u8';

           else if (finalUrl.includes('.mp4')) videoType = 'mp4';

           return { ep: 'Ep ' + (i + 1), type: videoType, src: finalUrl, cc: false };

        });

        container.innerHTML = ''; 

        container.id = 'tvpop-auto-player-' + index; 

        initTvPopPlaylist(container.id, playlistData);

      }

    });

  });

//]]>

</script>{codeBox}

Ahmedabad