0% found this document useful (0 votes)
4 views

Api

This document is a Node.js application using Express to create a video streaming service with two proxy endpoints: one for fetching playlists and another for video segments. It validates required parameters for each request and rewrites URLs for video segments accordingly. Additionally, it serves a video player webpage that utilizes HLS.js and Plyr for playback functionality.

Uploaded by

mayankk6582
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Api

This document is a Node.js application using Express to create a video streaming service with two proxy endpoints: one for fetching playlists and another for video segments. It validates required parameters for each request and rewrites URLs for video segments accordingly. Additionally, it serves a video player webpage that utilizes HLS.js and Plyr for playback functionality.

Uploaded by

mayankk6582
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 4

const express = require('express');

const axios = require('axios');


const app = express();
const PORT = process.env.PORT || 3000;

// Proxy endpoint for the playlist


app.get('/api/stream', async (req, res) => {
const { v, start, Policy, 'Key-Pair-Id': KeyPairId, Signature, quality } =
req.query;

// Check for required parameters


if (!v || !start || !Policy || !KeyPairId || !Signature) {
return res.status(400).json({ error: 'Missing required parameters.' });
}

const originalApiUrl = `https://live-to-rec.vercel.app/?v=$


{encodeURIComponent(v)}&start=${encodeURIComponent(start)}&Policy=$
{encodeURIComponent(Policy)}&Key-Pair-Id=$
{encodeURIComponent(KeyPairId)}&Signature=$
{encodeURIComponent(Signature)}&quality=${quality || ''}`;

try {
const response = await axios.get(originalApiUrl);
const playlist = response.data;

const rewrittenPlaylist = playlist.replace(/(https:\/\/[^\s]+)/g,


(originalUrl) => {
const extractedQuality = originalUrl.match(/quality=(\d+)/)?.[1] || '';
return `/api/segment?v=${encodeURIComponent(v)}&start=${start}&Policy=$
{encodeURIComponent(Policy)}&Key-Pair-Id=$
{encodeURIComponent(KeyPairId)}&Signature=$
{encodeURIComponent(Signature)}&quality=${extractedQuality}`;
});

res.setHeader('Content-Type', 'application/vnd.apple.mpegurl');
res.send(rewrittenPlaylist);
} catch (error) {
console.error('Error fetching the playlist:', error.message);
res.status(500).json({ error: 'Failed to fetch the playlist.' });
}
});

// Proxy endpoint for video segments


app.get('/api/segment', async (req, res) => {
const { v, start, Policy, 'Key-Pair-Id': KeyPairId, Signature, quality } =
req.query;

// Check for required parameters


if (!v || !start || !Policy || !KeyPairId || !Signature || !quality) {
return res.status(400).json({ error: 'Missing required parameters.' });
}

const originalApiUrl = `https://live-to-rec.vercel.app/?v=$


{encodeURIComponent(v)}&start=${encodeURIComponent(start)}&Policy=$
{encodeURIComponent(Policy)}&Key-Pair-Id=$
{encodeURIComponent(KeyPairId)}&Signature=$
{encodeURIComponent(Signature)}&quality=${quality}`;

try {
const response = await axios.get(originalApiUrl, { responseType:
'stream' });

res.setHeader('Content-Type', response.headers['content-type']);
response.data.pipe(res);
} catch (error) {
console.error('Error fetching the segment:', error.message);
res.status(500).json({ error: 'Failed to fetch the segment.' });
}
});

// Video player webpage


app.get('/player', (req, res) => {
const { v, start, Policy, 'Key-Pair-Id': KeyPairId, Signature } = req.query;

// Check for required parameters


if (!v || !start || !Policy || !KeyPairId || !Signature) {
return res.status(400).send('Missing required parameters.');
}

const streamUrl = `/api/stream?v=${encodeURIComponent(v)}&start=$


{encodeURIComponent(start)}&Policy=${encodeURIComponent(Policy)}&Key-Pair-Id=$
{encodeURIComponent(KeyPairId)}&Signature=${encodeURIComponent(Signature)}`;

const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Video Player</title>

<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script src="https://cdn.plyr.io/3.6.8/plyr.js"></script>
<script src="https://unpkg.com/lucide@latest"></script>
<script disable-devtool-auto="true" src="https://cdn.jsdelivr.net/npm/disable-
devtool" clear-log="true" disable-select="true" disable-copy="true" disable-
cut="true" disable-paste="true"></script>
<link rel="stylesheet" href="https://nexttoppers.github.io/plyr.css" />
<script src="https://cdn.tailwindcss.com/"></script>
<link rel="stylesheet" href="https://static.pw.live/fonts/reddit/font.css">
<link rel="stylesheet" href="https://nexttoppers.github.io/plyr1.css" />
<script src="https://cdn.plyr.io/3.7.8/plyr.js"></script>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<style>
.container {
margin: 95px auto;
width: 720px;
}
video {
width: 100%;
}
/* Remove default blue overlay on focus */
.plyr__controls button:focus,
.plyr__control:focus-visible,
.plyr__control:focus {
outline: none !important;
box-shadow: none !important;
}
</style>
</head>
<body>
<div class='container'>
<span class="dots"></span>
<video controls crossorigin playsinline></video>
</div>

<script>
document.addEventListener('DOMContentLoaded', () => {
const controls = ['play-large', 'rewind', 'play', 'fast-forward',
'progress', 'current-time', 'duration', 'mute', 'volume', 'settings',
'fullscreen'];
const source = '${streamUrl}';
const video = document.querySelector('video');
const defaultOptions = {
controls,
captions: { active: true, update: false, language: 'auto' }
};

if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(source);
hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
const availableQualities = hls.levels.map((l) => l.height);
defaultOptions.quality = {
default: availableQualities[0],
options: availableQualities,
forced: true,
onChange: (e) => updateQuality(e),
};
const player = new Plyr(video, defaultOptions);
});
hls.attachMedia(video);
window.hls = hls;
} else {
const player = new Plyr(video, defaultOptions);
}

function updateQuality(newQuality) {
window.hls.levels.forEach((level, levelIndex) => {
if (level.height === newQuality) {
window.hls.currentLevel = levelIndex;
}
});
}
});
</script>
</body>
</html>

`;

res.send(html);
});
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

You might also like