This commit is contained in:
Dongho Kim
2026-06-22 02:33:30 +02:00
commit c12f0945a4
5 changed files with 114 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
require('dotenv').config();
const express = require('express');
const axios = require('axios');
const app = express();
const port = process.env.PORT || 3000;
// Parse channels from .env
// Expected format: CHANNELS=id1:Name1,id2:Name2
const parseChannels = () => {
const channelsString = process.env.CHANNELS || '';
if (!channelsString) return [];
return channelsString.split(',').map(ch => {
const [id, ...nameParts] = ch.split(':');
return { id: id.trim(), name: nameParts.join(':').trim() };
}).filter(ch => ch.id && ch.name);
};
app.get('/playlist.m3u', (req, res) => {
const channels = parseChannels();
const host = req.get('host');
const protocol = req.protocol;
let m3u = "#EXTM3U\n";
channels.forEach(ch => {
m3u += `#EXTINF:-1 tvg-id="${ch.id}" tvg-name="${ch.name}" group-title="Chzzk",${ch.name}\n`;
m3u += `${protocol}://${host}/stream/${ch.id}\n`;
});
res.header('Content-Type', 'application/vnd.apple.mpegurl');
res.send(m3u);
});
app.get('/stream/:channelId', async (req, res) => {
const { channelId } = req.params;
try {
const response = await axios.get(`https://api.chzzk.naver.com/service/v1/channels/${channelId}/live-detail`, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
});
const data = response.data;
if (!data || !data.content || !data.content.livePlaybackJson) {
return res.status(404).send('Stream not found or offline');
}
const livePlayback = JSON.parse(data.content.livePlaybackJson);
const media = livePlayback.media || [];
// Find HLS or LLHLS stream
const hlsMedia = media.find(m => m.mediaId === 'HLS' || m.mediaId === 'LLHLS');
if (hlsMedia && hlsMedia.path) {
// Redirect Jellyfin to the actual M3U8 url
res.redirect(302, hlsMedia.path);
} else {
res.status(404).send('HLS stream not found in playback info');
}
} catch (error) {
console.error(`Error fetching stream for channel ${channelId}:`, error.message);
res.status(500).send('Error fetching stream from Chzzk API');
}
});
app.listen(port, () => {
console.log(`Chzzk IPTV Proxy running on port ${port}`);
console.log(`Playlist URL: http://localhost:${port}/playlist.m3u`);
});