风萧 发表于 2026-8-26 08:29:05

带歌词的音频播放器代码
推荐版·自动滚动歌词
<div style="width:100%;max-width:540px;margin:10px auto;border:1px solid #ddd;border-radius:14px;overflow:hidden;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);box-shadow:0 6px 20px rgba(0,0,0,0.15);font-family:'Microsoft YaHei','PingFang SC',Arial,sans-serif;color:#fff;font-size:14px;">

<!-- ========== 顶部:封面 + 歌曲信息 ========== -->
<div style="display:flex;align-items:center;padding:16px;background:rgba(0,0,0,0.18);">
    <img src="你的封面图片URL.jpg" alt="专辑封面" style="width:84px;height:84px;border-radius:10px;object-fit:cover;border:2px solid rgba(255,255,255,0.35);margin-right:16px;flex-shrink:0;" onerror="this.style.display='none';">
    <div style="flex:1;min-width:0;">
      <div style="font-size:19px;font-weight:bold;margin-bottom:6px;letter-spacing:0.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">♫ 声声慢</div>
      <div style="font-size:13px;opacity:0.8;margin-bottom:4px;">演唱:韩菁英</div>
      <div style="font-size:12px;opacity:0.6;">专辑:最美女声</div>
    </div>
</div>

<!-- ========== 中部:歌词滚动区 ========== -->
<div style="padding:14px 16px;background:rgba(255,255,255,0.08);">
    <div style="text-align:center;font-size:12px;opacity:0.7;margin-bottom:10px;letter-spacing:2px;">━━━ 歌词 ━━━</div>

    <!-- marquee:HTML原生滚动标签,direction=up向上滚动,scrollamount控制速度 -->
    <marquee direction="up" scrollamount="1" scrolldelay="130" height="180" style="text-align:center;line-height:2.1;font-size:15px;color:#fff;text-shadow:0 1px 3px rgba(0,0,0,0.3);">
<p>作词 : 崔开潮</p>
<p>作曲 : 崔开潮</p>
<p>青砖伴瓦漆</p>
<p>白马踏新泥</p>
<p>山花蕉叶暮色丛染红巾</p>
<p>屋檐洒雨滴</p>
<p>炊烟袅袅起</p>
<p>蹉跎辗转宛然的你在哪里</p>
<p>寻寻觅觅</p>
<p>冷冷清清</p>
<p>月落乌啼月牙落孤井</p>
<p>零零碎碎</p>
<p>点点滴滴</p>
<p>梦里有花梦里青草地</p>
<p>长发引涟漪</p>
<p>白布展石矶</p>
<p>河童撑杆摆长舟渡古稀</p>
<p>屋檐洒雨滴</p>
<p>炊烟袅袅起</p>
<p>蹉跎辗转宛然的你在哪里</p>
<p>寻寻觅觅</p>
<p>冷冷清清</p>
<p>月落乌啼月牙落孤井</p>
<p>零零碎碎</p>
<p>点点滴滴</p>
<p>梦里有花梦里青草地</p>
<p>青砖伴瓦漆</p>
<p>白马踏新泥</p>
<p>山花蕉叶暮色丛染红巾</p>
<p>屋檐洒雨滴</p>
<p>炊烟袅袅起</p>
<p>蹉跎辗转宛然的你在哪里</p>

      <span style="opacity:0.5;">—— 完 ——</span>
    </marquee>
</div>

<!-- ========== 底部:原生音频控件 ========== -->
<div style="padding:12px 14px;background:rgba(0,0,0,0.25);">
    <audio src="https://www.joy127.com/url/158097.mp3" controls="controls" loop="loop" autoplay preload="metadata" style="width:100%;height:44px;outline:none;border-radius:6px;"></audio>
</div>

<!-- 底部小提示条 -->
<div style="text-align:center;font-size:11px;opacity:0.55;padding:6px 0 10px;letter-spacing:1px;">
    点击播放器 ▶ 按钮开始播放
</div>
</div>

手动滚动歌词
<div style="width:100%;max-width:540px;margin:10px auto;border:1px solid #ddd;border-radius:14px;overflow:hidden;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);box-shadow:0 6px 20px rgba(0,0,0,0.15);font-family:'Microsoft YaHei','PingFang SC',Arial,sans-serif;color:#fff;font-size:14px;">

<div style="display:flex;align-items:center;padding:16px;background:rgba(0,0,0,0.18);">
    <img src="你的封面图片URL.jpg" alt="专辑封面" style="width:84px;height:84px;border-radius:10px;object-fit:cover;border:2px solid rgba(255,255,255,0.35);margin-right:16px;flex-shrink:0;" onerror="this.style.display='none';">
    <div style="flex:1;min-width:0;">
      <div style="font-size:19px;font-weight:bold;margin-bottom:6px;letter-spacing:0.5px;">♫ 声声慢</div>
      <div style="font-size:13px;opacity:0.8;margin-bottom:4px;">演唱:韩菁英</div>
      <div style="font-size:12px;opacity:0.6;">专辑:最美女声</div>
    </div>
</div>

<!-- 手动滚动歌词区:overflow:auto 自动生成滚动条 -->
<div style="padding:14px 16px;background:rgba(255,255,255,0.08);">
    <div style="text-align:center;font-size:12px;opacity:0.7;margin-bottom:10px;letter-spacing:2px;">━━━ 歌词(鼠标滚轮滑动) ━━━</div>
    <div style="height:180px;overflow-y:auto;overflow-x:hidden;text-align:center;line-height:2.1;font-size:15px;color:#fff;text-shadow:0 1px 3px rgba(0,0,0,0.3);scrollbar-width:thin;scrollbar-color:rgba(255,255,255,0.4) transparent;">
<p>作词 : 崔开潮</p>
<p>作曲 : 崔开潮</p>
<p>青砖伴瓦漆</p>
<p>白马踏新泥</p>
<p>山花蕉叶暮色丛染红巾</p>
<p>屋檐洒雨滴</p>
<p>炊烟袅袅起</p>
<p>蹉跎辗转宛然的你在哪里</p>
<p>寻寻觅觅</p>
<p>冷冷清清</p>
<p>月落乌啼月牙落孤井</p>
<p>零零碎碎</p>
<p>点点滴滴</p>
<p>梦里有花梦里青草地</p>
<p>长发引涟漪</p>
<p>白布展石矶</p>
<p>河童撑杆摆长舟渡古稀</p>
<p>屋檐洒雨滴</p>
<p>炊烟袅袅起</p>
<p>蹉跎辗转宛然的你在哪里</p>
<p>寻寻觅觅</p>
<p>冷冷清清</p>
<p>月落乌啼月牙落孤井</p>
<p>零零碎碎</p>
<p>点点滴滴</p>
<p>梦里有花梦里青草地</p>
<p>青砖伴瓦漆</p>
<p>白马踏新泥</p>
<p>山花蕉叶暮色丛染红巾</p>
<p>屋檐洒雨滴</p>
<p>炊烟袅袅起</p>
<p>蹉跎辗转宛然的你在哪里</p>
      <span style="opacity:0.5;">—— 完 ——</span>
    </div>
</div>

<div style="padding:12px 14px;background:rgba(0,0,0,0.25);">
    <audio src="https://www.joy127.com/url/158097.mp3" controls="controls" loop="loop" autoplay preload="metadata" style="width:100%;height:44px;outline:none;border-radius:6px;"></audio>
</div>

<div style="text-align:center;font-size:11px;opacity:0.55;padding:6px 0 10px;letter-spacing:1px;">
    点击播放器 ▶ 按钮开始播放
</div>
</div>

风萧 发表于 2026-8-26 10:19:40

非常漂亮的多歌列表播放器
<style type="text/css">
/* ========== 外层容器(不影响外部页面) ========== */
.audio-playlist-container {
    max-width: 800px;
    margin: 15px auto;
    font-family: "Microsoft YaHei", "微软雅黑", sans-serif;
    background: #1a1a1a;
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0 10px 40px rgba(0,0,0,0.5);
    color: #fff;
    box-sizing: border-box;
}
/* 容器内局部 reset —— 只影响播放器内部,不会改到论坛页面 */
.audio-playlist-container, .audio-playlist-container * {
    box-sizing: border-box;
}
.audio-playlist-container * {
    margin: 0;
    padding: 0;
}

/* ===== 主播放区(替代视频画面) ===== */
.audio-playlist-container .audio-main {
    position: relative;
    background: linear-gradient(135deg, #1a1a1a 0%, #0d0d0d 100%);
    padding: 30px 20px 20px;
    min-height: 280px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
/* 背景柔光 */
.audio-playlist-container .audio-main::before {
    content: "";
    position: absolute;
    width: 300px; height: 300px;
    background: radial-gradient(circle, rgba(231,76,60,0.25) 0%, transparent 70%);
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    pointer-events: none;
}
.audio-playlist-container .audio-info-bar {
    position: absolute;
    top: 0; left: 0; right: 0;
    background: linear-gradient(to bottom, rgba(0,0,0,0.75), transparent);
    padding: 15px 20px;
    z-index: 10;
}
.audio-playlist-container .audio-title {
    font-size: 16px;
    font-weight: bold;
    margin-bottom: 5px;
    text-shadow: 0 1px 3px rgba(0,0,0,0.6);
}
.audio-playlist-container .audio-index {
    font-size: 12px;
    opacity: 0.8;
}

/* 唱片封面 */
.audio-playlist-container .disc-wrap {
    position: relative;
    width: 180px;
    height: 180px;
    margin-top: 20px;
    z-index: 2;
}
.audio-playlist-container .disc {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background:
      radial-gradient(circle at center, #e74c3c 0 18%, #111 18.5% 22%, #222 22.5% 50%, #111 50.5% 52%, #222 52.5% 100%);
    box-shadow: 0 8px 30px rgba(0,0,0,0.7), inset 0 0 20px rgba(0,0,0,0.8);
    position: relative;
    animation: apc-spin 8s linear infinite;
    animation-play-state: paused;
}
.audio-playlist-container .disc::after {
    content: "♪";
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    color: #fff;
    font-size: 28px;
    text-shadow: 0 0 10px rgba(255,255,255,0.3);
}
.audio-playlist-container .disc.playing { animation-play-state: running; }
@keyframes apc-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
/* 唱针 */
.audio-playlist-container .needle {
    position: absolute;
    top: -10px; right: 10px;
    width: 60px; height: 90px;
    z-index: 3;
    transform-origin: top right;
    transform: rotate(-25deg);
    transition: transform 0.4s;
}
.audio-playlist-container .needle.playing { transform: rotate(-5deg); }
.audio-playlist-container .needle::before {
    content: "";
    position: absolute;
    top: 0; right: 0;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: #666;
    border: 2px solid #888;
}
.audio-playlist-container .needle::after {
    content: "";
    position: absolute;
    top: 8px; right: 6px;
    width: 3px; height: 75px;
    background: linear-gradient(to bottom, #999, #ccc 30%, #555 100%);
    border-radius: 2px;
    transform: rotate(15deg);
    transform-origin: top;
}

/* 音频波形 */
.audio-playlist-container .waveform {
    display: flex;
    align-items: center;
    gap: 3px;
    height: 32px;
    margin-top: 18px;
    z-index: 2;
}
.audio-playlist-container .waveform span {
    display: block;
    width: 4px;
    background: linear-gradient(to top, #c0392b, #e74c3c);
    border-radius: 2px;
    height: 6px;
    transition: height 0.15s;
}
.audio-playlist-container .waveform.playing span {
    animation: apc-wave 1s ease-in-out infinite;
}
.audio-playlist-container .waveform span:nth-child(1) { animation-delay: 0s; }
.audio-playlist-container .waveform span:nth-child(2) { animation-delay: 0.1s; }
.audio-playlist-container .waveform span:nth-child(3) { animation-delay: 0.2s; }
.audio-playlist-container .waveform span:nth-child(4) { animation-delay: 0.3s; }
.audio-playlist-container .waveform span:nth-child(5) { animation-delay: 0.4s; }
.audio-playlist-container .waveform span:nth-child(6) { animation-delay: 0.3s; }
.audio-playlist-container .waveform span:nth-child(7) { animation-delay: 0.2s; }
.audio-playlist-container .waveform span:nth-child(8) { animation-delay: 0.1s; }
.audio-playlist-container .waveform span:nth-child(9) { animation-delay: 0s; }
@keyframes apc-wave {
    0%, 100% { height: 6px; }
    50%      { height: 28px; }
}

/* audio 元素 */
.audio-playlist-container .audio-main audio {
    width: 100%;
    margin-top: 18px;
    z-index: 2;
    outline: none;
}
.audio-playlist-container .audio-main audio::-webkit-media-controls-panel {
    background-color: #2a2a2a;
}

/* ===== 控制栏 ===== */
.audio-playlist-container .audio-controls-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 15px;
    background: #222;
    color: #fff;
    flex-wrap: wrap;
    gap: 8px;
}
.audio-playlist-container .control-group {
    display: flex;
    gap: 10px;
    align-items: center;
}
.audio-playlist-container .ctrl-btn {
    background: #444;
    border: none;
    color: #fff;
    padding: 6px 12px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 12px;
    font-family: inherit;
    transition: background 0.2s;
    line-height: 1.4;
}
.audio-playlist-container .ctrl-btn:hover { background: #666; }
.audio-playlist-container .ctrl-btn.active { background: #e74c3c; }

/* ===== 播放列表 ===== */
.audio-playlist-container .playlist {
    max-height: 500px;
    overflow-y: auto;
    background: #1a1a1a;
}
/* 局部滚动条 —— 只改播放器内部列表,不影响论坛页面滚动条 */
.audio-playlist-container .playlist::-webkit-scrollbar { width: 6px; }
.audio-playlist-container .playlist::-webkit-scrollbar-track { background: #1a1a1a; }
.audio-playlist-container .playlist::-webkit-scrollbar-thumb { background: #555; border-radius: 3px; }

.audio-playlist-container .playlist-item {
    display: flex;
    align-items: center;
    padding: 12px 15px;
    border-bottom: 1px solid #333;
    cursor: pointer;
    transition: all 0.2s;
    color: #ccc;
}
.audio-playlist-container .playlist-item:hover { background: #2a2a2a; }
.audio-playlist-container .playlist-item.playing {
    background: linear-gradient(90deg, #c0392b 0%, #e74c3c 100%);
    color: #fff;
}
.audio-playlist-container .playlist-item.played { opacity: 0.6; }
.audio-playlist-container .item-index {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: #333;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    margin-right: 12px;
    flex-shrink: 0;
}
.audio-playlist-container .playlist-item.playing .item-index {
    background: #fff;
    color: #e74c3c;
}
.audio-playlist-container .item-info { flex: 1; min-width: 0; }
.audio-playlist-container .item-title {
    font-size: 14px;
    margin-bottom: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.audio-playlist-container .item-duration {
    font-size: 11px;
    opacity: 0.7;
}
.audio-playlist-container .playing-indicator {
    margin-left: 10px;
    font-size: 12px;
    flex-shrink: 0;
}

@media (max-width: 600px) {
    .audio-playlist-container .audio-title { font-size: 14px; }
    .audio-playlist-container .playlist-item { padding: 10px; }
    .audio-playlist-container .disc-wrap { width: 140px; height: 140px; margin-top: 30px; }
    .audio-playlist-container .audio-main { min-height: 260px; padding-top: 40px; }
    .audio-playlist-container .ctrl-btn { padding: 6px 10px; font-size: 12px; }
}
</style>

<div class="audio-playlist-container">
    <div class="audio-main">
      <div class="audio-info-bar">
            <div class="audio-title" id="audioTitle">个人收藏的单曲合集</div>
            <div class="audio-index" id="audioIndex">第 1 首 / 共 N 首</div>
      </div>

      <div class="disc-wrap">
            <div class="needle" id="needle"></div>
            <div class="disc" id="disc"></div>
      </div>

      <div class="waveform" id="waveform">
            <span></span><span></span><span></span><span></span><span></span>
            <span></span><span></span><span></span><span></span>
      </div>

      <audio id="mainAudio" controls preload="metadata" playsinline webkit-playsinline>
            您的浏览器不支持HTML5音频播放,请升级浏览器。
      </audio>
    </div>

    <div class="audio-controls-bar">
      <div class="control-group">
            <button class="ctrl-btn" onclick="prevAudio()">⏮ 上一首</button>
            <button class="ctrl-btn" onclick="nextAudio()">下一首 ⏭</button>
      </div>
      <div class="control-group">
            <button class="ctrl-btn active" id="autoPlayBtn" onclick="toggleAutoPlay()">🔁 连播: 开</button>
            <button class="ctrl-btn" id="loopBtn" onclick="toggleLoop()">🔂 循环: 关</button>
      </div>
    </div>

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

<script type="text/javascript">
// ======== 音频列表配置(替换为你自己的音频地址)========
var audioList = [
    {
      title: "第一首:笑纳 - 花僮",
      url: "https://www.joy127.com/url/158119.mp3",
      duration: ""
    },
    {
      title: "第二首:浪子闲话 - 花僮",
      url: "https://www.joy127.com/url/158118.mp3",
      duration: ""
    },
    {
      title: "第三首:秒针 - 阿梨粤",
      url: "https://www.joy127.com/url/158117.mp3",
      duration: ""
    },
    {
      title: "第四首:精忠报国 - 屠龙刚",
      url: "https://www.joy127.com/url/158116.mp3",
      duration: ""
    },
    {
      title: "第五首:赤伶 - 谭晶",
      url: "https://www.joy127.com/url/158115.mp3",
      duration: ""
    },
    {
      title: "第六首:客官不可以 - 麦小兜",
      url: "https://www.joy127.com/url/158114.mp3",
      duration: ""
    },
    {
      title: "第七首:小道童 - 麦小兜",
      url: "https://www.joy127.com/url/158113.mp3",
      duration: ""
    },
    {
      title: "第八首:情字最大 - 浅影阿",
      url: "https://www.joy127.com/url/158112.mp3",
      duration: ""
    },
    {
      title: "第九首:万疆 - 李玉刚",
      url: "https://www.joy127.com/url/158111.mp3",
      duration: ""
    },
    {
      title: "第十首:处处吻 - 杨千嬅",
      url: "https://www.joy127.com/url/158110.mp3",
      duration: ""
    },
    {
      title: "第十一首:声声慢 - 韩菁英(最美女声)",
      url: "https://www.joy127.com/url/158097.mp3",
      duration: ""
    },
    {
      title: "第十二首:声声慢 - 吴亮莹(吴侬软语)",
      url: "https://www.joy127.com/url/158096.mp3",
      duration: ""
    },
    {
      title: "第三首:音频标题写这里",
      url: "",
      duration: ""
    },
    // 按此格式继续添加更多音频即可
];
// ========================================================

(function(){
    var currentIndex = 0;
    var autoPlayNext = true;
    var loopAll = false;
    var audio = document.getElementById('mainAudio');
    var playlistEl = document.getElementById('playlist');
    var disc = document.getElementById('disc');
    var needle = document.getElementById('needle');
    var waveform = document.getElementById('waveform');

    function setPlayingVisual(isPlaying) {
      if (isPlaying) {
            disc.classList.add('playing');
            needle.classList.add('playing');
            waveform.classList.add('playing');
      } else {
            disc.classList.remove('playing');
            needle.classList.remove('playing');
            waveform.classList.remove('playing');
      }
    }

    function formatTime(sec) {
      if (!sec || isNaN(sec)) return '';
      var m = Math.floor(sec / 60);
      var s = Math.floor(sec % 60);
      return m + ':' + (s < 10 ? '0' + s : s);
    }

    function initPlaylist() {
      playlistEl.innerHTML = '';
      for (var i = 0; i < audioList.length; i++) {
            var item = document.createElement('div');
            item.className = 'playlist-item' + (i === 0 ? ' playing' : '');
            item.setAttribute('data-index', i);
            item.innerHTML =
                '<div class="item-index">' + (i + 1) + '</div>' +
                '<div class="item-info">' +
                  '<div class="item-title">' + audioList.title + '</div>' +
                  '<div class="item-duration" data-dur-idx="' + i + '">' + (audioList.duration || '--:--') + '</div>' +
                '</div>' +
                '<div class="playing-indicator">' + (i === 0 ? '▶ 播放中' : '') + '</div>';
            item.onclick = (function(idx) {
                return function() { playAudio(idx); };
            })(i);
            playlistEl.appendChild(item);
      }
    }

    function updatePlaylistUI() {
      var items = playlistEl.querySelectorAll('.playlist-item');
      for (var i = 0; i < items.length; i++) {
            items.className = 'playlist-item';
            var indicator = items.querySelector('.playing-indicator');
            indicator.textContent = '';
            if (i < currentIndex) items.className += ' played';
            if (i === currentIndex) {
                items.className += ' playing';
                indicator.textContent = '▶ 播放中';
            }
      }
    }

    function playAudio(index) {
      if (index < 0) index = loopAll ? audioList.length - 1 : 0;
      if (index >= audioList.length) index = loopAll ? 0 : audioList.length - 1;
      currentIndex = index;
      var item = audioList;
      audio.src = item.url;
      audio.load();
      audio.play().then(function() {
            setPlayingVisual(true);
      }).catch(function(e) {
            setPlayingVisual(false);
      });
      document.getElementById('audioTitle').textContent = item.title;
      document.getElementById('audioIndex').textContent = '第 ' + (index + 1) + ' 首 / 共 ' + audioList.length + ' 首';
      updatePlaylistUI();
    }

    window.nextAudio = function() {
      if (currentIndex < audioList.length - 1) playAudio(currentIndex + 1);
      else if (loopAll) playAudio(0);
    };
    window.prevAudio = function() {
      if (currentIndex > 0) playAudio(currentIndex - 1);
      else if (loopAll) playAudio(audioList.length - 1);
    };
    window.toggleAutoPlay = function() {
      autoPlayNext = !autoPlayNext;
      var btn = document.getElementById('autoPlayBtn');
      btn.textContent = autoPlayNext ? '🔁 连播: 开' : '🔁 连播: 关';
      btn.className = 'ctrl-btn' + (autoPlayNext ? ' active' : '');
    };
    window.toggleLoop = function() {
      loopAll = !loopAll;
      var btn = document.getElementById('loopBtn');
      btn.textContent = loopAll ? '🔂 循环: 开' : '🔂 循环: 关';
      btn.className = 'ctrl-btn' + (loopAll ? ' active' : '');
    };

    audio.addEventListener('play', function() { setPlayingVisual(true); });
    audio.addEventListener('pause', function() { setPlayingVisual(false); });
    audio.addEventListener('ended', function() {
      setPlayingVisual(false);
      if (autoPlayNext) {
            if (currentIndex < audioList.length - 1) nextAudio();
            else if (loopAll) playAudio(0);
      }
    });
    audio.addEventListener('loadedmetadata', function() {
      var durEl = playlistEl.querySelector('');
      if (durEl && (!audioList.duration)) {
            var t = formatTime(audio.duration);
            durEl.textContent = t;
            audioList.duration = t;
      }
    });

    initPlaylist();
    playAudio(0);
})();
</script>

风萧 发表于 2026-8-28 06:29:09

不带歌词版的单曲播发器
<!--
Discuz 论坛发帖专用 - 现代化玻璃拟态音乐播放器
使用说明:
1. 复制以下所有代码。
2. 在 Discuz 发帖编辑器中切换到“纯文本/HTML源码”模式。
3. 替换 src 中的音频链接和 img 中的封面链接。
4. 确保论坛权限允许发布 HTML 代码。
-->

<div style="
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
width: 320px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 20px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
color: white;
margin: 20px auto;
position: relative;
overflow: hidden;
text-align: center;
">

<!-- 背景装饰光斑 -->
<div style="
    position: absolute;
    top: -50%;
    left: -50%;
    width: 200%;
    height: 200%;
    background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 60%);
    pointer-events: none;
    z-index: 0;
"></div>

<!-- 内容区域 -->
<div style="position: relative; z-index: 1;">
   
    <!-- 唱片封面容器 -->
    <div style="
      width: 180px;
      height: 180px;
      margin: 0 auto 20px;
      border-radius: 50%;
      border: 4px solid rgba(255,255,255,0.2);
      box-shadow: 0 8px 20px rgba(0,0,0,0.3);
      overflow: hidden;
      position: relative;
      animation: rotate-disc 10s linear infinite;
      /* 默认暂停动画,播放时通过JS添加 class 或手动控制较难,这里使用CSS常转模拟黑胶效果,
         若需精确控制播放暂停动画,需JS支持,但Discuz限制JS,故采用视觉常驻旋转或静态美图为宜。
         此处为了美观,设为缓慢旋转,若介意可删除 animation 属性 -->
      animation-play-state: paused;
    " id="disc-cover">
      <!-- 封面图片:请替换下面的 src -->
      <img src="https://i.ibb.co/nN5s9FYn/CG.jpg" alt="音乐封面" style="
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
      ">
      <!-- 中心圆点 -->
      <div style="
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 30px;
      height: 30px;
      background: #2d3436;
      border-radius: 50%;
      border: 2px solid rgba(255,255,255,0.5);
      "></div>
    </div>

    <!-- 歌曲信息 -->
    <h3 style="
      margin: 0 0 5px;
      font-size: 18px;
      font-weight: 600;
      text-shadow: 0 2px 4px rgba(0,0,0,0.2);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    ">Simpa Pa Pa</h3>
    <p style="
      margin: 0 0 20px;
      font-size: 14px;
      opacity: 0.8;
      font-weight: 300;
    ">Yefium </p>

    <!-- 自定义控制按钮区域 (视觉层) -->
    <div style="
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 20px;
      margin-bottom: 15px;
    ">
      <!-- 播放/暂停按钮视觉提示 (实际功能由下方 audio controls 提供,此处仅为美化引导) -->
      <div style="
      font-size: 12px;
      opacity: 0.6;
      background: rgba(0,0,0,0.2);
      padding: 4px 10px;
      border-radius: 12px;
      ">点击下方原生控件播放</div>
    </div>

    <!-- 核心音频标签 -->
    <!--
      controls: 显示浏览器原生控件(最稳定兼容 Discuz)
      preload: 预加载元数据
      注意:为了保持 UI 统一,我们可以尝试隐藏原生控件的大部分内容,只保留进度条,
      但在不同浏览器下表现不一。最稳妥的“好看”方式是保留原生控件,但通过 CSS 美化容器。
      
      进阶技巧:如果 Discuz 允许少量 JS,可以添加 onclick 事件控制播放并旋转封面。
      下面代码包含一段简单的内联 JS 尝试控制封面旋转(视论坛过滤规则而定,若被过滤则仅作为静态播放器)。
    -->
    <audio id="my-audio" controls autoplay loop preload="metadata" style="
      width: 100%;
      height: 40px;
      outline: none;
      filter: invert(1) hue-rotate(180deg); /* 简单反转颜色以适配深色背景,视浏览器支持情况 */
      border-radius: 20px;
      background: rgba(255,255,255,0.1);
    "
    onplay="document.getElementById('disc-cover').style.animationPlayState='running'"
    onpause="document.getElementById('disc-cover').style.animationPlayState='paused'"
    >
      <!-- 请替换为你的音频文件直链 -->
      <source src="https://www.joy127.com/url/158258.mp3" type="audio/mpeg">
      您的浏览器不支持 audio 元素。
    </audio>

</div>

<!-- 内部样式定义 (部分论坛可能过滤 style 标签,若被过滤,以上内联样式已足够) -->
<style>
    @keyframes rotate-disc {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }
    /* 针对 Webkit 浏览器的音频控件微调 */
    audio::-webkit-media-controls-panel {
      background-color: rgba(255, 255, 255, 0.2);
    }
    audio::-webkit-media-controls-current-time-display,
    audio::-webkit-media-controls-time-remaining-display {
      color: white;
    }
</style>
</div>

风萧 发表于 2026-8-28 19:30:19

B站多视频列表播放器
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>B站多视频播放器</title>
    <style>
      /* 全局样式重置与基础设定 */
      .bili-player-container {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            max-width: 800px;
            margin: 20px auto;
            background-color: #f4f5f7;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
            overflow: hidden;
            border: 1px solid #e3e5e7;
      }

      /* 视频显示区域 */
      .video-stage {
            position: relative;
            width: 100%;
            padding-bottom: 56.25%; /* 16:9 比例 */
            background-color: #000;
            height: 0;
      }

      .video-stage iframe {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border: none;
      }

      /* 播放列表区域 */
      .playlist-area {
            padding: 15px;
            background-color: #fff;
      }

      .playlist-header {
            font-size: 16px;
            font-weight: bold;
            color: #333;
            margin-bottom: 10px;
            padding-bottom: 10px;
            border-bottom: 1px solid #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
      }

      .playlist-count {
            font-size: 12px;
            color: #999;
            font-weight: normal;
      }

      /* 列表容器 */
      .video-list {
            list-style: none;
            padding: 0;
            margin: 0;
            max-height: 300px;
            overflow-y: auto;
      }

      /* 滚动条样式优化 */
      .video-list::-webkit-scrollbar {
            width: 6px;
      }
      .video-list::-webkit-scrollbar-thumb {
            background-color: #ccc;
            border-radius: 3px;
      }

      /* 单个视频项 */
      .video-item {
            display: flex;
            align-items: center;
            padding: 10px;
            cursor: pointer;
            transition: background-color 0.2s ease;
            border-radius: 4px;
            margin-bottom: 5px;
      }

      .video-item:hover {
            background-color: #f0f2f5;
      }

      .video-item.active {
            background-color: #e7f0ff;
            border-left: 4px solid #00a1d6;
      }

      .video-item.active .video-title {
            color: #00a1d6;
            font-weight: 600;
      }

      /* 序号 */
      .item-index {
            width: 24px;
            height: 24px;
            background-color: #999;
            color: #fff;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            margin-right: 10px;
            flex-shrink: 0;
      }

      .video-item.active .item-index {
            background-color: #00a1d6;
      }

      /* 标题 */
      .video-title {
            font-size: 14px;
            color: #333;
            line-height: 1.4;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            flex-grow: 1;
      }

      /* 提示信息 */
      .tips {
            font-size: 12px;
            color: #999;
            margin-top: 10px;
            text-align: right;
      }
    </style>
</head>
<body>

<div class="bili-player-container">
    <!-- 视频播放舞台 -->
    <div class="video-stage">
      <iframe id="mainPlayer" src="" allowfullscreen="true" allow="autoplay; encrypted-media"></iframe>
    </div>

    <!-- 播放列表 -->
    <div class="playlist-area">
      <div class="playlist-header">
            <span>精选视频列表</span>
            <span class="playlist-count" id="videoCount">共 0 个视频</span>
      </div>
      <ul class="video-list" id="videoList">
            <!-- 列表项将通过 JS 动态生成 -->
      </ul>
      <div class="tips">点击列表即可切换视频</div>
    </div>
</div>

<script>
    (function() {
      // ================= 配置区域 =================
      // 请在此处修改您的 B站视频 BV 号或 AV 号以及标题
      // bvid: B站视频的 BV 号 (推荐)
      // title: 显示在列表中的标题
      const videoData = [
            {
                bvid: "BV1GJ411x7h7",
                title: "示例视频1:B站首页宣传片"
            },
            {
                bvid: "BV1xx411c7mD",
                title: "示例视频2:如何制作高质量视频"
            },
            {
                bvid: "BV1Ft411k7P6",
                title: "示例视频3:Discuz论坛使用教程"
            },
            {
                bvid: "BV1Kb411W75N",
                title: "示例视频4:Web前端开发基础"
            }
      ];
      // ===========================================

      const playerIframe = document.getElementById('mainPlayer');
      const listContainer = document.getElementById('videoList');
      const countLabel = document.getElementById('videoCount');
      let currentIndex = 0;

      // 初始化播放器
      function initPlayer() {
            if (!videoData || videoData.length === 0) {
                listContainer.innerHTML = '<li style="padding:10px;color:#999;text-align:center;">暂无视频数据</li>';
                return;
            }

            countLabel.textContent = `共 ${videoData.length} 个视频`;
            renderList();
            loadVideo(0);
      }

      // 渲染列表
      function renderList() {
            listContainer.innerHTML = '';
            videoData.forEach((video, index) => {
                const li = document.createElement('li');
                li.className = 'video-item';
                li.dataset.index = index;
               
                // 构建 HTML 结构
                li.innerHTML = `
                  <div class="item-index">${index + 1}</div>
                  <div class="video-title" title="${video.title}">${video.title}</div>
                `;

                // 点击事件
                li.addEventListener('click', function() {
                  loadVideo(index);
                });

                listContainer.appendChild(li);
            });
      }

      // 加载指定索引的视频
      function loadVideo(index) {
            if (index < 0 || index >= videoData.length) return;

            currentIndex = index;
            const video = videoData;
            
            // 更新 iframe 源地址
            // 使用 B站嵌入式播放器地址
            playerIframe.src = `//player.bilibili.com/player.html?bvid=${video.bvid}&page=1&high_quality=1&danmaku=0`;

            // 更新列表激活状态
            const items = listContainer.querySelectorAll('.video-item');
            items.forEach((item, i) => {
                if (i === index) {
                  item.classList.add('active');
                  // 确保激活项在可视区域
                  item.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                } else {
                  item.classList.remove('active');
                }
            });
      }

      // 启动
      initPlayer();
    })();
</script>

</body>
</html>

风萧 发表于 2026-8-29 19:23:47

支持m3u8格式的多视频选集播放器代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Discuz M3U8 分集播放器</title>
    <!-- 引入 TailwindCSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <script>
      tailwind.config = {
      corePlugins: {
      preflight: false, // 关闭Tailwind的全局重置样式,避免覆盖Discuz原有页面样式
                     }
      }
    </script>
    <!-- 引入 Font Awesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <!-- 引入 Hls.js -->
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest/dist/hls.min.js"></script>
    <style>
      /* 自定义滚动条样式 */
      .episode-scroll::-webkit-scrollbar {
            width: 6px;
            height: 6px;
      }
      .episode-scroll::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 3px;
      }
      .episode-scroll::-webkit-scrollbar-thumb {
            background: #cbd5e1;
            border-radius: 3px;
      }
      .episode-scroll::-webkit-scrollbar-thumb:hover {
            background: #94a3b8;
      }
      /* 选中状态动画 */
      .episode-btn.active {
            background-color: #3b82f6;
            color: white;
            border-color: #3b82f6;
      }
      /* 加载动画 */
      .loader {
            border: 3px solid #f3f3f3;
            border-radius: 50%;
            border-top: 3px solid #3b82f6;
            width: 24px;
            height: 24px;
            -webkit-animation: spin 1s linear infinite; /* Safari */
            animation: spin 1s linear infinite;
      }
      @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
      }
    </style>
</head>
<body class="bg-gray-100 p-4 font-sans">

    <!-- 播放器容器 -->
    <div id="dz-video-player-container" class="max-w-4xl mx-auto bg-white rounded-xl shadow-lg overflow-hidden border border-gray-200" style="isolation: isolate;">
      
      <!-- 视频区域 -->
      <div class="relative w-full aspect-video bg-black group">
            <video id="dz-video-element" class="w-full h-full object-contain" controls playsinline poster="/data/attachment/album/202608/31/200711vfnhzq7opn8dqp00.jpg"></video>
            
            <!-- 加载指示器 -->
            <div id="dz-loading-indicator" class="absolute inset-0 flex items-center justify-center bg-black/50 hidden z-10">
                <div class="loader"></div>
            </div>

            <!-- 错误提示层 -->
            <div id="dz-error-overlay" class="absolute inset-0 flex flex-col items-center justify-center bg-black/80 text-white hidden z-20">
                <i class="fas fa-exclamation-triangle text-4xl mb-2 text-red-500"></i>
                <p class="text-sm">视频加载失败,请检查网络或链接有效性</p>
                <button onclick="retryLoad()" class="mt-4 px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded text-sm transition">重试</button>
            </div>
      </div>

      <!-- 控制面板:标题与分集 -->
      <div class="p-4 bg-white">
            <div class="flex justify-between items-center mb-4 border-b pb-2">
                <h2 id="dz-video-title" class="text-lg font-bold text-gray-800 truncate pr-4">正在播放:第 1 集</h2>
                <!-- div class="text-xs text-gray-500 flex items-center gap-2">
                  <span id="dz-quality-badge" class="px-2 py-1 bg-gray-100 rounded text-gray-600">HD</span>
                  <span id="dz-duration">00:00</span>
                </div -->
            </div>

            <!-- 分集列表 -->
            <div class="mb-2 flex justify-between items-center">
                <span class="text-sm font-semibold text-gray-700"><i class="fas fa-list-ul mr-1"></i> 选集</span>
                <div class="flex gap-2">
                     <button onclick="toggleOrder()" class="text-xs text-blue-600 hover:text-blue-800 flex items-center gap-1">
                        <i class="fas fa-sort-amount-down" id="sort-icon"></i> <span id="sort-text">倒序</span>
                  </button>
                </div>
            </div>
            
            <div id="dz-episode-list" class="grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2 max-h-40 overflow-y-auto episode-scroll p-1">
                <!-- 分集按钮将通过 JS 动态生成 -->
            </div>
      </div>
    </div>

    <script>
      /**
         * Discuz M3U8 Player Configuration
         * 在 Discuz 发帖时,只需修改此处的 videoData 数组即可
         */
      const videoData = [
            { title: "HD国语版", url: "https://yzzy21.playback-speed.com/20240410/29373_4da7f681/index.m3u8" }
      ];

      // 全局变量
      let hls = null;
      let currentEpisodeIndex = 0;
      let isReversed = false;
      let displayedData = [...videoData];
      const videoElement = document.getElementById('dz-video-element');
      const episodeListContainer = document.getElementById('dz-episode-list');
      const loadingIndicator = document.getElementById('dz-loading-indicator');
      const errorOverlay = document.getElementById('dz-error-overlay');
      const titleElement = document.getElementById('dz-video-title');
      const durationElement = document.getElementById('dz-duration');

      /**
         * 初始化播放器
         */
      function initPlayer() {
            renderEpisodes();
            loadEpisode(0); // 默认加载第一集
            
            // 监听视频元数据加载完成,更新时长显示
            videoElement.addEventListener('loadedmetadata', () => {
                durationElement.innerText = formatTime(videoElement.duration);
            });

            // 监听播放结束,自动下一集
            videoElement.addEventListener('ended', () => {
                playNext();
            });
      }

      /**
         * 渲染分集列表
         */
      function renderEpisodes() {
            episodeListContainer.innerHTML = '';
            displayedData.forEach((item, index) => {
                // 找到原始数据中的真实索引,用于点击事件
                const originalIndex = videoData.indexOf(item);
               
                const btn = document.createElement('button');
                btn.className = `episode-btn px-3 py-2 text-xs font-medium rounded border border-gray-200 text-gray-700 hover:bg-blue-50 hover:border-blue-200 transition-all truncate ${originalIndex === currentEpisodeIndex ? 'active' : ''}`;
                btn.innerText = item.title;
                btn.onclick = () => loadEpisode(originalIndex);
                episodeListContainer.appendChild(btn);
            });
      }

      /**
         * 加载指定集数
         * @param {number} index - 原始数据数组中的索引
         */
      function loadEpisode(index) {
            if (index < 0 || index >= videoData.length) return;

            currentEpisodeIndex = index;
            const data = videoData;
            
            // 更新UI状态
            updateActiveButton();
            titleElement.innerText = `正在播放:${data.title}`;
            showLoading(true);
            hideError();

            // 销毁旧的 HLS 实例
            if (hls) {
                hls.destroy();
            }

            // 创建新的 HLS 实例
            if (Hls.isSupported()) {
                hls = new Hls({
                  debug: false,
                  enableWorker: true,
                  lowLatencyMode: true,
                  backBufferLength: 90
                });

                hls.loadSource(data.url);
                hls.attachMedia(videoElement);

                hls.on(Hls.Events.MANIFEST_PARSED, function() {
                  videoElement.play().catch(e => console.log("Auto-play prevented:", e));
                  showLoading(false);
                });

                hls.on(Hls.Events.ERROR, function(event, data) {
                  if (data.fatal) {
                        switch(data.type) {
                            case Hls.ErrorTypes.NETWORK_ERROR:
                              console.log("fatal network error encountered, try to recover");
                              hls.startLoad();
                              break;
                            case Hls.ErrorTypes.MEDIA_ERROR:
                              console.log("fatal media error encountered, try to recover");
                              hls.recoverMediaError();
                              break;
                            default:
                              showError();
                              hls.destroy();
                              break;
                        }
                  }
                });

            } else if (videoElement.canPlayType('application/vnd.apple.mpegurl')) {
                // Safari 原生支持
                videoElement.src = data.url;
                videoElement.addEventListener('loadedmetadata', function() {
                  videoElement.play();
                  showLoading(false);
                });
            } else {
                showError();
            }
      }

      /**
         * 更新按钮激活状态
         */
      function updateActiveButton() {
            const buttons = episodeListContainer.querySelectorAll('.episode-btn');
            buttons.forEach((btn, idx) => {
                // 注意:displayedData 可能是反转的,所以需要比对内容或重新映射
                // 这里简单起见,我们重新渲染或者通过文本匹配,但更优解是重新渲染
                // 为了性能,我们直接重新渲染整个列表是最安全的,因为列表通常不长
                renderEpisodes();
            });
      }

      /**
         * 播放下一集
         */
      function playNext() {
            if (currentEpisodeIndex < videoData.length - 1) {
                loadEpisode(currentEpisodeIndex + 1);
                // 滚动到当前选中的按钮
                setTimeout(() => {
                  const activeBtn = document.querySelector('.episode-btn.active');
                  if(activeBtn) activeBtn.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                }, 100);
            }
      }

      /**
         * 切换排序(正序/倒序)
         */
      function toggleOrder() {
            isReversed = !isReversed;
            const sortIcon = document.getElementById('sort-icon');
            const sortText = document.getElementById('sort-text');
            
            if (isReversed) {
                displayedData = [...videoData].reverse();
                sortIcon.className = "fas fa-sort-amount-up";
                sortText.innerText = "正序";
            } else {
                displayedData = [...videoData];
                sortIcon.className = "fas fa-sort-amount-down";
                sortText.innerText = "倒序";
            }
            renderEpisodes();
      }

      /**
         * 重试加载
         */
      function retryLoad() {
            loadEpisode(currentEpisodeIndex);
      }

      /**
         * UI 辅助函数
         */
      function showLoading(show) {
            loadingIndicator.classList.toggle('hidden', !show);
      }

      function showError() {
            errorOverlay.classList.remove('hidden');
            showLoading(false);
      }

      function hideError() {
            errorOverlay.classList.add('hidden');
      }

      function formatTime(seconds) {
            if (isNaN(seconds)) return "00:00";
            const m = Math.floor(seconds / 60);
            const s = Math.floor(seconds % 60);
            return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
      }

      // 启动
      document.addEventListener('DOMContentLoaded', initPlayer);

    </script>
</body>
</html>
页: 1 [2]
查看完整版本: 论坛发帖可以使用的HTML代码