A powerful Node.js library to create a seekable, chunked HTTP stream for remote audio files. It intelligently handles byte-range requests to start streaming from any point in the audio, and for WebM files, it performs on-the-fly remuxing to ensure a valid, playable stream even when seeking.
- Time-based Seeking: Start streaming from a specific timestamp (in milliseconds).
- Chunked Streaming: Fetches content in small, manageable chunks, ideal for production servers and efficient memory usage.
- WebM/Opus Seeking: Automatically remuxes WebM container headers to provide a valid stream when seeking.
- Metadata Detection: Probes the file to determine container, codec, duration, and content length.
- Wide Format Support: Works with MP3, WebM (Opus/Vorbis), AAC, and FLAC.
- Resilient: Handles servers that don't support range requests gracefully.
npm install seekable-streamimport { seekableStream } from 'seekable-stream'; async function getFullStream() { const url = 'https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3'; try { const { stream, meta } = await seekableStream(url); console.log('Stream metadata:', meta); // Now you can pipe the stream to a speaker, a file, or a processing library. // For example, saving it to a file: // import fs from 'fs'; // stream.pipe(fs.createWriteStream('audio.mp3')); stream.on('data', (chunk) => { console.log(`Received chunk of size: ${chunk.length}`); }); stream.on('end', () => { console.log('Stream finished.'); }); } catch (error) { console.error('Error getting stream:', error); } } getFullStream();This example shows how to start streaming an MP3 file from the 30-second mark.
import { seekableStream } from 'seekable-stream'; import fs from 'fs'; async function seekInMP3() { const url = 'https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3'; const startTimeMs = 30000; // Start at 30 seconds try { const { stream, meta } = await seekableStream(url, startTimeMs); console.log('Streaming MP3 from 30s mark...'); console.log('Metadata:', meta); // Pipe the partial stream to a file const writer = fs.createWriteStream('partial_audio.mp3'); stream.pipe(writer); writer.on('finish', () => { console.log('Partial MP3 stream saved to partial_audio.mp3'); }); } catch (error) { console.error('Error seeking in MP3:', error); } } seekInMP3();This example demonstrates seeking to 20 seconds in a WebM/Opus file and decoding the audio to raw PCM chunks in real-time using prism-media. This is useful for applications like music bots.
import { seekableStream } from 'seekable-stream'; import prism from 'prism-media'; async function processWebM() { const url = 'https://raw.githubusercontent.com/LunaStream/QuickMedia/refs/heads/main/lab/sample/videoplayback.webm'; const startTimeMs = 20000; // Start at 20 seconds try { const { stream, meta } = await seekableStream(url, startTimeMs); console.log('Streaming WebM from 20s mark...'); console.log('Metadata:', meta); // Setup prism-media pipeline to decode WebM/Opus to raw PCM const demuxer = new prism.opus.WebmDemuxer(); const decoder = new prism.opus.Decoder({ frameSize: 960, channels: 2, rate: 48000 }); const pcmStream = stream.pipe(demuxer).pipe(decoder); let chunksProcessed = 0; pcmStream.on('data', (chunk) => { chunksProcessed++; // Here you can process the raw PCM audio chunk console.log(`[Real-time] Processing PCM audio chunk #${chunksProcessed}, Size: ${chunk.length} bytes`); }); pcmStream.on('end', () => { console.log(`\nStream finished. Total PCM chunks processed: ${chunksProcessed}`); }); } catch (error) { console.error('Error processing WebM stream:', error); } } processWebM();seekableStream(urlString, startTime, endTime, httpHeaders)
urlString(string, required): The URL of the audio file. Supportshttp:,https:, andfile:.startTime(number, optional): The time in milliseconds to start streaming from. Defaults to0.endTime(number, optional): The time in milliseconds to stop streaming. Defaults to the end of the file.httpHeaders(object, optional): Custom headers to send with the HTTP requests (e.g., for authentication).
Returns: Promise<{ stream, meta }>
An object containing:
stream: A Node.jsReadablestream with the audio data.meta: An object with metadata about the stream and file.contentType(string): The MIME type of the content (e.g.,audio/mpeg).contentLength(number): The total size of the file in bytes.durationMs(number): The total duration of the audio in milliseconds (can be estimated).acceptRanges(string): Indicates if the server supports byte ranges.codec(object): Information about the detected audio codec.container(string): e.g.,mp3,webm.codecName(string): e.g.,A_OPUS,flac.
resolvedRange(object): The final byte range being streamed ({ start, end }).webmHeaderPrepended(boolean):trueif the stream is a remuxed WebM stream.warnings(Array): An array of any non-fatal warnings that occurred.
The library is designed to work with common web audio formats and has specific support for:
- MP3 (
audio/mpeg) - WebM (
audio/webm, with Opus or Vorbis codecs) - Ogg (
application/ogg, with Opus or Vorbis codecs) - AAC (
audio/aac) - FLAC (
audio/flac)