Lazy Node.js FFMpeg wrapper for streaming RTSP into MotionJPEG. It runs FFMpeg process only when someone is subscribed to its data event. Every data event contains one image Buffer object.
- Features
- Prerequisites
- Installation
- Usage Examples
- API Documentation
- Events
- Error Handling
- Troubleshooting
- Contributing
- License
- Lazy Loading: FFMpeg process starts only when clients are listening
- Automatic Cleanup: Process stops when no listeners remain
- Motion JPEG Streaming: Converts RTSP streams to MJPEG format
- Customizable Output: Configure framerate, resolution, and quality
- Multiple Stream Support: Handle multiple camera streams simultaneously
- Event-Driven: Simple event-based API
- Node.js: Version 6 or higher
- FFmpeg: Must be installed on your system
Check out the complete demo application to see rtsp-ffmpeg in action! The demo includes:
- 🎥 Real-time RTSP to JPEG streaming
- 🖥️ Modern web interface with controls
- 📊 Live FPS and frame statistics
- Ready-to-run example with public test streams
-
Install FFmpeg on your system:
- macOS:
brew install ffmpeg - Ubuntu/Debian:
sudo apt-get install ffmpeg - Windows: Download from FFmpeg official website
- macOS:
-
Install the package in your project:
npm install rtsp-ffmpeg
This example demonstrates streaming RTSP to a web browser using Socket.io.
const app = require('express')();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const rtsp = require('rtsp-ffmpeg');
server.listen(6147, () => {
console.log('Server listening on port 6147');
});
// RTSP stream URL (replace with your own stream URL)
const uri = 'rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov';
const stream = new rtsp.FFMpeg({ input: uri });
io.on('connection', (socket) => {
const pipeStream = (data) => {
socket.emit('data', data.toString('base64'));
};
// Add listener when client connects
stream.on('data', pipeStream);
// Remove listener when client disconnects
socket.on('disconnect', () => {
stream.removeListener('data', pipeStream);
});
});
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});Simple approach (not recommended for production):
<!DOCTYPE html>
<html>
<head>
<title>RTSP Stream</title>
</head>
<body>
<img id="img" alt="Live stream" />
<script src="/socket.io/socket.io.js"></script>
<script>
const img = document.getElementById('img');
const socket = io('');
socket.on('data', (data) => {
img.src = 'data:image/jpeg;base64,' + data;
});
</script>
</body>
</html>Note: For better performance with large resolution images or high framerates, use canvas rendering instead of direct image source updates. See the canvas example by Seikon.
Testing: The example above uses a public demo stream that may not always be available. Replace the URL with your own RTSP stream. If you need a test stream, you can set up a local RTSP server using tools like mediamtx or FFmpeg's built-in RTSP server.
For handling multiple camera streams, see /example/server.js.
For high-resolution streams using canvas rendering, check /example/server-canvas.js.
Create a new FFMpeg stream instance.
const FFMpeg = require('rtsp-ffmpeg').FFMpeg;
const stream = new FFMpeg(options);| Option | Type | Required | Default | Description |
|---|---|---|---|---|
input |
String | Yes | - | Stream URI (e.g., rtsp://localhost:8554/stream) |
rate |
Number | No | 10 |
Output framerate (frames per second) |
resolution |
String | No | - | Output resolution in WxH format (e.g., '640x480') |
quality |
Number | No | 3 |
JPEG compression quality level (1-31, where 1 is highest quality and 31 is lowest quality) |
arguments |
Array | No | [] |
Custom FFmpeg arguments |
const stream = new FFMpeg({
input: 'rtsp://localhost:8554/stream',
rate: 10,
resolution: '640x480',
quality: 3
});Manually start the FFMpeg process. Typically not needed as the process starts automatically when listeners are added.
stream.start();Stop the FFMpeg process and close the stream.
stream.stop();Restart the FFMpeg process with current settings.
stream.restart();Path or command to the FFmpeg executable. Modify this if FFmpeg is not in your system PATH.
const FFMpeg = require('rtsp-ffmpeg').FFMpeg;
// Windows example
FFMpeg.cmd = 'C:\\ffmpeg\\bin\\ffmpeg.exe';
// Linux example
FFMpeg.cmd = '/usr/local/bin/ffmpeg';The FFMpeg instance inherits from Node.js EventEmitter and emits the following events:
Emitted when a complete JPEG frame is received.
Callback Arguments:
buffer(Buffer): Image data as a Buffer object
Example:
stream.on('data', (imageBuffer) => {
// Process the image buffer
console.log('Received frame, size:', imageBuffer.length);
});Emitted when the FFMpeg process starts.
Example:
stream.on('start', () => {
console.log('Stream started');
});Emitted when the FFMpeg process stops.
Example:
stream.on('stop', () => {
console.log('Stream stopped');
});Cause: FFmpeg executable not found in system PATH.
Solution:
- Ensure FFmpeg is installed on your system
- Set the correct path using
FFMpeg.cmd:
const FFMpeg = require('rtsp-ffmpeg').FFMpeg;
FFMpeg.cmd = '/path/to/ffmpeg'; // or 'C:\\path\\to\\ffmpeg.exe' on WindowsCause: Unable to connect to RTSP stream (invalid URL, network issues, authentication failure).
Solution:
- Verify the RTSP URL is correct
- Check network connectivity
- Ensure authentication credentials are included in the URL if required:
rtsp://username:password@host:port/path
stream.on('error', (error) => {
console.error('Stream error:', error);
// Implement retry logic or notify users
});- Check FFmpeg installation: Run
ffmpeg -versionin terminal - Verify RTSP URL: Test the URL with FFmpeg directly:
ffmpeg -i rtsp://your-stream-url -f image2 -vframes 1 test.jpg
- Check network connectivity: Ensure the RTSP source is reachable
- Firewall settings: Ensure ports are not blocked
- Increase the
rateoption value - Check network bandwidth
- Verify source stream quality
- Reduce
resolutionto lower values - Increase
qualityvalue (lower quality, smaller file size) - Reduce
rateto lower framerate
The process should automatically stop when all listeners are removed. If it doesn't:
// Manually stop the stream
stream.removeAllListeners('data');
stream.stop();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.
- Andrew D.Laptev - Original author
- Seikon - Canvas rendering examples
- Igor Koval - Contributions
This project is licensed under the MIT License - see the LICENSE file for details.
Repository: agsh/rtsp-ffmpeg
NPM Package: rtsp-ffmpeg