A JavaScript runtime parses and executes JavaScript code outside the browser. In browser environments, the runtime includes APIs for DOM interaction, event handling, and UI operations. These runtimes do not support backend tasks. Node.js uses the V8 engine and a non-blocking I/O model to run JavaScript on servers without relying on a browser.

Node.js: Server-Side JavaScript Runtime

Node.js runs JavaScript outside the browser using the V8 engine. It connects with system-level APIs to perform networking, file I/O, and process management. It is used to build backend services, automation tasks, and command-line tools.

Example:

code
// Import core Node.js modules
code
const http = require('http');
code
const fs = require('fs').promises;
code
const path = require('path');
code

code
// Create an HTTP server
code
const server = http.createServer(async (req, res) => {
code
try {
code
// Process management: Get CPU usage
code
const startUsage = process.cpuUsage();
code
code
// Handle different routes
code
if (req.url === '/') {
code
// File I/O: Read HTML file
code
const data = await fs.readFile(
code
path.join(__dirname, 'public', 'index.html'),
code
'utf8'
code
);
code
code
res.writeHead(200, { 'Content-Type': 'text/html' });
code
res.end(data);
code
} else if (req.url === '/api/data') {
code
// Networking: API endpoint
code
res.writeHead(200, { 'Content-Type': 'application/json' });
code
res.end(JSON.stringify({
code
message: "Hello from Node.js!",
code
pid: process.pid,
code
uptime: process.uptime(),
code
cpuUsage: process.cpuUsage(startUsage)
code
}));
code
} else {
code
res.writeHead(404);
code
res.end('Not Found');
code
}
code
} catch (err) {
code
console.error('Server error:', err);
code
res.writeHead(500);
code
res.end('Internal Server Error');
code
}
code
});
code

code
// Start the server
code
const PORT = process.env.PORT || 3000;
code
server.listen(PORT, () => {
code
console.log(`Server running on port ${PORT}`);
code
console.log(`Process ID: ${process.pid}`);
code
console.log(`Platform: ${process.platform}`);
code
});
code

code
// Demonstrate event loop with async operation
code
setImmediate(() => {
code
console.log('Event loop demo: setImmediate callback executed');
code
});
code

code
// File system watcher (demonstrating fs module)
code
if (process.env.NODE_ENV === 'development') {
code
fs.watch(path.join(__dirname, 'public'))
code
.on('change', (eventType, filename) => {
code
console.log(`File changed: ${filename} (${eventType})`);
code
});
code
}

Explanation:

  • fs.promises enables non-blocking file operations using Promises (readFile, watch, etc.)
  • path helps build file paths in a cross-platform-safe way.
  • The callback receives req (request) and res (response) objects for handling HTTP traffic.
  • Marked async to support await for asynchronous file I/O and system calls.

For this to work completely, you'd want a public/index.html file:

code
<!DOCTYPE html>
code
<html>
code
<head>
code
<title>Node.js Demo</title>
code
</head>
code
<body>
code
<h1>Node.js Runtime Demo</h1>
code
<button id="fetchData">Get System Info</button>
code
<pre id="output"></pre>
code
<script>
code
document.getElementById('fetchData').addEventListener('click', async () => {
code
const response = await fetch('/api/data');
code
document.getElementById('output').textContent =
code
JSON.stringify(await response.json(), null, 2);
code
});
code
</script>
code
</body>
code
</html>

Explanation:

  • Attaches a click event listener to the button using its id.
  • Arrow function is declared async to handle asynchronous fetch operations.
  • Sends a GET request to the /api/data endpoint.
  • Returns a Response object containing the HTTP response from the server.

Node.js Execution Model

Node.js uses a non-blocking execution model built around asynchronous operations. V8 compiles JavaScript to machine code, and libuv manages system-level I/O. The event loop coordinates execution without blocking the main thread.

Example

code
const fs = require('fs');
code

code
fs.readFile('./data.txt', 'utf8', (err, data) => {
code
if (err) throw err;
code
console.log('File contents:', data);
code
});
code

code
console.log('Reading file...');

Explanation:

  • fs.readFile is non-blocking. The script continues execution and logs "Reading file...".
  • When the file read completes, its callback is pushed to the queue and executed later.

How Node.js Fits into Video Workflows

Node.js integrates into video workflows by managing backend tasks such as encoding orchestration, metadata processing, and API routing. Its asynchronous I/O model supports concurrent video uploads, format conversions, and stream control without blocking execution.

Manifest Generation and Video Metadata APIs

Node.js is used to build APIs that serve video manifests (like HLS .m3u8 or DASH .mpd) dynamically based on user entitlements or session tokens. These APIs also handle metadata retrieval, license generation requests (for DRM), and secure playback initialization.

code
app.get('/manifest/:videoId', async (req, res) => {
code
const videoId = req.params.videoId;
code
const manifest = await fetchManifest(videoId);
code
res.setHeader('Content-Type', 'application/vnd.apple.mpegurl');
code
res.send(manifest);
code
});

Explanation:

  • app.get('/manifest/:videoId', ...) defines an HTTP GET route in an Express application. The path includes a route parameter :videoId, allowing clients to request different manifest files by ID.
  • req.params.videoId extracts the videoId string from the URL. For example, a request to /manifest/abc123 sets videoId to 'abc123'.

This API route could serve adaptive bitrate manifests after performing access control or token verification.

Chunked Upload Handling for Video Ingest

Node.js handles multipart uploads for large media files. It streams uploaded video chunks directly to cloud storage without buffering the entire file in memory.

code
const stream = require('stream');
code
app.post('/upload', (req, res) => {
code
const uploadStream = createS3Stream();
code
req.pipe(uploadStream).on('finish', () => res.end('Upload complete'));
code
});

Explanation:

  • const stream = require('stream') imports Node.js's core stream module.
  • app.post('/upload', ...) defines an HTTP POST endpoint at /upload.
  • createS3Stream() initializes a writable stream that connects to an object storage service like AWS S3, MinIO, or Backblaze B2.

Real-Time Analytics for Video Sessions

Node.js runs real-time analytics pipelines by listening to playback session events, forwarding logs to services like Kafka, and storing session heatmaps in a NoSQL store. Due to its non-blocking nature, it handles high throughput logging with low latency.

Example: Capture and Forward Playback Events to Kafka

code
// server.ts
code

code
import express from 'express';
code
import { Kafka } from 'kafkajs';
code

code
const app = express();
code
app.use(express.json());
code

code
const kafka = new Kafka({ clientId: 'video-analytics', brokers: ['localhost:9092'] });
code
const producer = kafka.producer();
code

code
await producer.connect();
code

code
app.post('/analytics/event', async (req, res) => {
code
const { sessionId, videoId, event, timestamp } = req.body;
code

code
await producer.send({
code
topic: 'video-events',
code
messages: [
code
{
code
key: sessionId,
code
value: JSON.stringify({ videoId, event, timestamp }),
code
},
code
],
code
});
code

code
res.status(200).end();
code
});

Explanation:

  • clientId: 'video-analytics' assigns a unique identifier to this Kafka client instance for tracking and logging within the Kafka cluster.
  • brokers: ['localhost:9092'] specifies the Kafka broker address. Kafka producers connect here to publish messages.