吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1421|回复: 57
收起左侧

[学习记录] AI生成的本地多媒体播放器HTML

  [复制链接]
lcg888 发表于 2025-4-18 11:24

[Asm] 纯文本查看 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI生成本地多媒体播放器</title>
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
    <style>
        :root {
            --primary: #6366f1;
            --primary-light: #818cf8;
            --secondary: #10b981;
            --dark: #1e293b;
            --light: #f8fafc;
            --gray: #94a3b8;
            --glass: rgba(255, 255, 255, 0.15);
            --shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
            --border-radius: 12px;
            --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
            background: linear-gradient(135deg, #f5f7fa 0%, #e4e7eb 100%);
            color: var(--dark);
            min-height: 100vh;
            padding: 2rem;
            line-height: 1.6;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        header {
            text-align: center;
            margin-bottom: 3rem;
            opacity: 0;
            transform: translateY(20px);
            animation: fadeIn 0.6s forwards 0.1s;
        }

        h1 {
            font-size: 2.5rem;
            font-weight: 700;
            background: linear-gradient(to right, var(--primary), var(--secondary));
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
            margin-bottom: 0.5rem;
        }

        .subtitle {
            color: var(--gray);
            font-size: 1.1rem;
            max-width: 600px;
            margin: 0 auto;
        }

        .card {
            background: rgba(255, 255, 255, 0.8);
            backdrop-filter: blur(12px);
            -webkit-backdrop-filter: blur(12px);
            border-radius: var(--border-radius);
            box-shadow: var(--shadow);
            padding: 2rem;
            margin-bottom: 2rem;
            transition: var(--transition);
            opacity: 0;
            transform: translateY(30px);
            animation: fadeInUp 0.6s forwards;
        }

        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 15px 30px rgba(0, 0, 0, 0.12);
        }

        .card:nth-child(1) { animation-delay: 0.2s; }
        .card:nth-child(2) { animation-delay: 0.3s; }
        .card:nth-child(3) { animation-delay: 0.4s; }

        .section-title {
            display: flex;
            align-items: center;
            margin-bottom: 1.5rem;
            color: var(--primary);
        }

        .section-title svg {
            margin-right: 0.75rem;
            width: 24px;
            height: 24px;
        }

        .input-group {
            display: flex;
            gap: 1rem;
            margin-bottom: 1.5rem;
        }

        .input-field {
            flex: 1;
            padding: 0.75rem 1rem;
            border: 1px solid rgba(0, 0, 0, 0.1);
            border-radius: var(--border-radius);
            font-size: 1rem;
            transition: var(--transition);
            background: rgba(255, 255, 255, 0.7);
        }

        .input-field:focus {
            outline: none;
            border-color: var(--primary);
            box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
        }

        .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            padding: 0.75rem 1.5rem;
            border-radius: var(--border-radius);
            font-size: 1rem;
            font-weight: 500;
            cursor: pointer;
            transition: var(--transition);
            border: none;
            white-space: nowrap;
        }

        .btn-primary {
            background: var(--primary);
            color: white;
        }

        .btn-primary:hover {
            background: var(--primary-light);
            transform: translateY(-2px);
        }

        .btn-secondary {
            background: var(--secondary);
            color: white;
        }

        .btn-secondary:hover {
            background: #0ea472;
            transform: translateY(-2px);
        }

        .btn-icon {
            margin-right: 0.5rem;
        }

        .file-input {
            display: none;
        }

        .media-container {
            width: 100%;
            margin-top: 1.5rem;
            border-radius: var(--border-radius);
            overflow: hidden;
            background: #000;
            position: relative;
            display: none;
        }

        video, audio {
            width: 100%;
            outline: none;
        }

        .image-preview {
            max-width: 100%;
            max-height: 60vh;
            display: block;
            margin: 1.5rem auto 0;
            border-radius: var(--border-radius);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
            cursor: zoom-in;
            transition: var(--transition);
            display: none;
        }

        .image-preview:hover {
            transform: scale(1.02);
        }

        .status {
            padding: 1rem;
            border-radius: var(--border-radius);
            margin-top: 1rem;
            display: none;
        }

        .status-success {
            background: rgba(16, 185, 129, 0.1);
            color: var(--secondary);
            display: block;
        }

        .status-error {
            background: rgba(239, 68, 68, 0.1);
            color: #ef4444;
            display: block;
        }

        .formats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
            gap: 1.5rem;
            margin-top: 1.5rem;
        }

        .format-card {
            background: white;
            border-radius: var(--border-radius);
            padding: 1.5rem;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
            transition: var(--transition);
        }

        .format-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
        }

        .format-title {
            font-weight: 600;
            margin-bottom: 1rem;
            color: var(--dark);
            display: flex;
            align-items: center;
        }

        .format-title svg {
            margin-right: 0.5rem;
            color: var(--primary);
        }

        .format-list {
            list-style: none;
        }

        .format-item {
            margin-bottom: 0.5rem;
            display: flex;
            align-items: center;
        }

        .format-item svg {
            margin-right: 0.5rem;
        }

        .supported {
            color: var(--secondary);
        }

        .unsupported {
            color: #ef4444;
        }

        /* Image viewer modal */
        .image-viewer {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.9);
            display: none;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            cursor: zoom-out;
        }

        .viewer-image {
            max-width: 90%;
            max-height: 90%;
            transition: transform 0.3s ease;
        }

        .viewer-controls {
            position: absolute;
            bottom: 2rem;
            left: 50%;
            transform: translateX(-50%);
            display: flex;
            gap: 0.75rem;
            background: rgba(0, 0, 0, 0.7);
            padding: 0.75rem;
            border-radius: 2rem;
        }

        .control-btn {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            background: rgba(255, 255, 255, 0.1);
            color: white;
            border: none;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            transition: var(--transition);
        }

        .control-btn:hover {
            background: rgba(255, 255, 255, 0.2);
            transform: scale(1.1);
        }

        footer {
            text-align: center;
            margin-top: 3rem;
            color: var(--gray);
            font-size: 0.9rem;
        }

        /* Animations */
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }

        @keyframes fadeInUp {
            from { opacity: 0; transform: translateY(30px); }
            to { opacity: 1; transform: translateY(0); }
        }

        /* Responsive */
        [url=home.php?mod=space&uid=945662]@media[/url] (max-width: 768px) {
            body {
                padding: 1rem;
            }

            h1 {
                font-size: 2rem;
            }

            .input-group {
                flex-direction: column;
            }

            .formats-grid {
                grid-template-columns: 1fr;
            }
        }

        /* Icons */
        .icon {
            width: 1em;
            height: 1em;
            vertical-align: -0.125em;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>本地多媒体播放器</h1>
            <p class="subtitle">多媒体播放解决方案,支持视频、音频和图片格式</p>
        </header>

        <main>
            <div class="card">
                <h2 class="section-title">
                    <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                        <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 14H9V8h2v8zm4 0h-2V8h2v8z"/>
                    </svg>
                    媒体控制中心
                </h2>
                
                <div class="input-group">
                    <input type="text" class="input-field" id="media-url" placeholder="输入媒体URL (支持MP4, WebM, MP3, JPG等)">
                    <button class="btn btn-primary" id="play-btn">
                        <svg class="icon btn-icon" viewBox="0 0 24 24" fill="currentColor">
                            <path d="M8 5v14l11-7z"/>
                        </svg>
                        播放
                    </button>
                </div>
                
                <div class="input-group">
                    <button class="btn btn-secondary" id="file-btn">
                        <svg class="icon btn-icon" viewBox="0 0 24 24" fill="currentColor">
                            <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
                        </svg>
                        选择文件
                    </button>
                    <input type="file" class="file-input" id="file-input" accept="video/*,audio/*,image/*">
                </div>
                
                <div class="status" id="status-message"></div>
                
                <div class="media-container" id="video-player">
                    <video controls crossorigin="anonymous"></video>
                </div>
                
                <div class="media-container" id="audio-player">
                    <audio controls></audio>
                </div>
                
                <img class="image-preview" id="image-preview" alt="预览图片">
            </div>
            
            <div class="card">
                <h2 class="section-title">
                    <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                        <path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/>
                        <path d="M7 12h2v5H7zm4-7h2v12h-2zm4 5h2v7h-2z"/>
                    </svg>
                    支持的格式
                </h2>
                
                <div class="formats-grid">
                    <div class="format-card">
                        <h3 class="format-title">
                            <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                <path d="M10 8v8l5-4-5-4zm9-5H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/>
                            </svg>
                            视频格式
                        </h3>
                        <ul class="format-list">
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported" id="mp4-support">MP4 (H.264)</span>
                            </li>
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported" id="webm-support">WebM</span>
                            </li>
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported" id="ogg-support">Ogg Theora</span>
                            </li>
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported" id="hls-support">M3U8/HLS</span>
                            </li>
                        </ul>
                    </div>
                    
                    <div class="format-card">
                        <h3 class="format-title">
                            <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
                            </svg>
                            音频格式
                        </h3>
                        <ul class="format-list">
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported" id="mp3-support">MP3</span>
                            </li>
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported" id="wav-support">WAV</span>
                            </li>
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported" id="ogg-audio-support">Ogg Vorbis</span>
                            </li>
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported" id="aac-support">AAC</span>
                            </li>
                        </ul>
                    </div>
                    
                    <div class="format-card">
                        <h3 class="format-title">
                            <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                <path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4.86 8.86l-3 3.87L9 13.14 6 17h12l-3.86-5.14z"/>
                            </svg>
                            图片格式
                        </h3>
                        <ul class="format-list">
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported">JPG/JPEG</span>
                            </li>
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported">PNG</span>
                            </li>
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported">GIF</span>
                            </li>
                            <li class="format-item">
                                <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
                                </svg>
                                <span class="supported">WebP</span>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </main>

        <!-- Image Viewer Modal -->
        <div class="image-viewer" id="image-viewer">
            <img class="viewer-image" id="viewer-image" alt="全屏图片">
            <div class="viewer-controls">
                <button class="control-btn" id="zoom-in">
                    <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                        <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
                    </svg>
                </button>
                <button class="control-btn" id="zoom-out">
                    <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                        <path d="M19 13H5v-2h14v2z"/>
                    </svg>
                </button>
                <button class="control-btn" id="zoom-reset">
                    <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                        <path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/>
                    </svg>
                </button>
                <button class="control-btn" id="close-viewer">
                    <svg class="icon" viewBox="0 0 24 24" fill="currentColor">
                        <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
                    </svg>
                </button>
            </div>
        </div>

        <footer>
            <p>网页由AI仅供参考</p>
            <p>特此奉献给有需要的道友</p>
            <p><a href="https://www.52pojie.cn" target="_blank">www.52pojie.cn</a></p>
        </footer>
    </div>

    <script>
        // 全局变量
        let hls = null;
        let currentMediaType = null;
        let currentScale = 1;
        
        // DOM元素
        const fileInputBtn = document.getElementById('file-btn');
        const fileInput = document.getElementById('file-input');
        const playBtn = document.getElementById('play-btn');
        const mediaUrlInput = document.getElementById('media-url');
        const videoPlayer = document.getElementById('video-player');
        const videoElement = videoPlayer.querySelector('video');
        const audioPlayer = document.getElementById('audio-player');
        const audioElement = audioPlayer.querySelector('audio');
        const imagePreview = document.getElementById('image-preview');
        const imageViewer = document.getElementById('image-viewer');
        const viewerImage = document.getElementById('viewer-image');
        const zoomInBtn = document.getElementById('zoom-in');
        const zoomOutBtn = document.getElementById('zoom-out');
        const zoomResetBtn = document.getElementById('zoom-reset');
        const closeViewerBtn = document.getElementById('close-viewer');
        const statusMessage = document.getElementById('status-message');
        
        // 初始化播放器
        function initPlayer() {
            checkSupportedFormats();
            setupEventListeners();
        }
        
        // 检测浏览器支持的格式
        function checkSupportedFormats() {
            const video = document.createElement('video');
            const audio = document.createElement('audio');
            
            // 检测视频格式支持
            document.getElementById('mp4-support').className = video.canPlayType('video/mp4; codecs="avc1.42E01E"') ? 'supported' : 'unsupported';
            document.getElementById('webm-support').className = video.canPlayType('video/webm; codecs="vp8, vorbis"') ? 'supported' : 'unsupported';
            document.getElementById('ogg-support').className = video.canPlayType('video/ogg; codecs="theora, vorbis"') ? 'supported' : 'unsupported';
            
            // 检测音频格式支持
            document.getElementById('mp3-support').className = audio.canPlayType('audio/mpeg') ? 'supported' : 'unsupported';
            document.getElementById('wav-support').className = audio.canPlayType('audio/wav') ? 'supported' : 'unsupported';
            document.getElementById('ogg-audio-support').className = audio.canPlayType('audio/ogg; codecs="vorbis"') ? 'supported' : 'unsupported';
            document.getElementById('aac-support').className = audio.canPlayType('audio/aac') ? 'supported' : 'unsupported';
            
            // 检测HLS支持
            const hlsSupport = document.getElementById('hls-support');
            if (video.canPlayType('application/vnd.apple.mpegurl') || Hls.isSupported()) {
                hlsSupport.className = 'supported';
            } else {
                hlsSupport.className = 'unsupported';
            }
        }
        
        // 设置事件监听器
        function setupEventListeners() {
            // 文件选择按钮点击事件
            fileInputBtn.addEventListener('click', () => {
                fileInput.click();
            });
            
            // 文件输入变化事件
            fileInput.addEventListener('change', handleFileSelect);
            
            // 播放按钮点击事件
            playBtn.addEventListener('click', playFromUrl);
            
            // URL输入框回车事件
            mediaUrlInput.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') {
                    playFromUrl();
                }
            });
            
            // 图片点击事件 - 打开查看器
            imagePreview.addEventListener('click', openImageViewer);
            
            // 查看器控制按钮
            zoomInBtn.addEventListener('click', () => zoomImage(1.2));
            zoomOutBtn.addEventListener('click', () => zoomImage(0.8));
            zoomResetBtn.addEventListener('click', () => zoomImage(0));
            closeViewerBtn.addEventListener('click', closeImageViewer);
            
            // 键盘快捷键
            document.addEventListener('keydown', handleKeyDown);
            
            // 鼠标滚轮缩放
            imageViewer.addEventListener('wheel', handleWheel, { passive: false });
        }
        
        // 处理文件选择
        function handleFileSelect(event) {
            const file = event.target.files[0];
            if (!file) return;
            
            const fileUrl = URL.createObjectURL(file);
            loadMedia(fileUrl, file.type);
        }
        
        // 从URL播放
        function playFromUrl() {
            const url = mediaUrlInput.value.trim();
            if (!url) {
                showStatus('请输入有效的媒体URL', 'error');
                return;
            }
            
            // 检查是否是HLS流
            if (url.endsWith('.m3u8')) {
                loadHlsStream(url);
                return;
            }
            
            // 尝试确定媒体类型
            let mimeType = '';
            if (url.match(/\.(mp4|m4v|mov)$/i)) {
                mimeType = 'video/mp4';
            } else if (url.match(/\.webm$/i)) {
                mimeType = 'video/webm';
            } else if (url.match(/\.og[gv]$/i)) {
                mimeType = 'video/ogg';
            } else if (url.match(/\.(mp3)$/i)) {
                mimeType = 'audio/mpeg';
            } else if (url.match(/\.wav$/i)) {
                mimeType = 'audio/wav';
            } else if (url.match(/\.(ogg|oga)$/i)) {
                mimeType = 'audio/ogg';
            } else if (url.match(/\.(aac)$/i)) {
                mimeType = 'audio/aac';
            } else if (url.match(/\.(jpe?g|png|gif|bmp|webp)$/i)) {
                mimeType = 'image/' + url.split('.').pop().toLowerCase();
                if (mimeType === 'image/jpg') mimeType = 'image/jpeg';
            }
            
            loadMedia(url, mimeType);
        }
        
        // 加载媒体
        function loadMedia(url, mimeType) {
            // 清理之前的媒体
            resetPlayer();
            
            // 根据MIME类型确定媒体类型
            let mediaType;
            if (mimeType.startsWith('video/')) {
                mediaType = 'video';
            } else if (mimeType.startsWith('audio/')) {
                mediaType = 'audio';
            } else if (mimeType.startsWith('image/')) {
                mediaType = 'image';
            } else {
                // 如果无法从MIME类型确定,尝试从URL扩展名猜测
                if (url.match(/\.(mp4|webm|og[gv]|m4v|mov)$/i)) {
                    mediaType = 'video';
                } else if (url.match(/\.(mp3|wav|ogg|aac)$/i)) {
                    mediaType = 'audio';
                } else if (url.match(/\.(jpe?g|png|gif|bmp|webp)$/i)) {
                    mediaType = 'image';
                } else {
                    showStatus('无法确定媒体类型,请尝试指定完整URL或选择文件', 'error');
                    return;
                }
            }
            
            currentMediaType = mediaType;
            
            try {
                switch (mediaType) {
                    case 'video':
                        videoPlayer.style.display = 'block';
                        videoElement.src = url;
                        videoElement.load();
                        videoElement.play().catch(e => {
                            showStatus('视频加载成功,但自动播放被阻止。请点击播放按钮。', 'success');
                        });
                        break;
                    case 'audio':
                        audioPlayer.style.display = 'block';
                        audioElement.src = url;
                        audioElement.load();
                        audioElement.play().catch(e => {
                            showStatus('音频加载成功,但自动播放被阻止。请点击播放按钮。', 'success');
                        });
                        break;
                    case 'image':
                        imagePreview.style.display = 'block';
                        imagePreview.src = url;
                        showStatus('图片已加载', 'success');
                        break;
                }
            } catch (e) {
                showStatus('加载媒体时出错: ' + e.message, 'error');
                console.error(e);
            }
        }
        
        // 加载HLS流
        function loadHlsStream(url) {
            resetPlayer();
            currentMediaType = 'video';
            
            if (Hls.isSupported()) {
                // 如果支持HLS.js
                if (hls) {
                    hls.destroy();
                }
                
                hls = new Hls();
                hls.loadSource(url);
                hls.attachMedia(videoElement);
                hls.on(Hls.Events.MANIFEST_PARSED, () => {
                    videoPlayer.style.display = 'block';
                    videoElement.play().catch(e => {
                        showStatus('HLS流加载成功,但自动播放被阻止。请点击播放按钮。', 'success');
                    });
                });
                
                hls.on(Hls.Events.ERROR, (event, data) => {
                    if (data.fatal) {
                        switch (data.type) {
                            case Hls.ErrorTypes.NETWORK_ERROR:
                                showStatus('网络错误,尝试恢复...', 'error');
                                hls.startLoad();
                                break;
                            case Hls.ErrorTypes.MEDIA_ERROR:
                                showStatus('媒体错误,尝试恢复...', 'error');
                                hls.recoverMediaError();
                                break;
                            default:
                                showStatus('无法加载HLS流', 'error');
                                hls.destroy();
                                break;
                        }
                    }
                });
            } else if (videoElement.canPlayType('application/vnd.apple.mpegurl')) {
                // Safari原生支持HLS
                videoPlayer.style.display = 'block';
                videoElement.src = url;
                videoElement.addEventListener('error', () => {
                    showStatus('无法加载HLS流', 'error');
                });
                videoElement.play().catch(e => {
                    showStatus('HLS流加载成功,但自动播放被阻止。请点击播放按钮。', 'success');
                });
            } else {
                showStatus('您的浏览器不支持HLS流播放', 'error');
            }
        }
        
        // 重置播放器
        function resetPlayer() {
            // 隐藏所有播放器
            videoPlayer.style.display = 'none';
            audioPlayer.style.display = 'none';
            imagePreview.style.display = 'none';
            
            // 重置源
            videoElement.src = '';
            audioElement.src = '';
            imagePreview.src = '';
            
            // 停止HLS实例
            if (hls) {
                hls.destroy();
                hls = null;
            }
            
            // 清除状态消息
            statusMessage.style.display = 'none';
            statusMessage.textContent = '';
            statusMessage.className = 'status';
        }
        
        // 显示状态消息
        function showStatus(message, type) {
            statusMessage.textContent = message;
            statusMessage.className = 'status status-' + type;
            statusMessage.style.display = 'block';
        }
        
        // 图片查看器功能
        function openImageViewer() {
            viewerImage.src = imagePreview.src;
            currentScale = 1;
            viewerImage.style.transform = 'scale(1)';
            imageViewer.style.display = 'flex';
            document.body.style.overflow = 'hidden';
        }
        
        function closeImageViewer() {
            imageViewer.style.display = 'none';
            document.body.style.overflow = '';
        }
        
        function zoomImage(factor) {
            if (factor === 0) {
                // 重置缩放
                currentScale = 1;
            } else {
                // 应用缩放因子
                currentScale *= factor;
                
                // 限制缩放范围
                if (currentScale < 0.1) currentScale = 0.1;
                if (currentScale > 10) currentScale = 10;
            }
            
            viewerImage.style.transform = `scale(${currentScale})`;
        }
        
        // 键盘快捷键处理
        function handleKeyDown(e) {
            if (imageViewer.style.display === 'flex') {
                switch (e.key) {
                    case 'Escape':
                        closeImageViewer();
                        break;
                    case '+':
                    case '=':
                        zoomImage(1.2);
                        break;
                    case '-':
                    case '_':
                        zoomImage(0.8);
                        break;
                    case '0':
                        zoomImage(0);
                        break;
                }
            }
        }
        
        // 鼠标滚轮缩放处理
        function handleWheel(e) {
            if (imageViewer.style.display === 'flex') {
                e.preventDefault();
                if (e.deltaY < 0) {
                    // 滚轮向上 - 放大
                    zoomImage(1.1);
                } else {
                    // 滚轮向下 - 缩小
                    zoomImage(0.9);
                }
            }
        }
        
        // 初始化
        window.addEventListener('DOMContentLoaded', initPlayer);
    </script>
</body>
</html>



主要功能
多格式支持:

视频:MP4 (H.264), WebM, Ogg Theora
音频:MP3, WAV, Ogg Vorbis, AAC
图片:JPG, PNG, GIF, BMP, WebP
文件选择界面:

使用美观的按钮触发文件选择
通过文件类型过滤只显示媒体文件
自适应播放器:

根据选择的文件类型自动显示相应的播放器(视频、音频或图片)
隐藏不相关的播放器元素
图片查看器功能:

点击图片可放大查看
支持缩放功能(放大、缩小、重置)
可通过按钮或键盘快捷键控制
鼠标滚轮缩放支持
响应式设计:

适应不同屏幕尺寸
美观的UI设计
技术实现
HTML5媒体元素:

使用<video>和<audio>标签实现媒体播放
使用<img>标签显示图片
文件处理:

使用URL.createObjectURL()创建本地文件URL
通过文件类型检测自动选择正确的播放器
图片查看器:

使用CSS transform实现缩放效果
固定定位的全屏查看器
事件监听处理用户交互
键盘快捷键:

ESC键关闭查看器
+/-键缩放图片
0键重置缩放
用户体验优化
自动尝试播放媒体文件
清晰的格式支持说明
平滑的动画过渡效果
防止背景滚动干扰查看体验
直观的操作提示


新增改进:
M3U8/HLS支持:
引入了hls.js库来处理M3U8格式的视频流

自动检测浏览器对HLS的支持情况,优先使用原生支持(Safari),否则使用hls.js

添加了错误处理和恢复机制

URL输入功能:
增加了URL输入框和播放按钮
自动识别M3U8格式和其他视频格式

支持MP4、WebM、Ogg和M3U8等多种格式

跨域处理:
为video标签添加了crossorigin="anonymous"属性以支持跨域视频

改进了格式兼容性检测

用户体验改进:

在格式信息中显示浏览器对各种格式的支持情况
优化了错误处理和用户反馈

代码结构优化:
将HLS实例管理封装在全局变量中
改进了媒体切换逻辑,确保资源正确释放

使用说明
可以直接输入M3U8或其他视频URL进行播放
也可以选择本地视频/音频/图片文件进行播放
系统会自动检测浏览器对各种格式的支持情况
对于M3U8格式,会优先使用浏览器原生支持(Safari),否则使用hls.js

注意事项
某些浏览器可能限制自动播放,需要用户交互后才能播放

跨域视频需要服务器正确配置CORS头

加密的M3U8流需要额外处理密钥

这个改进后的播放器现在可以完美支持M3U8/HLS格式的视频流,同时保留了原有的本地文件播放功能。


免费评分

参与人数 11吾爱币 +8 热心值 +11 收起 理由
cccfind911 + 1 谢谢@Thanks!
repack9527 + 1 + 1 我很赞同!
rhclike + 1 我很赞同!
qinni8513 + 1 + 1 谢谢@Thanks!
施施乐 + 1 + 1 谢谢@Thanks!
WXJYXLWMH + 1 + 1 谢谢@Thanks!
片地花开 + 1 + 1 谢谢@Thanks!
Robinbnbnbm + 1 热心回复!
Jixuan0723 + 1 + 1 谢谢@Thanks!
ps122 + 1 + 1 谢谢@Thanks!
hicesamon + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

  • · 好玩|主题: 1, 订阅: 0

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

hicesamon 发表于 2025-4-18 11:52
感谢分享,界面很美观
sfl4800 发表于 2025-4-18 11:58
Y有成品吗??这个好看简单。。但是不会搞成成品哦
hicesamon 发表于 2025-4-18 12:04
适配有问题,自带小米浏览器不能选择文件,via界面排版不好看(用电脑ua也一样)
hicesamon 发表于 2025-4-18 12:06
sfl4800 发表于 2025-4-18 11:58
Y有成品吗??这个好看简单。。但是不会搞成成品哦

用文件管理器新建文件,命名成“1.html”,然后编辑这个文件,把上面的代码复制进去并保存。打开这个文件就行了
miraak 发表于 2025-4-18 12:12
这还用生成?
大约是已有代码略微变动的。
fyfy123456 发表于 2025-4-18 12:18
谢谢 分享~!
ps122 发表于 2025-4-18 12:20
效果不错,多谢分享!
 楼主| lcg888 发表于 2025-4-18 12:53
miraak 发表于 2025-4-18 12:12
这还用生成?
大约是已有代码略微变动的。

这是我根据我自己的需求一个个让ai完善的,自己改动了一小下
 楼主| lcg888 发表于 2025-4-18 12:54
sfl4800 发表于 2025-4-18 11:58
Y有成品吗??这个好看简单。。但是不会搞成成品哦

直接复制代码到html本地就可以打开使用啊
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-6-15 04:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表