A tool to grab streams from SLDP WebSocket servers and save/mux them
Project description
sldp-grabber
A small tool and Python library to grab streams from SLDP WebSocket servers.
- Connects to SLDP servers
- Saves raw H.264, AAC, or Opus
- Optionally muxes into MP4/MKV using
ffmpeg - Supports segmenting, reconnects, and live piping to tools like
ffplay - Exposes a clean
SLDPGrabberAPI for custom processing
Installation
From PyPI:
pip install sldp-grabber
From source:
git clone https://github.com/dgkn94/sldp-grabber.git
cd sldp-grabber
pip install .
Requirements:
-
Python 3.7+
-
websocket-client>=1.3.0 -
ffmpeginPATHfor MP4/MKV muxing (recommended) -
Optional:
ffplayfor live previewav(PyAV) for thumbnail/advanced processing examples
Quick Start (CLI)
Basic recording
sldp-grabber \
--url wss://example.com/app/stream \
--duration 60
- Writes
video.h264/audio.aacintorecordings/ - If
ffmpegis available and--no-muxis not set, also createsrecording.mp4
Keep only raw streams
sldp-grabber \
--url wss://example.com/app/stream \
--duration 30 \
--no-mux \
--keep-raw
Segment recording (e.g. 5-minute chunks)
sldp-grabber \
--url wss://example.com/app/stream \
--segment-duration 300
Each segment becomes its own raw/set of files and (optionally) MP4/MKV.
Live Preview with ffplay
You can mirror the live stream to another process while still recording.
Example: live H.264 preview while recording:
sldp-grabber \
--url wss://example.com/app/stream \
--pipe-h264-cmd "ffplay -fflags nobuffer -flags low_delay -f h264 -i -" \
--duration 60
What this does:
- Pipes Annex B H.264 to
ffplayvia stdin - Still writes to disk
- Still muxes to MP4 if enabled
Same idea works for audio using --pipe-aac-cmd.
Using as a Library
You can import and use SLDPGrabber directly.
Basic usage
from sldp_grabber import SLDPGrabber
grabber = SLDPGrabber(
url="wss://example.com/app/stream",
out_dir="recordings",
duration=30,
)
grabber.run() # blocks until done
Custom Frame Processing
You can hook into incoming frames using callbacks.
from sldp_grabber import SLDPGrabber
class FrameProcessor:
def __init__(self):
self.video_count = 0
self.audio_count = 0
def on_video_frame(self, data: bytes, meta: dict):
# data: Annex B H.264
self.video_count += 1
if meta.get("keyframe"):
print(f"Keyframe at TS={meta.get('timestamp')}")
def on_audio_frame(self, data: bytes, meta: dict):
# data: ADTS AAC or raw Opus
self.audio_count += 1
processor = FrameProcessor()
grabber = SLDPGrabber(
url="wss://example.com/app/stream",
out_dir="processed_recordings",
duration=10,
on_video_frame=processor.on_video_frame,
on_audio_frame=processor.on_audio_frame,
)
grabber.run()
print(
f"Processed {processor.video_count} video frames and "
f"{processor.audio_count} audio frames"
)
Example: Extract Thumbnails with PyAV
See examples/extract_thumbnails.py for a full script.
import os
import av
from sldp_grabber import SLDPGrabber
class ThumbnailExtractor:
def __init__(self, out_dir="thumbnails"):
os.makedirs(out_dir, exist_ok=True)
self.out_dir = out_dir
self.count = 0
self.codec = av.CodecContext.create("h264", "r")
def on_video_frame(self, data, meta):
try:
packet = av.packet.Packet(data)
frames = self.codec.decode(packet)
except av.AVError:
return
for frame in frames:
self.count += 1
path = os.path.join(self.out_dir, f"thumb_{self.count:04d}.jpg")
frame.to_image().save(path)
print(f"Saved {path}")
extractor = ThumbnailExtractor()
grabber = SLDPGrabber(
url="wss://example.com/app/stream",
out_dir="thumb_recordings",
duration=10,
on_video_frame=extractor.on_video_frame,
keep_raw=False,
)
grabber.run(create_mp4=False)
print(f"Saved {extractor.count} thumbnails")
Requires:
pip install av
CLI Options Overview
Run:
sldp-grabber --help
Key options:
-u, --url– (required) SLDP WebSocket URL--stream– Specific stream name (if multiple)-d, --duration– Seconds to record (0= until interrupted)--out-dir– Output directory (default:recordings)--segment-duration– Split into N-second segments--no-mux– Do not runffmpeg, keep only raw files--keep-raw– Keep.h264/.aac/.opusafter muxing--pipe-h264-cmd– Pipe H.264 to command via stdin--pipe-aac-cmd– Pipe AAC/Opus to command via stdin-H, --header– Extra HTTP headers (auth, cookies, etc.)--header-file– Load headers from file--strict– Fail fast on unsupported codecs--debug-ts– Save timestamps totimestamps.csv-v– Increase verbosity (-v= DEBUG)
Notes
-
Video is handled as H.264 (Annex B) when supported.
-
Audio is handled as AAC (ADTS) or raw Opus packets.
-
Muxing:
- H.264 + AAC → MP4
- H.264 + (no AAC) + Opus sidecar → MKV +
.opuskept
-
Designed to be simple to script against and easy to extend.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sldp_grabber-1.0.0.tar.gz.
File metadata
- Download URL: sldp_grabber-1.0.0.tar.gz
- Upload date:
- Size: 19.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d5e24d10aeeff325d0f393bf210625b446a012541d32bab11c91248f7152b5f
|
|
| MD5 |
2d099cce4704a097193ae0db1f623fac
|
|
| BLAKE2b-256 |
a058845682a3fbbfd2dc333e49be7b8ae6a5cd81bd51f54a512cee6b7f5588e9
|
File details
Details for the file sldp_grabber-1.0.0-py3-none-any.whl.
File metadata
- Download URL: sldp_grabber-1.0.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55c57884a01b84351d1bd0d07a3d872720d24a207e48b8fe67be1c7863ece773
|
|
| MD5 |
c004aaf46625e3f5239abb9fdf84c0c1
|
|
| BLAKE2b-256 |
96bc1bbcd6c6c78d10e5c49aaac9e745a857d8b6586196c8588ad5a6cada2934
|