Important
This is an independent open source project and is not affiliated with, endorsed by, or supported by Milestone Systems. XProtect is a trademark of Milestone Systems A/S.
A Milestone XProtect® MIP device driver that receives direct RTMP push streams and passes H.264 video through to Milestone. Push from OBS, FFmpeg, Drones, or any RTMP-capable source directly into XProtect -- no intermediate media server required.
DJI test
demo_dji.mp4
Multiple streams test
demo.mp4
Demo Vids: Video courtesy of Dronestock https://dronestock.com/
- Download and run the installer from the Releases page
- Add hardware in Management Client (see Installation for details)
- Point your RTMP source (OBS, drone, encoder, ...) at
rtmp://<milestone-server>:<port>/<stream-path>
Requirements: Milestone XProtect® (Professional+, Expert, Corporate, or Essential+) with a Recording Server.
- Download
RTMPDriver-vX.X-Setup.exefrom the Releases page - Run the installer as Administrator -- it stops the Recording Server, copies the driver files, and starts the service automatically
- Download the
.zipfrom the Releases page - Unblock the ZIP before extracting -- Windows marks downloaded files as untrusted (Mark of the Web). Right-click the
.zip→ Properties → check Unblock → OK. If you skip this, Windows will block the driver DLLs and they will fail to load. Alternatively, in PowerShell:Unblock-File -Path .\RTMPDriver-*.zip - Stop the Milestone XProtect® Recording Server service
- Create a
MIPDriversfolder inC:\Program Files\Milestone\(if it doesn't already exist) - Extract the release into
C:\Program Files\Milestone\MIPDrivers\RTMPDriver\
- Start the Milestone XProtect® Recording Server service
After installing, add new hardware in the Management Client:
Add.Instance.Tutorial.mp4
Credentials:
Milestone requires a credential to connect, even though this driver does not verify them. Add any username/password combination (e.g. root / pass or just leave empty) and make sure it is checked.
Factory Default: If you use factory default as credentials, then you need to select manually the driver (Hardware Model) in the Add Hardware Tab, that Tab where you specifiy the Address and port.
Note
The port you enter (Add Hardware Tab) becomes the RTMP listening port (e.g. 8783). The wizard defaults to port 80, so you must change it to your desired RTMP port. You can adjust the port later in the Server Port hardware setting.
To add multiple instances, use localhost with a different port for each one. Each instance runs its own RTMP server, so every instance needs a unique port.
Caution
Each driver instance must use a unique port. If two instances share the same port, the second one will fail to add and shown as not responding.
Push an RTMP stream to rtmp://<milestone-server>:<port>/<stream-path> from any RTMP-capable source. The video encoder must be set to H.264.
- Go to Settings > Stream
- Set Service to Custom...
- Set Server to
rtmp://<milestone-server>:8783 - Set Stream Key to
stream1(or whichever stream path you configured) - Under Settings > Output, ensure the video encoder is set to x264 (H.264)
Useful for testing or scripted scenarios:
# Push a test pattern at 30fps to stream1
ffmpeg -re -f lavfi -i testsrc2=size=640x480:rate=30 \
-c:v libx264 -preset ultrafast -tune zerolatency -g 30 \
-f flv rtmp://localhost:8783/stream1
# Push a local file
ffmpeg -re -i input.mp4 -c:v libx264 -f flv rtmp://localhost:8783/stream1All settings are configured in the Management Client. Hardware settings apply to the entire driver; device settings are per-camera. Changes take effect immediately.
| Setting | Default | Description |
|---|---|---|
| Server Port | (from URI) | RTMP listening port. Initially set from the port entered in the Add Hardware wizard. Can be changed here afterwards. |
| Show Stream Offline Info | true |
Show a test pattern with device name and RTMP URL when offline. When disabled, a black frame is shown instead. |
| Max Concurrent Connections | 32 |
Maximum simultaneous RTMP connections across all IPs (1--1000). Additionally, each individual IP is limited to 16 concurrent connections. |
| Enable Rate Limiter | true |
Per-IP connection rate limiting |
| Rate Limit Max Requests Per Second | 10 |
Maximum new connections per second per IP (1--1000) |
Note
Make sure to open the Server Port (TCP) on Windows Firewall and any network firewalls between the stream source and the Milestone server.
Caution
Each driver instance must use a unique port. If the port is already in use by another instance or application, the driver will fail to start and the hardware will show as not responding. Change the Server Port to resolve the conflict.
| Setting | Default | Description |
|---|---|---|
| RTMP Push Stream Path | /stream1 -- /stream16 |
The RTMP path this camera listens on |
Note
The RTMP protocol has no built-in authentication. The configurable RTMP Push Stream Path per camera acts like a stream key -- if you suspect a URL is being misused, simply change the path. For additional security, use network/firewall rules to restrict access.
Each camera device exposes two events that can be used in Rules and Alarm Definitions within the Management Client:
| Event | Triggered when |
|---|---|
| RTMP Stream Started | An RTMP source begins pushing to the stream path |
| RTMP Stream Stopped | The RTMP source disconnects or stops publishing |
Use these to trigger recordings, send notifications, activate outputs, or raise alarms whenever a stream comes online or goes offline.
The driver enforces several timeouts to prevent idle or misbehaving connections from occupying server resources:
| Timeout | Duration | Description |
|---|---|---|
| Publish Timeout | 10 seconds | Clients that connect but never publish are disconnected |
| Video Data Timeout | 15 seconds | Publishers that stop sending video data are disconnected |
| TCP Receive Timeout | 30 seconds | Connections that stop sending any data are disconnected |
| Problem | Solution |
|---|---|
| No video in Smart Client | Check that the stream path in OBS/FFmpeg matches the camera's configured path. Check the driver log for connection/publish messages. |
| Stream connects but no video | Ensure you are sending H.264 (not HEVC/H.265). Check the log for SPS/PPS messages to confirm video data is arriving. |
| DLLs blocked / driver not loading after extraction | Right-click the original .zip → Properties → Unblock, then re-extract. Or run Get-ChildItem -Path .\RTMPDriver -Recurse | Unblock-File in PowerShell. See Installation step 2. |
| "Hardware not responding" in Management Client | Verify the Recording Server service is running and the driver DLLs are in the correct path. |
| Port already in use | Another instance or application is using this port. Change the Server Port in hardware settings to a different value. Each driver instance must use a unique port. |
| "Stream is already being published to" | Only one source can push to a given stream path at a time. Stop the existing stream before starting a new one. |
| Connection rejected / rate limited | The rate limiter is blocking connections from your IP. Increase Rate Limit Max Requests Per Second or disable the rate limiter in hardware settings. |
Driver logs are written to:
C:\ProgramData\Milestone\XProtect Recording Server\Logs\DriverFramework_RTMPDriver.log
- H.264 only -- HEVC/H.265 and other codecs are not supported at this time
┌───────────┐ ┌───────────┐ ┌───────────┐
│ OBS │ │ FFmpeg │ │ Drone │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
│ RTMP push │ RTMP push │
▼ ▼ ▼
┌─────────────────────────────────────────┐
│ RTMPDriver (this project) │
│ │
│ RTMP Server (:8783) │
│ /stream1 /stream2 ... /stream16 │
│ │
│ H.264 passthrough ── no transcoding │
└─────────────────┬───────────────────────┘
│
│ MIP Driver Framework
▼
┌─────────────────────────────────────────┐
│ Milestone XProtect® Recording Server │
└─────────────────────────────────────────┘
- Open
RTMPDriver.slnin Visual Studio (2019 or later) - Restore NuGet packages (the Milestone VideoOS SDK packages require Visual Studio -- they do not resolve via CLI)
- Build the solution
- The output is automatically placed in
C:\Program Files\Milestone\MIPDrivers\RTMPDriver\
Note
The build events stop and start the Milestone XProtect® Recording Server service automatically. Make sure Visual Studio is running as Administrator.
To build locally (Release + ZIP + installer):
.\build.ps1Requires Visual Studio (MSBuild), NuGet, and optionally NSIS for the installer. The script skips the installer if NSIS is not installed.
Releases are built automatically by GitHub Actions when you push a version tag.
- Update the version in two files:
RTMPDriver/Config/Constants.cs-- changeDriverVersionRTMPDriver/Properties/AssemblyInfo.cs-- changeAssemblyVersionandAssemblyFileVersion
- Commit the version bump
- Tag the commit with the matching version and push:
git tag v1.1.0 git push origin main --tags
- GitHub Actions will automatically build the Release configuration and publish a
RTMPDriver-v1.1.0.zipandRTMPDriver-v1.1.0-Setup.exeto the Releases page
The CI build uses /p:PreBuildEvent= /p:PostBuildEvent= to skip the Milestone service stop/start that normally happens during local development builds (the service doesn't exist in CI).
Contributions are welcome! Feel free to open issues or submit pull requests.
If you have feature requests, please open a GitHub Issue.
This project is licensed under the MIT License.
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This is an independent open source project and is not affiliated with, endorsed by, or supported by Milestone Systems. XProtect is a trademark of Milestone Systems A/S.
Caution
Use at your own risk. This driver interacts directly with your Milestone installation. Always test in a non-production environment first.