Spaces:
Paused
Paused
| # 1. Start Xvfb (Virtual Screen) | |
| Xvfb :99 -screen 0 1080x1920x24 & | |
| export DISPLAY=:99 | |
| # 2. Check for Music | |
| if [ ! -f bgm.mp3 ]; then | |
| echo "Downloading background music..." | |
| wget -q -O bgm.mp3 "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Kevin_MacLeod/Oddities/Kevin_MacLeod_-_Winner_Winner.mp3" | |
| fi | |
| # 3. Create Node Server (Website) on Port 7860 | |
| echo " | |
| const express = require('express'); | |
| const app = express(); | |
| const path = require('path'); | |
| app.get('/', (req, res) => res.sendFile(path.join(__dirname, 'index.html'))); | |
| app.get('/health', (req, res) => res.send('OK')); | |
| app.listen(7860, () => console.log('Server ready on port 7860')); | |
| const puppeteer = require('puppeteer'); | |
| (async () => { | |
| try { | |
| const browser = await puppeteer.launch({ | |
| executablePath: '/usr/bin/google-chrome', | |
| headless: false, | |
| args: [ | |
| '--no-sandbox', | |
| '--disable-setuid-sandbox', | |
| '--start-fullscreen', | |
| '--window-size=1080,1920', | |
| '--kiosk', | |
| '--disable-infobars', | |
| '--disable-dev-shm-usage', | |
| '--disable-gpu', | |
| '--autoplay-policy=no-user-gesture-required' | |
| ] | |
| }); | |
| const page = await browser.newPage(); | |
| await page.setViewport({ width: 1080, height: 1920 }); | |
| await page.goto('http://localhost:7860'); | |
| console.log('Browser loaded successfully'); | |
| } catch (e) { | |
| console.error('Browser crashed:', e); | |
| } | |
| })(); | |
| " > server.js | |
| # 4. Create Smart DNS Resolver | |
| echo " | |
| const https = require('https'); | |
| const url = 'https://dns.google/resolve?name=a.rtmp.youtube.com&type=A'; | |
| https.get(url, (res) => { | |
| let data = ''; | |
| res.on('data', (chunk) => data += chunk); | |
| res.on('end', () => { | |
| try { | |
| const json = JSON.parse(data); | |
| if (json.Answer) { | |
| console.log(json.Answer.find(a => a.type === 1).data); | |
| } else { console.log('DNS_FAIL'); } | |
| } catch (e) { console.log('DNS_FAIL'); } | |
| }); | |
| }).on('error', (err) => console.log('DNS_FAIL')); | |
| " > resolve_ip.js | |
| # 5. Start Website | |
| node server.js & | |
| sleep 15 | |
| # 6. Resolve YouTube IP | |
| echo "Resolving YouTube IP..." | |
| YOUTUBE_IP=$(node resolve_ip.js) | |
| if [ "$YOUTUBE_IP" == "DNS_FAIL" ] || [ -z "$YOUTUBE_IP" ]; then | |
| YOUTUBE_IP="142.250.179.140" | |
| fi | |
| echo "Targeting Server: $YOUTUBE_IP" | |
| # 7. Start Stream (CPU OPTIMIZED) | |
| # Changes: Reduced bitrate to 2500k, changed preset to ultrafast, added -r 30 output enforcement | |
| ffmpeg -y \ | |
| -thread_queue_size 1024 -f x11grab -draw_mouse 0 -s 1080x1920 -framerate 30 -i :99 \ | |
| -thread_queue_size 1024 -stream_loop -1 -i bgm.mp3 \ | |
| -c:v libx264 -preset ultrafast -b:v 2500k -maxrate 3000k -bufsize 6000k -pix_fmt yuv420p -g 60 -r 30 \ | |
| -c:a aac -b:a 128k -ar 44100 -map 0:v:0 -map 1:a:0 \ | |
| -f flv "rtmp://$YOUTUBE_IP:1935/live2/$YOUTUBE_KEY" |