各个宽带运营商都有 IPTV 业务,不用安装有线电视就可以高清无卡顿的看电视。没有开通 iptv 可以使用抓取的直播源地址,复制到电脑、手机、电视网络盒子等设备上看,如果动手能力强也可以自己抓包获取直播源(不会)

项目地址:xisohi/CHINA-IPTV
提供了各省联通,移动,电信的IPTV单播和组播地址。
这里只使用单播地址。
直播源地址是txt格式,部分软件可以直接使用,转成m3u格式兼容性更好。

下载txt

地址前加上https://gh-proxy.com/即可不用梯子直接下载。
比如河北移动 https://github.com/xisohi/CHINA-IPTV/blob/main/Unicast/hebei/mobile.txt ,加上前缀之后可直接点击打开 ,txt会在浏览器中打开,全选复制,粘贴到文本文件中,保存。

txt转m3u

项目提供了一个html转换工具。
为方便使用,这里贴出全文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>直播源格式转换器</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center">
<div class="bg-white p-8 rounded-lg shadow-md w-full max-w-md">
<h1 class="text-2xl font-bold mb-6 text-center">直播源格式转换器</h1>

<div class="mb-8">
<h2 class="text-xl font-semibold mb-4">M3U 转 TXT(可选项:保留分组信息)</h2>
<form id="m3u-to-txt-form" class="space-y-4">
<input type="file" id="m3u-file" accept=".m3u" required class="w-full p-2 border rounded">
<div class="flex items-center">
<input type="checkbox" id="keep-groups-m3u" class="form-checkbox h-5 w-5 text-blue-600">
<label for="keep-groups-m3u" class="ml-2">保留分组信息</label>
</div>
<button type="submit" class="w-full bg-blue-500 text-white py-2 rounded hover:bg-blue-600 transition duration-200">转换</button>
</form>
</div>

<div>
<h2 class="text-xl font-semibold mb-4">TXT 转 M3U(可选项:保留分组信息)</h2>
<form id="txt-to-m3u-form" class="space-y-4">
<input type="file" id="txt-file" accept=".txt" required class="w-full p-2 border rounded">
<input type="text" id="epg-url" placeholder="EPG URL (可选,默认为 https://epg.112114.xyz/pp.xml)" class="w-full p-2 border rounded">
<div class="flex items-center">
<input type="checkbox" id="keep-groups-txt" class="form-checkbox h-5 w-5 text-green-600">
<label for="keep-groups-txt" class="ml-2">保留分组信息</label>
</div>
<button type="submit" class="w-full bg-green-500 text-white py-2 rounded hover:bg-green-600 transition duration-200">转换</button>
</form>
</div>
</div>

<script>
function parseM3UToTXT(m3uContent, keepGroups) {
const lines = m3uContent.split('\n');
const channels = {};
let currentGroup = '未分组';

for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line.startsWith('#EXTINF:-1')) {
const groupMatch = line.match(/group-title="([^"]*)"/);
const nameMatch = line.match(/tvg-name="([^"]*)"/);
const group = groupMatch ? groupMatch[1] : currentGroup;
const name = nameMatch ? nameMatch[1] : line.split(',').pop();
const url = lines[i + 1] ? lines[i + 1].trim() : '';

if (!channels[group]) {
channels[group] = [];
}
channels[group].push(`${name},${url}`);
currentGroup = group;
}
}

let txtContent = '';
if (keepGroups) {
for (const [group, channelList] of Object.entries(channels)) {
txtContent += `${group},#genre#\n`;
txtContent += channelList.join('\n') + '\n';
}
} else {
for (const [group, channelList] of Object.entries(channels)) {
txtContent += channelList.join('\n') + '\n';
}
}

return txtContent;
}

function convertTXTToM3U(txtContent, epgUrl, keepGroups) {
const defaultEpgUrl = "https://epg.112114.xyz/pp.xml";
const lines = txtContent.split('\n');
let m3uContent = `#EXTM3U x-tvg-url="${epgUrl || defaultEpgUrl}"\n`;
let currentGenre = '未分类';

for (const line of lines) {
const trimmedLine = line.trim();
if (trimmedLine.endsWith(',#genre#')) {
currentGenre = trimmedLine.replace(',#genre#', '');
} else if (trimmedLine && !trimmedLine.startsWith('#')) {
const [channelName, channelUrl] = trimmedLine.split(',');
const tvgLogo = `https://epg.112114.xyz/logo/${channelName}.png`;
if (keepGroups) {
m3uContent += `#EXTINF:-1 group-title="${currentGenre}" tvg-name="${channelName}" tvg-logo="${tvgLogo}" epg-url="${epgUrl || defaultEpgUrl}",${channelName}\n`;
} else {
m3uContent += `#EXTINF:-1 tvg-name="${channelName}" tvg-logo="${tvgLogo}" epg-url="${epgUrl || defaultEpgUrl}",${channelName}\n`;
}
m3uContent += `${channelUrl}\n`;
}
}

return m3uContent;
}

function downloadFile(content, filename) {
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}

function getCurrentDateTime() {
const now = new Date();
return now.getFullYear() +
('0' + (now.getMonth() + 1)).slice(-2) +
('0' + now.getDate()).slice(-2) +
('0' + now.getHours()).slice(-2) +
('0' + now.getMinutes()).slice(-2) +
('0' + now.getSeconds()).slice(-2);
}

function getFileNameWithoutExtension(filename) {
return filename.split('.').slice(0, -1).join('.');
}

document.getElementById('m3u-to-txt-form').addEventListener('submit', function(e) {
e.preventDefault();
const file = document.getElementById('m3u-file').files[0];
const reader = new FileReader();
const keepGroups = document.getElementById('keep-groups-m3u').checked;
reader.onload = function(e) {
const m3uContent = e.target.result;
const txtContent = parseM3UToTXT(m3uContent, keepGroups);
const originalName = getFileNameWithoutExtension(file.name);
const newFileName = `${originalName}_${getCurrentDateTime()}.txt`;
downloadFile(txtContent, newFileName);
};
reader.readAsText(file);
});

document.getElementById('txt-to-m3u-form').addEventListener('submit', function(e) {
e.preventDefault();
const file = document.getElementById('txt-file').files[0];
const epgUrl = document.getElementById('epg-url').value.trim() || "https://epg.112114.xyz/pp.xml";
const reader = new FileReader();
const keepGroups = document.getElementById('keep-groups-txt').checked;
reader.onload = function(e) {
const txtContent = e.target.result;
const m3uContent = convertTXTToM3U(txtContent, epgUrl, keepGroups);
const originalName = getFileNameWithoutExtension(file.name);
const newFileName = `${originalName}_${getCurrentDateTime()}.m3u`;
downloadFile(m3uContent, newFileName);
};
reader.readAsText(file);
});
</script>
</body>
</html>

复制后保存到html文件,打开:

勾选保留分组信息,打开前文的txt文件,可得到m3u文件。可用potplayer直接打开播放。
放到web上可供手机,电视使用。

河北移动可用:https://api.qs100371.top/mobile.m3u

现在正是世界杯期间,稳定的IPTV源很重要,之前的migu_video项目也可以流畅观看。