/** * AeThex LIVE - RTMP Media Server * * This receives RTMP streams from OBS and converts to HLS for playback. * * OBS Settings: * Server: rtmp://localhost:1935/live * Stream Key: anything (e.g., "stream" or a random key) * * HLS Playback URL: * http://localhost:8000/live/{streamKey}/index.m3u8 */ const NodeMediaServer = require('node-media-server'); const path = require('path'); const fs = require('fs'); // Create media directory if it doesn't exist const mediaDir = path.join(__dirname, 'media'); if (!fs.existsSync(mediaDir)) { fs.mkdirSync(mediaDir, { recursive: true }); } const config = { rtmp: { port: 1935, chunk_size: 60000, gop_cache: true, ping: 30, ping_timeout: 60 }, http: { port: 8000, mediaroot: mediaDir, allow_origin: '*', api: true }, trans: { ffmpeg: process.env.FFMPEG_PATH || 'ffmpeg', tasks: [ { app: 'live', hls: true, hlsFlags: '[hls_time=2:hls_list_size=3:hls_flags=delete_segments]', hlsKeep: false, // Don't keep old segments dash: false, } ] } }; const nms = new NodeMediaServer(config); nms.on('preConnect', (id, args) => { console.log('[NodeEvent on preConnect]', `id=${id} args=${JSON.stringify(args)}`); }); nms.on('postConnect', (id, args) => { console.log('[NodeEvent on postConnect]', `id=${id} args=${JSON.stringify(args)}`); }); nms.on('doneConnect', (id, args) => { console.log('[NodeEvent on doneConnect]', `id=${id} args=${JSON.stringify(args)}`); }); nms.on('prePublish', (id, StreamPath, args) => { console.log('[NodeEvent on prePublish]', `id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`); console.log(''); console.log('='.repeat(60)); console.log('đŸŽĨ STREAM STARTED!'); console.log('='.repeat(60)); console.log(`HLS URL: http://localhost:8000${StreamPath}/index.m3u8`); console.log(''); console.log('Add this to your .env.local:'); console.log(`NEXT_PUBLIC_STREAM_URL=http://localhost:8000${StreamPath}/index.m3u8`); console.log('='.repeat(60)); console.log(''); }); nms.on('postPublish', (id, StreamPath, args) => { console.log('[NodeEvent on postPublish]', `id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`); }); nms.on('donePublish', (id, StreamPath, args) => { console.log('[NodeEvent on donePublish]', `id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`); console.log(''); console.log('âšī¸ Stream ended'); console.log(''); }); nms.on('prePlay', (id, StreamPath, args) => { console.log('[NodeEvent on prePlay]', `id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`); }); nms.on('postPlay', (id, StreamPath, args) => { console.log('[NodeEvent on postPlay]', `id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`); }); nms.on('donePlay', (id, StreamPath, args) => { console.log('[NodeEvent on donePlay]', `id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`); }); console.log(''); console.log('='.repeat(60)); console.log('🚀 AeThex LIVE - Media Server Starting'); console.log('='.repeat(60)); console.log(''); console.log('RTMP Server: rtmp://localhost:1935/live'); console.log('HTTP Server: http://localhost:8000'); console.log(''); console.log('OBS Settings:'); console.log(' Service: Custom'); console.log(' Server: rtmp://localhost:1935/live'); console.log(' Stream Key: stream (or any key you want)'); console.log(''); console.log('After you start streaming, your HLS URL will be:'); console.log(' http://localhost:8000/live/stream/index.m3u8'); console.log(''); console.log('='.repeat(60)); console.log(''); nms.run();