const express = require('express');
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const app = express();
const PORT = 8787;
app.use(express.urlencoded({ extended: true }));
// Function to get Ngrok URL from config.json
function getNgrokUrl() {
try {
const configPath = path.join(__dirname, 'config.json');
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
return config.ngrokUrl;
} catch (error) {
console.error('Error reading config file: ', error);
return null;
}
}
// Get Ngrok URL
const ngrokUrl = getNgrokUrl();
if (!ngrokUrl) {
console.error('Ngrok URL is not defined. Please check the config.json file.');
process.exit(1);
}
// Serve HLS files
const hlsDirectory = path.join(__dirname, 'hls');
app.use('/hls', express.static(hlsDirectory));
if (!fs.existsSync(hlsDirectory)) {
fs.mkdirSync(hlsDirectory);
}
let ffmpegPid = null;
// Function to delete HLS files
function deleteHLSFiles() {
fs.readdir(hlsDirectory, (err, files) => {
if (err) {
console.error('Error reading HLS directory for deletion:', err);
return;
}
const deletePromises = files.map(file => {
return new Promise((resolve, reject) => {
fs.unlink(path.join(hlsDirectory, file), err => {
if (err) {
console.error('Error deleting HLS file:', err);
return reject(err);
}
resolve();
});
});
});
Promise.all(deletePromises)
.then(() => {
console.log('HLS files deleted successfully.');
})
.catch(err => {
console.error('Error deleting HLS files:', err);
});
});
}
// Serve the home page with a form
app.get('/', (req, res) => {
// Check if HLS files exist
fs.readdir(hlsDirectory, (err, files) => {
const hlsFilesExist = files && files.length > 0;
const stopButtonEnabled = ffmpegPid !== null || hlsFilesExist;
res.send(`
<<< bypassV >>>
<<< bypassV >>>
[restriction bypass v1.1]
`);
});
});
// Helper function to convert duration to seconds
function durationToSeconds(duration) {
const parts = duration.split(':').map(part => parseInt(part, 10));
if (parts.length === 3) {
return parts[0] * 3600 + parts[1] * 60 + parts[2];
} else if (parts.length === 2) {
return parts[0] * 60 + parts[1];
} else if (parts.length === 1) {
return parts[0];
}
return 0;
}
// Handle the stream request
app.post('/stream', (req, res) => {
const videoUrl = req.body.videoUrl;
if (!videoUrl) {
return res.status(400).send('Error: No video URL provided.');
}
const ytdlpCommand = `yt-dlp --get-duration "${videoUrl}" && yt-dlp -f best -g "${videoUrl}"`;
exec(ytdlpCommand, (error, stdout, stderr) => {
if (error) {
console.error(`Error fetching video URL: ${error.message}`);
console.error(`yt-dlp stderr: ${stderr}`);
return res.status(500).send('Error fetching video URL.');
}
const output = stdout.trim().split('\n');
const durationStr = output[0];
const directVideoUrl = output[1];
if (!directVideoUrl) {
console.error('No direct video URL found.');
return res.status(500).send('Error fetching video URL.');
}
const durationSeconds = durationToSeconds(durationStr);
if (durationSeconds === 0) {
console.error('Invalid video duration.');
return res.status(500).send('Error processing video duration.');
}
// Clear existing HLS files before starting a new stream
deleteHLSFiles();
const ffmpegCommand = [
'-i', directVideoUrl,
'-c:v', 'libx264',
'-preset', 'fast',
'-crf', '22',
'-g', '60',
'-hls_time', '2',
'-hls_list_size', '0',
'-f', 'hls',
path.join(hlsDirectory, 'stream.m3u8')
];
const ffmpegProcess = spawn('ffmpeg', ffmpegCommand);
ffmpegPid = ffmpegProcess.pid;
ffmpegProcess.stdout.on('data', (data) => {
console.log(`ffmpeg stdout: ${data}`);
});
ffmpegProcess.stderr.on('data', (data) => {
console.error(`ffmpeg stderr: ${data}`);
});
ffmpegProcess.on('exit', (code, signal) => {
console.log(`ffmpeg process exited with code ${code} and signal ${signal}`);
ffmpegPid = null; // Reset ffmpegPid when streaming is done
// HLS files remain for potential cleanup
});
res.send(`
bypassv - Streaming
Streaming Video...
0:00 / ${durationStr}
`);
});
});
// Stop streaming route
app.post('/stop', (req, res) => {
if (ffmpegPid) {
console.log(`Stopping ffmpeg process with PID: ${ffmpegPid}`);
exec(`kill -9 ${ffmpegPid}`, (error) => {
if (error) {
console.error(`Error stopping ffmpeg process: ${error.message}`);
return res.status(500).send('Error stopping stream.');
}
console.log('ffmpeg process stopped successfully.');
ffmpegPid = null; // Reset ffmpegPid
});
}
// Delete HLS files
deleteHLSFiles();
return res.send('Streaming has been stopped and HLS files deleted.');
});
// Start the server
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}`);
});