JSPM

hls-streamer

2.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 15
  • Score
    100M100P100Q67462F
  • License MIT

Lightweight HLS streaming from MP3 files on demand, without temporary files or ffmpeg dependency

Package Exports

  • hls-streamer

Readme

HLS Streamer

npm version License: MIT TypeScript

HLS Streamer is a lightweight npm package that creates and streams HLS (HTTP Live Streaming) from MP3 files on demand, without storing temporary files or requiring ffmpeg.

โœจ Features

  • ๐Ÿš€ Zero Dependencies - No ffmpeg required
  • ๐Ÿ’พ No Temporary Files - Stream directly from source
  • โšก Fast Startup - Optional smaller initial segments for quick playback start
  • ๐ŸŽฏ TypeScript Support - Full type definitions included
  • ๐Ÿ”ง Configurable - Customizable segment sizes and naming
  • ๐Ÿ“ฑ Memory Efficient - Byte-range streaming with minimal memory footprint

๐Ÿ“ฆ Installation

npm install hls-streamer
yarn add hls-streamer
pnpm add hls-streamer

๐Ÿš€ Quick Start

Basic Usage

import { HlsStreamer } from 'hls-streamer';

const hls = new HlsStreamer({
  filePath: 'path/to/audio.mp3',
  segmentSizeKB: 512,
  fileName: 'segment',
  baseUrl: 'segments/session-123',
  enableFastStart: true
});

// Generate M3U8 playlist
const playlist = await hls.createM3U8();

// Get file buffer for specific byte range
const buffer = await hls.getFileBuffer(startByte, endByte);

Express.js Integration

import express from 'express';
import { HlsStreamer } from 'hls-streamer';

const app = express();

// Serve M3U8 playlist
app.get('/stream/:sessionId/playlist.m3u8', async (req, res) => {
  const hls = new HlsStreamer({
    filePath: getFilePath(req.params.sessionId),
    baseUrl: `stream/${req.params.sessionId}`,
    enableFastStart: true
  });

  res.setHeader('Content-Type', 'application/vnd.apple.mpegurl');
  res.send(await hls.createM3U8());
});

// Serve segment files
app.get('/stream/:sessionId/:start/:end/:filename', async (req, res) => {
  const hls = new HlsStreamer({
    filePath: getFilePath(req.params.sessionId),
    baseUrl: `stream/${req.params.sessionId}`
  });

  const start = parseInt(req.params.start);
  const end = parseInt(req.params.end);

  res.setHeader('Content-Type', 'audio/mpeg');
  res.setHeader('Accept-Ranges', 'bytes');
  res.send(await hls.getFileBuffer(start, end));
});

๐Ÿ› ๏ธ API Reference

HlsStreamer

Constructor Options

interface HlsStreamerOptions {
  /** Path to the MP3 file */
  filePath: string;
  /** Segment size in KB (default: 512) */
  segmentSizeKB?: number;
  /** Base filename for segments (default: "file") */
  fileName?: string;
  /** Base URL path for segment URLs */
  baseUrl?: string;
  /** Enable smaller initial segments for faster startup */
  enableFastStart?: boolean;
}

Methods

createM3U8(): Promise<string>

Generates an HLS M3U8 playlist file content.

Returns: M3U8 playlist as a string

getFileBuffer(startByte: number, endByte: number): Promise<Buffer>

Retrieves a specific byte range from the MP3 file.

Parameters:

  • startByte - Starting byte position (inclusive)
  • endByte - Ending byte position (exclusive)

Returns: Buffer containing the requested byte range

getSegmentDuration(segmentIndex: number): Promise<number>

Gets the accurate duration of a specific segment.

Parameters:

  • segmentIndex - Zero-based segment index

Returns: Duration in seconds

Error Handling

The package includes custom error types for better error handling:

import {
  FileNotFoundError,
  InvalidFileError,
  InvalidRangeError,
  InvalidParameterError
} from 'hls-streamer';

try {
  const hls = new HlsStreamer({ filePath: 'nonexistent.mp3' });
} catch (error) {
  if (error instanceof FileNotFoundError) {
    console.error('File not found:', error.message);
  }
}

๐Ÿ“‹ Configuration Options

Option Type Default Description
filePath string required Path to the MP3 file
segmentSizeKB number 512 Size of each segment in KB
fileName string "file" Base name for segment files
baseUrl string "" Base URL path for segment URLs
enableFastStart boolean false Use smaller initial segments for faster startup

๐ŸŽฏ Use Cases

  • Audio Streaming Services - Stream music without pre-processing
  • Podcast Platforms - On-demand episode streaming
  • Educational Platforms - Stream lecture recordings
  • Voice Message Systems - Real-time audio message playback
  • Audio Books - Chapter-based streaming

๐Ÿ”ง Advanced Examples

Custom Segment Sizing

const hls = new HlsStreamer({
  filePath: 'large-audio-file.mp3',
  segmentSizeKB: 1024, // 1MB segments for better quality
  enableFastStart: true // First segments will be 256KB and 512KB
});

Dynamic File Paths

class AudioStreamer {
  async streamAudio(userId: string, audioId: string) {
    const filePath = await this.getAudioPath(userId, audioId);

    const hls = new HlsStreamer({
      filePath,
      baseUrl: `audio/${userId}/${audioId}`,
      fileName: `audio-${audioId}`,
      segmentSizeKB: 256 // Smaller segments for mobile
    });

    return hls.createM3U8();
  }
}

๐Ÿงช Testing

npm test
npm run test:watch
npm run test:coverage

๐Ÿ—๏ธ Building

npm run build        # Build both ESM and CJS
npm run build:esm    # Build ES modules
npm run build:cjs    # Build CommonJS

๐Ÿ“„ License

MIT License - see LICENSE file for details.

๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

๐Ÿ“ž Support


Made with โค๏ธ by LordVersA