update
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
PORT=3000
|
||||||
|
|
||||||
|
# Format: CHANNELS=id1:Name1,id2:Name2
|
||||||
|
# You can find the channel ID in the URL of the streamer's Chzzk channel (e.g., chzzk.naver.com/CHANNEL_ID)
|
||||||
|
CHANNELS=4df4756104a54e28e967bff6dc08e319:KBS2,8ecd602c251f30fd7f09463e9f55609f:JTBC
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["npm", "start"]
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
chzzk-proxy:
|
||||||
|
build: .
|
||||||
|
container_name: chzzk-jellyfin-proxy
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
restart: unless-stopped
|
||||||
@@ -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`);
|
||||||
|
});
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "czzk-jellyfin-proxy",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Chzzk to Jellyfin IPTV Proxy",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.6.8",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"express": "^4.19.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user