{"id":752,"date":"2024-12-27T09:38:51","date_gmt":"2024-12-27T01:38:51","guid":{"rendered":"https:\/\/10.10.10.2\/wordpress?p=752"},"modified":"2024-12-27T09:44:45","modified_gmt":"2024-12-27T01:44:45","slug":"%e7%ba%af%e5%89%8d%e7%ab%afiptv%e6%92%ad%e6%94%be%e5%99%a8%ef%bc%8c%e6%ba%90%e7%a0%81%e5%88%86%e4%ba%ab%ef%bc%8c%e7%9b%b4%e6%92%ad%e6%ba%90%e5%88%86%e4%ba%ab","status":"publish","type":"post","link":"https:\/\/freet.cc\/wordpress\/?p=752","title":{"rendered":"\u7eaf\u524d\u7aefIPTV\u64ad\u653e\u5668\uff0c\u6e90\u7801\u5206\u4eab\uff0c\u76f4\u64ad\u6e90\u5206\u4eab"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"http:\/\/freet.cc\/wordpress\/wp-content\/uploads\/2024\/12\/a6bd50a4f4bed8df8ca18085f21ae371db2f854a_2_642x500.jpg\" alt=\"\"\/><\/figure>\n\n\n\n<p>\u76f4\u64ad\u6e90\uff1a<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">TXT\u8ba2\u9605\u5730\u5740: http:\/\/amw1933.cn:51001\/Sub?type=txt<\/h5>\n\n\n\n<h5 class=\"wp-block-heading\">M3u\u8ba2\u9605\u5730\u5740: http:\/\/amw1933.cn:51001\/Sub?type=m3u<\/h5>\n\n\n\n<pre class=\"wp-block-code has-pale-cyan-blue-background-color has-background\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"zh-CN\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;\u667a\u80fdIPTV\u64ad\u653e\u5668&lt;\/title&gt;\n    &lt;link href=\"https:\/\/vjs.zencdn.net\/7.20.3\/video-js.min.css\" rel=\"stylesheet\"&gt;\n    &lt;script src=\"https:\/\/vjs.zencdn.net\/7.20.3\/video.min.js\"&gt;&lt;\/script&gt;\n    &lt;link href=\"https:\/\/fonts.googleapis.com\/css2?family=Noto+Sans+SC:wght@300;400;700&amp;display=swap\" rel=\"stylesheet\"&gt;\n    &lt;style&gt;\n        :root {\n            --primary-color: #2c3e50;\n            --secondary-color: #34495e;\n            --accent-color: #3498db;\n            --background-color: #ecf0f1;\n            --text-color: #2c3e50;\n            --hover-color: #e74c3c;\n        }\n\n        * {\n            box-sizing: border-box;\n            margin: 0;\n            padding: 0;\n        }\n\n        body {\n            font-family: 'Noto Sans SC', sans-serif;\n            background-color: var(--background-color);\n            color: var(--text-color);\n            line-height: 1.6;\n        }\n\n        .container {\n            max-width: 1400px;\n            margin: 0 auto;\n            padding: 20px;\n        }\n\n        header {\n            background-color: var(--primary-color);\n            color: white;\n            text-align: center;\n            padding: 20px 0;\n            margin-bottom: 30px;\n            box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n        }\n\n        h1 {\n            font-size: 2.5em;\n            font-weight: 700;\n            letter-spacing: 2px;\n        }\n\n        .content {\n            display: flex;\n            gap: 30px;\n            background-color: white;\n            border-radius: 15px;\n            overflow: hidden;\n            box-shadow: 0 10px 20px rgba(0,0,0,0.1);\n        }\n\n        #channel-list {\n            flex: 0 0 300px;\n            height: calc(100vh - 200px);\n            overflow-y: auto;\n            background-color: var(--secondary-color);\n            padding: 20px;\n            scrollbar-width: thin;\n            scrollbar-color: var(--accent-color) var(--secondary-color);\n        }\n\n        #channel-list::-webkit-scrollbar {\n            width: 8px;\n        }\n\n        #channel-list::-webkit-scrollbar-track {\n            background: var(--secondary-color);\n        }\n\n        #channel-list::-webkit-scrollbar-thumb {\n            background-color: var(--accent-color);\n            border-radius: 20px;\n        }\n\n        #channel-list button {\n            display: block;\n            width: 100%;\n            padding: 15px;\n            border: none;\n            background-color: transparent;\n            color: white;\n            text-align: left;\n            cursor: pointer;\n            transition: all 0.3s ease;\n            border-radius: 8px;\n            margin-bottom: 10px;\n        }\n\n        #channel-list button:hover, #channel-list button.active {\n            background-color: var(--accent-color);\n            transform: translateX(5px);\n        }\n\n        #player-container {\n            flex: 1;\n            display: flex;\n            flex-direction: column;\n            justify-content: center;\n            align-items: center;\n            padding: 20px;\n        }\n\n        #video-wrapper {\n            width: 100%;\n            max-width: 1080px;\n            position: relative;\n            padding-top: 56.25%; \/* 16:9 Aspect Ratio *\/\n        }\n\n        .video-js {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            border-radius: 8px;\n            overflow: hidden;\n            box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n        }\n\n        .channel-item {\n            display: flex;\n            align-items: center;\n        }\n\n        .channel-icon {\n            width: 40px;\n            height: 40px;\n            margin-right: 15px;\n            object-fit: contain;\n            border-radius: 50%;\n            background-color: white;\n            padding: 5px;\n            transition: transform 0.3s ease;\n        }\n\n        #channel-list button:hover .channel-icon {\n            transform: scale(1.1);\n        }\n\n        .channel-info {\n            display: flex;\n            flex-direction: column;\n            flex-grow: 1;\n            overflow: hidden;\n        }\n\n        .channel-name {\n            font-weight: bold;\n            margin-bottom: 5px;\n            font-size: 1em;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n        }\n\n        .channel-description {\n            font-size: 0.8em;\n            opacity: 0.8;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n        }\n\n        @media (max-width: 968px) {\n            .content {\n                flex-direction: column;\n            }\n\n            #channel-list, #player-container {\n                width: 100%;\n            }\n\n            #channel-list {\n                height: 300px;\n                flex: none;\n            }\n        }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;header&gt;\n        &lt;h1&gt;\u667a\u80fdIPTV\u64ad\u653e\u5668&lt;\/h1&gt;\n    &lt;\/header&gt;\n    &lt;div class=\"container\"&gt;\n        &lt;div class=\"content\"&gt;\n            &lt;div id=\"channel-list\"&gt;&lt;\/div&gt;\n            &lt;div id=\"player-container\"&gt;\n                &lt;div id=\"video-wrapper\"&gt;\n                    &lt;video-js id=\"my-video\" class=\"video-js vjs-big-play-centered\" controls preload=\"auto\" data-setup='{\"techOrder\": &#91;\"html5\"]}'&gt;\n                        &lt;p class=\"vjs-no-js\"&gt;\n                            To view this video please enable JavaScript, and consider upgrading to a web browser that\n                            &lt;a href=\"https:\/\/videojs.com\/html5-video-support\/\" target=\"_blank\"&gt;supports HTML5 video&lt;\/a&gt;\n                        &lt;\/p&gt;\n                    &lt;\/video-js&gt;\n                &lt;\/div&gt;\n            &lt;\/div&gt;\n        &lt;\/div&gt;\n    &lt;\/div&gt;\n\n    &lt;script&gt;\n        const playlistUrl = 'https:\/\/raw.githubusercontent.com\/hujingguang\/ChinaIPTV\/main\/cnTV_AutoUpdate.m3u8';\n        const channelList = document.getElementById('channel-list');\n        const player = videojs('my-video', {\n            html5: {\n                hls: {\n                    overrideNative: true\n                }\n            }\n        });\n\n        let currentChannelIndex = -1;\n        let channels = &#91;];\n\n        function isValidIpv4Url(string) {\n            try {\n                const url = new URL(string);\n                return !string.includes('&#91;') &amp;&amp; !string.includes(']');\n            } catch (_) {\n                return false;\n            }\n        }\n\n        function parseM3ULine(line) {\n            if (line.startsWith('http:\/\/') || line.startsWith('https:\/\/')) {\n                return line.trim();\n            }\n            return null;\n        }\n\n        function extractTvgInfo(extinf) {\n            const logoMatch = extinf.match(\/tvg-logo=\"(&#91;^\"]+)\"\/);\n            const nameMatch = extinf.match(\/tvg-name=\"(&#91;^\"]+)\"\/);\n            return {\n                logo: logoMatch ? logoMatch&#91;1] : null,\n                name: nameMatch ? nameMatch&#91;1] : null\n            };\n        }\n\n        function playChannel(index) {\n            if (index &gt;= 0 &amp;&amp; index &lt; channels.length) {\n                const channel = channels&#91;index];\n                player.src({\n                    type: 'application\/x-mpegURL',\n                    src: channel.url\n                });\n                player.play();\n                channelList.querySelectorAll('button').forEach(btn =&gt; btn.classList.remove('active'));\n                channelList.children&#91;index].classList.add('active');\n                currentChannelIndex = index;\n                channelList.children&#91;index].scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n            }\n        }\n\n        fetch(playlistUrl)\n            .then(response =&gt; response.text())\n            .then(data =&gt; {\n                const lines = data.split('\\n');\n                for (let i = 0; i &lt; lines.length; i++) {\n                    if (lines&#91;i].startsWith('#EXTINF')) {\n                        const tvgInfo = extractTvgInfo(lines&#91;i]);\n                        const title = lines&#91;i].split(',')&#91;1];\n                        const url = parseM3ULine(lines&#91;i+1]);\n                        if (url &amp;&amp; isValidIpv4Url(url)) {\n                            channels.push({ title, url, tvgInfo });\n                            const button = document.createElement('button');\n                            const channelItem = document.createElement('div');\n                            channelItem.className = 'channel-item';\n\n                            if (tvgInfo.logo) {\n                                const img = document.createElement('img');\n                                img.src = tvgInfo.logo;\n                                img.className = 'channel-icon';\n                                img.onerror = function() { this.style.display = 'none'; };\n                                channelItem.appendChild(img);\n                            }\n\n                            const infoDiv = document.createElement('div');\n                            infoDiv.className = 'channel-info';\n\n                            const nameSpan = document.createElement('span');\n                            nameSpan.className = 'channel-name';\n                            nameSpan.textContent = tvgInfo.name || title;\n                            infoDiv.appendChild(nameSpan);\n\n                            if (tvgInfo.name &amp;&amp; tvgInfo.name !== title) {\n                                const descSpan = document.createElement('span');\n                                descSpan.className = 'channel-description';\n                                descSpan.textContent = title;\n                                infoDiv.appendChild(descSpan);\n                            }\n\n                            channelItem.appendChild(infoDiv);\n                            button.appendChild(channelItem);\n                            channelList.appendChild(button);\n                        }\n                    }\n                }\n                if (channels.length &gt; 0) {\n                    playChannel(0);\n                }\n                \/\/ \u8bbe\u7f6e\u9891\u9053\u70b9\u51fb\u4e8b\u4ef6\n                channelList.querySelectorAll('button').forEach((button, index) =&gt; {\n                    button.onclick = function() {\n                        playChannel(index);\n                    };\n                });\n            })\n            .catch(error =&gt; console.error('Error:', error));\n    &lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;```<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u76f4\u64ad\u6e90\uff1a TXT\u8ba2\u9605\u5730\u5740: h&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,4,1],"tags":[],"class_list":["post-752","post","type-post","status-publish","format-standard","hentry","category-linux","category-4","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/752","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=752"}],"version-history":[{"count":5,"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/752\/revisions"}],"predecessor-version":[{"id":761,"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/752\/revisions\/761"}],"wp:attachment":[{"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=752"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=752"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/freet.cc\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=752"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}