_MediaMTX_ is a ready-to-use and zero-dependency real-time media server and media proxy that allows to publish, read, proxy, record and playback video and audio streams. It has been conceived as a "media router" that routes media streams from one end to the other, with a focus on efficiency and portability.
- [Publish](https://mediamtx.org/docs/usage/publish) live streams to the server with SRT, WebRTC, RTSP, RTMP, HLS, MPEG-TS, RTP, using FFmpeg, GStreamer, OBS Studio, Python , Golang, Unity, web browsers, Raspberry Pi Cameras and more.
- [Read](https://mediamtx.org/docs/usage/read) live streams from the server with SRT, WebRTC, RTSP, RTMP, HLS, using FFmpeg, GStreamer, VLC, OBS Studio, Python , Golang, Unity, web browsers and more.
- Streams are automatically converted from a protocol to another
- Serve several streams at once in separate paths
- Reload the configuration without disconnecting existing clients (hot reloading)
- [Serve always-available streams](https://mediamtx.org/docs/usage/always-available) even when the publisher is offline
- [Record](https://mediamtx.org/docs/usage/record) streams to disk in fMP4 or MPEG-TS format
- [Playback](https://mediamtx.org/docs/usage/playback) recorded streams
- [Authenticate](https://mediamtx.org/docs/usage/authentication) users with internal, HTTP or JWT authentication
- [Forward](https://mediamtx.org/docs/usage/forward) streams to other servers
- [Proxy](https://mediamtx.org/docs/usage/proxy) requests to other servers
- [Control](https://mediamtx.org/docs/usage/control-api) the server through the Control API
- [Extract metrics](https://mediamtx.org/docs/usage/metrics) from the server in a Prometheus-compatible format
- [Monitor performance](https://mediamtx.org/docs/usage/performance) to investigate CPU and RAM consumption
- [Run hooks](https://mediamtx.org/docs/usage/hooks) (external commands) when clients connect, disconnect, read or publish streams
- Compatible with Linux, Windows and macOS, does not require any dependency or interpreter, it's a single executable
- ...and many [others](https://mediamtx.org/docs/kickoff/introduction).
================================================
FILE: SECURITY.md
================================================
# Security
Check the [Security page](https://mediamtx.org/docs/other/security) on the website.
================================================
FILE: api/.redocly.yaml
================================================
extends:
- recommended
rules:
operation-4xx-response: off
================================================
FILE: api/openapi.yaml
================================================
openapi: 3.0.0
info:
version: 1.0.0
title: MediaMTX API
description: API of MediaMTX, a server and proxy that supports various protocols.
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: http://localhost:9997
security: []
components:
schemas:
OKStatus:
type: string
enum: [ok]
ErrorStatus:
type: string
enum: [error]
PathSourceType:
type: string
enum:
- hlsSource
- redirect
- rpiCameraSource
- rtmpConn
- rtmpsConn
- rtmpSource
- rtspSession
- rtspSource
- rtspsSession
- srtConn
- srtSource
- mpegtsSource
- rtpSource
- webRTCSession
- webRTCSource
PathReaderType:
type: string
enum:
- hlsMuxer
- rpiCameraSecondary
- rtmpConn
- rtmpsConn
- rtspConn
- rtspSession
- rtspsConn
- rtspsSession
- srtConn
- webRTCSession
PathTrackCodec:
type: string
enum:
- AV1
- VP9
- VP8
- H265
- H264
- MPEG-4 Video
- MPEG-1 Video
- MJPEG
- Opus
- Vorbis
- MPEG-4 Audio
- MPEG-4 Audio LATM
- MPEG-1 Audio
- AC3
- Speex
- G726
- G722
- G711
- LPCM
- MPEG-TS
- KLV
- Generic
AlwaysAvailableTrackCodec:
type: string
enum:
- AV1
- VP9
- H265
- H264
- MPEG4Audio
- Opus
- G711
- LPCM
AuthAction:
type: string
enum:
- publish
- read
- playback
- api
- metrics
- pprof
AuthMethod:
type: string
enum: [internal, http, jwt]
Encryption:
type: string
enum: [no, optional, strict]
HLSVariant:
type: string
enum: [mpegts, fmp4, lowLatency]
LogDestination:
type: string
enum: [stdout, file, syslog]
LogLevel:
type: string
enum: [error, warn, info, debug]
RecordFormat:
type: string
enum: [fmp4, mpegts]
RTSPAuthMethod:
type: string
enum: [basic, digest]
RTSPRangeType:
type: string
enum: ['', clock, npt, smpte]
RTSPTransport:
type: string
enum: [udp, multicast, tcp, automatic]
RTMPConnState:
type: string
enum: [idle, read, publish]
RTSPSessionState:
type: string
enum: [idle, read, publish]
SRTConnState:
type: string
enum: [idle, read, publish]
WebRTCSessionState:
type: string
enum: [read, publish]
OK:
type: object
properties:
status:
$ref: '#/components/schemas/OKStatus'
Error:
type: object
properties:
status:
$ref: '#/components/schemas/ErrorStatus'
error:
type: string
Info:
type: object
properties:
version:
type: string
started:
type: string
AuthInternalUser:
type: object
properties:
user:
type: string
pass:
type: string
ips:
type: array
items:
type: string
permissions:
type: array
items:
$ref: '#/components/schemas/AuthInternalUserPermission'
AuthInternalUserPermission:
type: object
properties:
action:
$ref: '#/components/schemas/AuthAction'
path:
type: string
GlobalConf:
type: object
properties:
# General
logLevel:
$ref: '#/components/schemas/LogLevel'
logDestinations:
type: array
items:
$ref: '#/components/schemas/LogDestination'
logStructured:
type: boolean
logFile:
type: string
sysLogPrefix:
type: string
dumpPackets:
type: boolean
readTimeout:
type: string
writeTimeout:
type: string
readBufferCount:
type: integer
format: int64
nullable: true
deprecated: true
writeQueueSize:
type: integer
format: int64
udpMaxPayloadSize:
type: integer
format: int64
udpReadBufferSize:
type: integer
format: uint64
runOnConnect:
type: string
runOnConnectRestart:
type: boolean
runOnDisconnect:
type: string
# Authentication
authMethod:
$ref: '#/components/schemas/AuthMethod'
authInternalUsers:
type: array
items:
$ref: '#/components/schemas/AuthInternalUser'
authHTTPAddress:
type: string
externalAuthenticationURL:
type: string
nullable: true
deprecated: true
authHTTPFingerprint:
type: string
authHTTPExclude:
type: array
items:
$ref: '#/components/schemas/AuthInternalUserPermission'
authJWTJWKS:
type: string
authJWTJWKSFingerprint:
type: string
authJWTClaimKey:
type: string
authJWTIssuer:
type: string
authJWTAudience:
type: string
authJWTExclude:
type: array
items:
$ref: '#/components/schemas/AuthInternalUserPermission'
authJWTInHTTPQuery:
type: boolean
# Control API
api:
type: boolean
apiAddress:
type: string
apiEncryption:
type: boolean
apiServerKey:
type: string
apiServerCert:
type: string
apiAllowOrigin:
type: string
nullable: true
deprecated: true
apiAllowOrigins:
type: array
items:
type: string
apiTrustedProxies:
type: array
items:
type: string
# Metrics
metrics:
type: boolean
metricsAddress:
type: string
metricsEncryption:
type: boolean
metricsServerKey:
type: string
metricsServerCert:
type: string
metricsAllowOrigin:
type: string
nullable: true
deprecated: true
metricsAllowOrigins:
type: array
items:
type: string
metricsTrustedProxies:
type: array
items:
type: string
# PPROF
pprof:
type: boolean
pprofAddress:
type: string
pprofEncryption:
type: boolean
pprofServerKey:
type: string
pprofServerCert:
type: string
pprofAllowOrigin:
type: string
nullable: true
deprecated: true
pprofAllowOrigins:
type: array
items:
type: string
pprofTrustedProxies:
type: array
items:
type: string
# Playback server
playback:
type: boolean
playbackAddress:
type: string
playbackEncryption:
type: boolean
playbackServerKey:
type: string
playbackServerCert:
type: string
playbackAllowOrigin:
type: string
nullable: true
deprecated: true
playbackAllowOrigins:
type: array
items:
type: string
playbackTrustedProxies:
type: array
items:
type: string
# RTSP server
rtsp:
type: boolean
rtspDisable:
type: boolean
nullable: true
deprecated: true
protocols:
type: array
nullable: true
items:
type: string
enum: [udp, multicast, tcp]
deprecated: true
rtspTransports:
type: array
items:
type: string
enum: [udp, multicast, tcp]
encryption:
type: string
nullable: true
deprecated: true
allOf:
- $ref: '#/components/schemas/Encryption'
rtspEncryption:
$ref: '#/components/schemas/Encryption'
rtspAddress:
type: string
rtspsAddress:
type: string
rtpAddress:
type: string
rtcpAddress:
type: string
multicastIPRange:
type: string
multicastRTPPort:
type: integer
format: int64
multicastRTCPPort:
type: integer
format: int64
srtpAddress:
type: string
srtcpAddress:
type: string
multicastSRTPPort:
type: integer
format: int64
multicastSRTCPPort:
type: integer
format: int64
rtspServerKey:
type: string
rtspServerCert:
type: string
authMethods:
type: array
nullable: true
items:
$ref: '#/components/schemas/RTSPAuthMethod'
deprecated: true
rtspAuthMethods:
type: array
items:
$ref: '#/components/schemas/RTSPAuthMethod'
rtspUDPReadBufferSize:
type: integer
format: uint64
nullable: true
deprecated: true
# RTMP server
rtmp:
type: boolean
rtmpDisable:
type: boolean
nullable: true
deprecated: true
rtmpEncryption:
$ref: '#/components/schemas/Encryption'
rtmpAddress:
type: string
rtmpsAddress:
type: string
rtmpServerKey:
type: string
rtmpServerCert:
type: string
# HLS server
hls:
type: boolean
hlsDisable:
type: boolean
nullable: true
deprecated: true
hlsAddress:
type: string
hlsEncryption:
type: boolean
hlsServerKey:
type: string
hlsServerCert:
type: string
hlsAllowOrigin:
type: string
nullable: true
deprecated: true
hlsAllowOrigins:
type: array
items:
type: string
hlsTrustedProxies:
type: array
items:
type: string
hlsAlwaysRemux:
type: boolean
hlsVariant:
$ref: '#/components/schemas/HLSVariant'
hlsSegmentCount:
type: integer
format: int64
hlsSegmentDuration:
type: string
hlsPartDuration:
type: string
hlsSegmentMaxSize:
type: string
hlsDirectory:
type: string
hlsMuxerCloseAfter:
type: string
# WebRTC server
webrtc:
type: boolean
webrtcDisable:
type: boolean
nullable: true
deprecated: true
webrtcAddress:
type: string
webrtcEncryption:
type: boolean
webrtcServerKey:
type: string
webrtcServerCert:
type: string
webrtcAllowOrigin:
type: string
nullable: true
deprecated: true
webrtcAllowOrigins:
type: array
items:
type: string
webrtcTrustedProxies:
type: array
items:
type: string
webrtcLocalUDPAddress:
type: string
webrtcLocalTCPAddress:
type: string
webrtcIPsFromInterfaces:
type: boolean
webrtcIPsFromInterfacesList:
type: array
items:
type: string
webrtcAdditionalHosts:
type: array
items:
type: string
webrtcICEServers2:
type: array
items:
$ref: '#/components/schemas/WebRTCICEServer'
webrtcSTUNGatherTimeout:
type: string
webrtcHandshakeTimeout:
type: string
webrtcTrackGatherTimeout:
type: string
webrtcICEUDPMuxAddress:
type: string
nullable: true
deprecated: true
webrtcICETCPMuxAddress:
type: string
nullable: true
deprecated: true
webrtcICEHostNAT1To1IPs:
type: array
nullable: true
items:
type: string
deprecated: true
webrtcICEServers:
type: array
nullable: true
items:
type: string
deprecated: true
# SRT server
srt:
type: boolean
srtAddress:
type: string
# Record (deprecated)
record:
type: boolean
nullable: true
deprecated: true
recordPath:
type: string
nullable: true
deprecated: true
recordFormat:
type: string
nullable: true
deprecated: true
allOf:
- $ref: '#/components/schemas/RecordFormat'
recordPartDuration:
type: string
nullable: true
deprecated: true
recordSegmentDuration:
type: string
nullable: true
deprecated: true
recordDeleteAfter:
type: string
nullable: true
deprecated: true
PathConf:
type: object
properties:
name:
type: string
# General
source:
type: string
sourceFingerprint:
type: string
sourceOnDemand:
type: boolean
sourceOnDemandStartTimeout:
type: string
sourceOnDemandCloseAfter:
type: string
maxReaders:
type: integer
format: int64
srtReadPassphrase:
type: string
fallback:
type: string
nullable: true
deprecated: true
useAbsoluteTimestamp:
type: boolean
# Always available
alwaysAvailable:
type: boolean
alwaysAvailableTracks:
type: array
items:
$ref: '#/components/schemas/AlwaysAvailableTrack'
alwaysAvailableFile:
type: string
# Record
record:
type: boolean
playback:
type: boolean
nullable: true
deprecated: true
recordPath:
type: string
recordFormat:
$ref: '#/components/schemas/RecordFormat'
recordPartDuration:
type: string
recordMaxPartSize:
type: string
recordSegmentDuration:
type: string
recordDeleteAfter:
type: string
# Authentication (deprecated)
publishUser:
type: string
nullable: true
deprecated: true
publishPass:
type: string
nullable: true
deprecated: true
publishIPs:
type: array
nullable: true
items:
type: string
deprecated: true
readUser:
type: string
nullable: true
deprecated: true
readPass:
type: string
nullable: true
deprecated: true
readIPs:
type: array
nullable: true
items:
type: string
deprecated: true
# Publisher source
overridePublisher:
type: boolean
disablePublisherOverride:
type: boolean
nullable: true
deprecated: true
srtPublishPassphrase:
type: string
rtspDemuxMpegts:
type: boolean
# RTSP source
rtspTransport:
$ref: '#/components/schemas/RTSPTransport'
rtspAnyPort:
type: boolean
sourceProtocol:
type: string
nullable: true
deprecated: true
allOf:
- $ref: '#/components/schemas/RTSPTransport'
sourceAnyPortEnable:
type: boolean
nullable: true
deprecated: true
rtspRangeType:
$ref: '#/components/schemas/RTSPRangeType'
rtspRangeStart:
type: string
rtspUDPReadBufferSize:
type: integer
format: uint64
nullable: true
deprecated: true
rtspUDPSourcePortRange:
type: array
minItems: 2
maxItems: 2
items:
type: integer
format: uint64
# MPEG-TS source
mpegtsUDPReadBufferSize:
type: integer
format: uint64
nullable: true
deprecated: true
# RTP source
rtpSDP:
type: string
rtpUDPReadBufferSize:
type: integer
format: uint64
nullable: true
deprecated: true
# WHEP source
whepBearerToken:
type: string
whepSTUNGatherTimeout:
type: string
whepHandshakeTimeout:
type: string
whepTrackGatherTimeout:
type: string
# Redirect source
sourceRedirect:
type: string
# Raspberry Pi Camera source
rpiCameraCamID:
type: integer
format: uint64
rpiCameraSecondary:
type: boolean
rpiCameraWidth:
type: integer
format: uint64
rpiCameraHeight:
type: integer
format: uint64
rpiCameraHFlip:
type: boolean
rpiCameraVFlip:
type: boolean
rpiCameraBrightness:
type: number
format: double
rpiCameraContrast:
type: number
format: double
rpiCameraSaturation:
type: number
format: double
rpiCameraSharpness:
type: number
format: double
rpiCameraExposure:
type: string
rpiCameraAWB:
type: string
rpiCameraAWBGains:
type: array
minItems: 2
maxItems: 2
items:
type: number
format: double
rpiCameraDenoise:
type: string
rpiCameraShutter:
type: integer
format: uint64
rpiCameraMetering:
type: string
rpiCameraGain:
type: number
format: double
rpiCameraEV:
type: number
format: double
rpiCameraROI:
type: string
rpiCameraHDR:
type: boolean
rpiCameraTuningFile:
type: string
rpiCameraMode:
type: string
rpiCameraFPS:
type: number
format: double
rpiCameraAfMode:
type: string
rpiCameraAfRange:
type: string
rpiCameraAfSpeed:
type: string
rpiCameraLensPosition:
type: number
format: double
rpiCameraAfWindow:
type: string
rpiCameraFlickerPeriod:
type: integer
format: uint64
rpiCameraTextOverlayEnable:
type: boolean
rpiCameraTextOverlay:
type: string
rpiCameraCodec:
type: string
rpiCameraIDRPeriod:
type: integer
format: uint64
rpiCameraBitrate:
type: integer
format: uint64
rpiCameraProfile:
type: string
nullable: true
deprecated: true
rpiCameraLevel:
type: string
nullable: true
deprecated: true
rpiCameraHardwareH264Profile:
type: string
rpiCameraHardwareH264Level:
type: string
rpiCameraSoftwareH264Profile:
type: string
rpiCameraSoftwareH264Level:
type: string
rpiCameraJPEGQuality:
type: integer
format: uint64
nullable: true
deprecated: true
rpiCameraMJPEGQuality:
type: integer
format: uint64
# Hooks
runOnInit:
type: string
runOnInitRestart:
type: boolean
runOnDemand:
type: string
runOnDemandRestart:
type: boolean
runOnDemandStartTimeout:
type: string
runOnDemandCloseAfter:
type: string
runOnUnDemand:
type: string
runOnReady:
type: string
runOnReadyRestart:
type: boolean
runOnNotReady:
type: string
runOnRead:
type: string
runOnReadRestart:
type: boolean
runOnUnread:
type: string
runOnRecordSegmentCreate:
type: string
runOnRecordSegmentComplete:
type: string
PathConfList:
type: object
properties:
pageCount:
type: integer
format: int64
itemCount:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/PathConf'
Path:
type: object
properties:
name:
type: string
confName:
type: string
source:
type: object
nullable: true
allOf:
- $ref: '#/components/schemas/PathSource'
ready:
type: boolean
deprecated: true
readyTime:
type: string
nullable: true
deprecated: true
available:
type: boolean
availableTime:
type: string
nullable: true
online:
type: boolean
onlineTime:
type: string
nullable: true
tracks:
type: array
deprecated: true
items:
$ref: '#/components/schemas/PathTrackCodec'
tracks2:
type: array
items:
$ref: '#/components/schemas/PathTrack'
inboundBytes:
type: integer
format: uint64
outboundBytes:
type: integer
format: uint64
inboundFramesInError:
type: integer
format: uint64
bytesReceived:
type: integer
format: uint64
deprecated: true
bytesSent:
type: integer
format: uint64
deprecated: true
readers:
type: array
items:
$ref: '#/components/schemas/PathReader'
PathList:
type: object
properties:
pageCount:
type: integer
format: int64
itemCount:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/Path'
PathSource:
type: object
properties:
type:
$ref: '#/components/schemas/PathSourceType'
id:
type: string
PathReader:
type: object
properties:
type:
$ref: '#/components/schemas/PathReaderType'
id:
type: string
PathTrack:
type: object
properties:
codec:
$ref: '#/components/schemas/PathTrackCodec'
codecProps:
type: object
nullable: true
allOf:
- $ref: '#/components/schemas/PathTrackCodecProps'
PathTrackCodecProps:
oneOf:
- $ref: '#/components/schemas/PathTrackCodecPropsAV1'
- $ref: '#/components/schemas/PathTrackCodecPropsVP9'
- $ref: '#/components/schemas/PathTrackCodecPropsH265'
- $ref: '#/components/schemas/PathTrackCodecPropsH264'
- $ref: '#/components/schemas/PathTrackCodecPropsOpus'
- $ref: '#/components/schemas/PathTrackCodecPropsMPEG4Audio'
- $ref: '#/components/schemas/PathTrackCodecPropsAC3'
- $ref: '#/components/schemas/PathTrackCodecPropsG711'
- $ref: '#/components/schemas/PathTrackCodecPropsLPCM'
PathTrackCodecPropsAV1:
type: object
properties:
width:
type: integer
format: int64
height:
type: integer
format: int64
profile:
type: integer
format: int64
level:
type: integer
format: int64
tier:
type: integer
format: int64
PathTrackCodecPropsVP9:
type: object
properties:
profile:
type: integer
format: int64
PathTrackCodecPropsH265:
type: object
properties:
width:
type: integer
format: int64
height:
type: integer
format: int64
profile:
type: string
level:
type: string
PathTrackCodecPropsH264:
type: object
properties:
width:
type: integer
format: int64
height:
type: integer
format: int64
profile:
type: string
level:
type: string
PathTrackCodecPropsOpus:
type: object
properties:
channelCount:
type: integer
format: int64
PathTrackCodecPropsMPEG4Audio:
type: object
properties:
sampleRate:
type: integer
format: int64
channelCount:
type: integer
format: int64
PathTrackCodecPropsAC3:
type: object
properties:
sampleRate:
type: integer
format: int64
channelCount:
type: integer
format: int64
PathTrackCodecPropsG711:
type: object
properties:
muLaw:
type: boolean
sampleRate:
type: integer
format: int64
channelCount:
type: integer
format: int64
PathTrackCodecPropsLPCM:
type: object
properties:
bitDepth:
type: integer
format: int64
sampleRate:
type: integer
format: int64
channelCount:
type: integer
format: int64
HLSMuxer:
type: object
properties:
path:
type: string
created:
type: string
lastRequest:
type: string
outboundBytes:
type: integer
format: uint64
outboundFramesDiscarded:
type: integer
format: uint64
bytesSent:
type: integer
format: uint64
deprecated: true
HLSMuxerList:
type: object
properties:
pageCount:
type: integer
format: int64
itemCount:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/HLSMuxer'
Recording:
type: object
properties:
name:
type: string
segments:
type: array
items:
$ref: '#/components/schemas/RecordingSegment'
RecordingList:
type: object
properties:
pageCount:
type: integer
format: int64
itemCount:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/Recording'
RecordingSegment:
type: object
properties:
start:
type: string
RTMPConn:
type: object
properties:
id:
type: string
format: uuid
created:
type: string
remoteAddr:
type: string
state:
$ref: '#/components/schemas/RTMPConnState'
path:
type: string
query:
type: string
user:
type: string
inboundBytes:
type: integer
format: uint64
outboundBytes:
type: integer
format: uint64
outboundFramesDiscarded:
type: integer
format: uint64
bytesReceived:
type: integer
format: uint64
deprecated: true
bytesSent:
type: integer
format: uint64
deprecated: true
RTMPConnList:
type: object
properties:
pageCount:
type: integer
format: int64
itemCount:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/RTMPConn'
RTSPConn:
type: object
properties:
id:
type: string
format: uuid
created:
type: string
remoteAddr:
type: string
session:
type: string
format: uuid
nullable: true
tunnel:
type: string
inboundBytes:
type: integer
format: uint64
outboundBytes:
type: integer
format: uint64
bytesReceived:
type: integer
format: uint64
deprecated: true
bytesSent:
type: integer
format: uint64
deprecated: true
RTSPConnList:
type: object
properties:
pageCount:
type: integer
format: int64
itemCount:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/RTSPConn'
RTSPSession:
type: object
properties:
id:
type: string
format: uuid
created:
type: string
remoteAddr:
type: string
state:
$ref: '#/components/schemas/RTSPSessionState'
path:
type: string
query:
type: string
user:
type: string
transport:
type: string
nullable: true
profile:
type: string
nullable: true
conns:
type: array
items:
type: string
format: uuid
inboundBytes:
type: integer
format: uint64
inboundRTPPackets:
type: integer
format: uint64
inboundRTPPacketsLost:
type: integer
format: uint64
inboundRTPPacketsInError:
type: integer
format: uint64
inboundRTPPacketsJitter:
type: number
format: double
inboundRTCPPackets:
type: integer
format: uint64
inboundRTCPPacketsInError:
type: integer
format: uint64
outboundBytes:
type: integer
format: uint64
outboundRTPPackets:
type: integer
format: uint64
outboundRTPPacketsReportedLost:
type: integer
format: uint64
outboundRTPPacketsDiscarded:
type: integer
format: uint64
outboundRTCPPackets:
type: integer
format: uint64
bytesReceived:
type: integer
format: uint64
deprecated: true
bytesSent:
type: integer
format: uint64
deprecated: true
rtpPacketsReceived:
type: integer
format: uint64
deprecated: true
rtpPacketsSent:
type: integer
format: uint64
deprecated: true
rtpPacketsLost:
type: integer
format: uint64
deprecated: true
rtpPacketsInError:
type: integer
format: uint64
deprecated: true
rtpPacketsJitter:
type: number
format: double
deprecated: true
rtcpPacketsReceived:
type: integer
format: uint64
deprecated: true
rtcpPacketsSent:
type: integer
format: uint64
deprecated: true
rtcpPacketsInError:
type: integer
format: uint64
deprecated: true
RTSPSessionList:
type: object
properties:
pageCount:
type: integer
format: int64
itemCount:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/RTSPSession'
SRTConn:
type: object
properties:
id:
type: string
format: uuid
created:
type: string
remoteAddr:
type: string
state:
$ref: '#/components/schemas/SRTConnState'
path:
type: string
query:
type: string
user:
type: string
packetsSent:
type: integer
format: uint64
description: The total number of sent DATA packets, including retransmitted packets
packetsReceived:
type: integer
format: uint64
description: The total number of received DATA packets, including retransmitted packets
packetsReceivedBelated:
type: integer
format: uint64
packetsSentUnique:
type: integer
format: uint64
description: The total number of unique DATA packets sent by the SRT sender
packetsReceivedUnique:
type: integer
format: uint64
description: The total number of unique original, retransmitted or recovered by the packet filter DATA packets received in time, decrypted without errors and, as a result, scheduled for delivery to the upstream application by the SRT receiver.
packetsSendLoss:
type: integer
format: uint64
description: The total number of data packets considered or reported as lost at the sender side. Does not correspond to the packets detected as lost at the receiver side.
packetsReceivedLoss:
type: integer
format: uint64
description: The total number of SRT DATA packets detected as presently missing (either reordered or lost) at the receiver side
packetsRetrans:
type: integer
format: uint64
description: The total number of retransmitted packets sent by the SRT sender
packetsReceivedRetrans:
type: integer
format: uint64
description: The total number of retransmitted packets registered at the receiver side
packetsSentACK:
type: integer
format: uint64
description: The total number of sent ACK (Acknowledgement) control packets
packetsReceivedACK:
type: integer
format: uint64
description: The total number of received ACK (Acknowledgement) control packets
packetsSentNAK:
type: integer
format: uint64
description: The total number of sent NAK (Negative Acknowledgement) control packets
packetsReceivedNAK:
type: integer
format: uint64
description: The total number of received NAK (Negative Acknowledgement) control packets
packetsSentKM:
type: integer
format: uint64
description: The total number of sent KM (Key Material) control packets
packetsReceivedKM:
type: integer
format: uint64
description: The total number of received KM (Key Material) control packets
usSndDuration:
type: integer
format: uint64
description: The total accumulated time in microseconds, during which the SRT sender has some data to transmit, including packets that have been sent, but not yet acknowledged
packetsSendDrop:
type: integer
format: uint64
description: The total number of dropped by the SRT sender DATA packets that have no chance to be delivered in time
packetsReceivedDrop:
type: integer
format: uint64
description: The total number of dropped by the SRT receiver and, as a result, not delivered to the upstream application DATA packets
packetsReceivedUndecrypt:
type: integer
format: uint64
description: The total number of packets that failed to be decrypted at the receiver side
bytesSent:
type: integer
format: uint64
description: Same as packetsSent, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
bytesReceived:
type: integer
format: uint64
description: Same as packetsReceived, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
bytesReceivedBelated:
type: integer
format: uint64
bytesSentUnique:
type: integer
format: uint64
description: Same as packetsSentUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
bytesReceivedUnique:
type: integer
format: uint64
description: Same as packetsReceivedUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
bytesReceivedLoss:
type: integer
format: uint64
description: Same as packetsReceivedLoss, but expressed in bytes, including payload and all the headers (IP, TCP, SRT), bytes for the presently missing (either reordered or lost) packets' payloads are estimated based on the average packet size
bytesRetrans:
type: integer
format: uint64
description: Same as packetsRetrans, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
bytesReceivedRetrans:
type: integer
format: uint64
description: Same as packetsReceivedRetrans, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
bytesSendDrop:
type: integer
format: uint64
description: Same as packetsSendDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
bytesReceivedDrop:
type: integer
format: uint64
description: Same as packetsReceivedDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
bytesReceivedUndecrypt:
type: integer
format: uint64
description: Same as packetsReceivedUndecrypt, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
usPacketsSendPeriod:
type: number
format: double
description: Current minimum time interval between which consecutive packets are sent, in microseconds
packetsFlowWindow:
type: integer
format: uint64
description: The maximum number of packets that can be "in flight"
packetsFlightSize:
type: integer
format: uint64
description: The number of packets in flight
msRTT:
type: number
format: double
description: Smoothed round-trip time (SRTT), an exponentially-weighted moving average (EWMA) of an endpoint's RTT samples, in milliseconds
mbpsSendRate:
type: number
format: double
description: Current transmission bandwidth, in Mbps
mbpsReceiveRate:
type: number
format: double
description: Current receiving bandwidth, in Mbps
mbpsLinkCapacity:
type: number
format: double
description: Estimated capacity of the network link, in Mbps
bytesAvailSendBuf:
type: integer
format: uint64
description: The available space in the sender's buffer, in bytes
bytesAvailReceiveBuf:
type: integer
format: uint64
description: The available space in the receiver's buffer, in bytes
mbpsMaxBW:
type: number
format: double
description: Transmission bandwidth limit, in Mbps
byteMSS:
type: integer
format: uint64
description: Maximum Segment Size (MSS), in bytes
packetsSendBuf:
type: integer
format: uint64
description: The number of packets in the sender's buffer that are already scheduled for sending or even possibly sent, but not yet acknowledged
bytesSendBuf:
type: integer
format: uint64
description: Instantaneous (current) value of packetsSndBuf, but expressed in bytes, including payload and all headers (IP, TCP, SRT)
msSendBuf:
type: integer
format: uint64
description: The timespan (msec) of packets in the sender's buffer (unacknowledged packets)
msSendTsbPdDelay:
type: integer
format: uint64
description: Timestamp-based Packet Delivery Delay value of the peer
packetsReceiveBuf:
type: integer
format: uint64
description: The number of acknowledged packets in receiver's buffer
bytesReceiveBuf:
type: integer
format: uint64
description: Instantaneous (current) value of packetsRcvBuf, expressed in bytes, including payload and all headers (IP, TCP, SRT)
msReceiveBuf:
type: integer
format: uint64
description: The timespan (msec) of acknowledged packets in the receiver's buffer
msReceiveTsbPdDelay:
type: integer
format: uint64
description: Timestamp-based Packet Delivery Delay value set on the socket via SRTO_RCVLATENCY or SRTO_LATENCY
packetsReorderTolerance:
type: integer
format: uint64
description: Instant value of the packet reorder tolerance
packetsReceivedAvgBelatedTime:
type: integer
format: uint64
description: Accumulated difference between the current time and the time-to-play of a packet that is received late
packetsSendLossRate:
type: number
format: double
description: Percentage of resent data vs. sent data
packetsReceivedLossRate:
type: number
format: double
description: Percentage of retransmitted data vs. received data
outboundFramesDiscarded:
type: integer
format: uint64
SRTConnList:
type: object
properties:
pageCount:
type: integer
format: int64
itemCount:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/SRTConn'
AlwaysAvailableTrack:
type: object
properties:
codec:
$ref: '#/components/schemas/AlwaysAvailableTrackCodec'
sampleRate:
type: integer
format: int64
channelCount:
type: integer
format: int64
muLaw:
type: boolean
WebRTCICEServer:
type: object
properties:
url:
type: string
username:
type: string
password:
type: string
clientOnly:
type: boolean
WebRTCSession:
type: object
properties:
id:
type: string
format: uuid
created:
type: string
remoteAddr:
type: string
peerConnectionEstablished:
type: boolean
localCandidate:
type: string
remoteCandidate:
type: string
state:
$ref: '#/components/schemas/WebRTCSessionState'
path:
type: string
query:
type: string
user:
type: string
inboundBytes:
type: integer
format: uint64
inboundRTPPackets:
type: integer
format: uint64
inboundRTPPacketsLost:
type: integer
format: uint64
inboundRTPPacketsJitter:
type: number
format: double
inboundRTCPPackets:
type: integer
format: uint64
outboundBytes:
type: integer
format: uint64
outboundRTPPackets:
type: integer
format: uint64
outboundRTCPPackets:
type: integer
format: uint64
outboundFramesDiscarded:
type: integer
format: uint64
bytesReceived:
type: integer
format: uint64
deprecated: true
bytesSent:
type: integer
format: uint64
deprecated: true
rtpPacketsReceived:
type: integer
format: uint64
deprecated: true
rtpPacketsSent:
type: integer
format: uint64
deprecated: true
rtpPacketsLost:
type: integer
format: uint64
deprecated: true
rtpPacketsJitter:
type: number
format: double
deprecated: true
rtcpPacketsReceived:
type: integer
format: uint64
deprecated: true
rtcpPacketsSent:
type: integer
format: uint64
deprecated: true
WebRTCSessionList:
type: object
properties:
pageCount:
type: integer
format: int64
itemCount:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/WebRTCSession'
paths:
/v3/info:
get:
operationId: info
tags: [General]
summary: returns informations about the instance.
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/Info'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/auth/jwks/refresh:
post:
operationId: authJwksRefresh
tags: [Authentication]
summary: Manually refreshes the JWT JWKS.
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/global/get:
get:
operationId: configGlobalGet
tags: [Configuration]
summary: returns the global configuration.
description: ''
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/GlobalConf'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/global/patch:
patch:
operationId: configGlobalSet
tags: [Configuration]
summary: patches the global configuration.
description: all fields are optional.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GlobalConf'
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/pathdefaults/get:
get:
operationId: configPathDefaultsGet
tags: [Configuration]
summary: returns the default path configuration.
description: ''
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/PathConf'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/pathdefaults/patch:
patch:
operationId: configPathDefaultsPatch
tags: [Configuration]
summary: patches the default path configuration.
description: all fields are optional.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PathConf'
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/paths/list:
get:
operationId: configPathsList
tags: [Configuration]
summary: returns all path configurations.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/PathConfList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/paths/get/{name}:
get:
operationId: configPathsGet
tags: [Configuration]
summary: returns a path configuration.
description: ''
parameters:
- name: name
in: path
required: true
description: the name of the path.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/PathConf'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: path not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/paths/add/{name}:
post:
operationId: configPathsAdd
tags: [Configuration]
summary: adds a path configuration.
description: all fields are optional.
parameters:
- name: name
in: path
required: true
description: the name of the path.
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PathConf'
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/paths/patch/{name}:
patch:
operationId: configPathsPatch
tags: [Configuration]
summary: patches a path configuration.
description: all fields are optional.
parameters:
- name: name
in: path
required: true
description: the name of the path.
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PathConf'
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: path not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/paths/replace/{name}:
post:
operationId: configPathsReplace
tags: [Configuration]
summary: replaces all values of a path configuration.
description: all fields are optional.
parameters:
- name: name
in: path
required: true
description: the name of the path.
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PathConf'
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: path not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/config/paths/delete/{name}:
delete:
operationId: configPathsDelete
tags: [Configuration]
summary: removes a path configuration.
description: ''
parameters:
- name: name
in: path
required: true
description: the name of the path.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: path not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/hlsmuxers/list:
get:
operationId: hlsMuxersList
tags: [HLS]
summary: returns all HLS muxers.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/HLSMuxerList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/hlsmuxers/get/{name}:
get:
operationId: hlsMuxersGet
tags: [HLS]
summary: returns a HLS muxer.
description: ''
parameters:
- name: name
in: path
required: true
description: name of the muxer.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/HLSMuxer'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: muxer not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/paths/list:
get:
operationId: pathsList
tags: [Paths]
summary: returns all paths.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/PathList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/paths/get/{name}:
get:
operationId: pathsGet
tags: [Paths]
summary: returns a path.
description: ''
parameters:
- name: name
in: path
required: true
description: name of the path.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/Path'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: path not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspconns/list:
get:
operationId: rtspConnsList
tags: [RTSP]
summary: returns all RTSP connections.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTSPConnList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspconns/get/{id}:
get:
operationId: rtspConnsGet
tags: [RTSP]
summary: returns a RTSP connection.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTSPConn'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: connection not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspsessions/list:
get:
operationId: rtspSessionsList
tags: [RTSP]
summary: returns all RTSP sessions.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTSPSessionList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspsessions/get/{id}:
get:
operationId: rtspSessionsGet
tags: [RTSP]
summary: returns a RTSP session.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTSPSession'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: session not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspsessions/kick/{id}:
post:
operationId: rtspSessionsKick
tags: [RTSP]
summary: kicks out a RTSP session from the server.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the session.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: session not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspsconns/list:
get:
operationId: rtspsConnsList
tags: [RTSP]
summary: returns all RTSPS connections.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTSPConnList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspsconns/get/{id}:
get:
operationId: rtspsConnsGet
tags: [RTSP]
summary: returns a RTSPS connection.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTSPConn'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: connection not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspssessions/list:
get:
operationId: rtspsSessionsList
tags: [RTSP]
summary: returns all RTSPS sessions.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTSPSessionList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspssessions/get/{id}:
get:
operationId: rtspsSessionsGet
tags: [RTSP]
summary: returns a RTSPS session.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTSPSession'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: session not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtspssessions/kick/{id}:
post:
operationId: rtspsSessionsKick
tags: [RTSP]
summary: kicks out a RTSPS session from the server.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the session.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: session not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtmpconns/list:
get:
operationId: rtmpConnsList
tags: [RTMP]
summary: returns all RTMP connections.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTMPConnList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtmpconns/get/{id}:
get:
operationId: rtmpConnectionsGet
tags: [RTMP]
summary: returns a RTMP connection.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTMPConn'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: connection not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtmpconns/kick/{id}:
post:
operationId: rtmpConnsKick
tags: [RTMP]
summary: kicks out a RTMP connection from the server.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: connection not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtmpsconns/list:
get:
operationId: rtmpsConnsList
tags: [RTMP]
summary: returns all RTMPS connections.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTMPConnList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtmpsconns/get/{id}:
get:
operationId: rtmpsConnectionsGet
tags: [RTMP]
summary: returns a RTMPS connection.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RTMPConn'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: connection not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/rtmpsconns/kick/{id}:
post:
operationId: rtmpsConnsKick
tags: [RTMP]
summary: kicks out a RTMPS connection from the server.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: connection not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/srtconns/list:
get:
operationId: srtConnsList
tags: [SRT]
summary: returns all SRT connections.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/SRTConnList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/srtconns/get/{id}:
get:
operationId: srtConnsGet
tags: [SRT]
summary: returns a SRT connection.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/SRTConn'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: connection not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/srtconns/kick/{id}:
post:
operationId: srtConnsKick
tags: [SRT]
summary: kicks out a SRT connection from the server.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the connection.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: connection not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/webrtcsessions/list:
get:
operationId: webrtcSessionsList
tags: [WebRTC]
summary: returns all WebRTC sessions.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/WebRTCSessionList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/webrtcsessions/get/{id}:
get:
operationId: webrtcSessionsGet
tags: [WebRTC]
summary: returns a WebRTC session.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the session.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/WebRTCSession'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: session not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/webrtcsessions/kick/{id}:
post:
operationId: webrtcSessionsKick
tags: [WebRTC]
summary: kicks out a WebRTC session from the server.
description: ''
parameters:
- name: id
in: path
required: true
description: ID of the session.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: session not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/recordings/list:
get:
operationId: recordingsList
tags: [Recordings]
summary: returns all recordings, splitted by path.
description: ''
parameters:
- name: page
in: query
description: page number.
schema:
type: integer
default: 0
- name: itemsPerPage
in: query
description: items per page.
schema:
type: integer
default: 100
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/RecordingList'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/recordings/get/{name}:
get:
operationId: recordingsGet
tags: [Recordings]
summary: returns recordings of a path.
description: ''
parameters:
- name: name
in: path
required: true
description: name of the path.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/Recording'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: path not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v3/recordings/deletesegment:
delete:
operationId: recordingsDeleteSegment
tags: [Recordings]
summary: deletes a recording segment.
description: ''
parameters:
- name: path
in: query
required: true
description: path.
schema:
type: string
- name: start
in: query
required: true
description: starting date of the segment.
schema:
type: string
responses:
'200':
description: the request was successful.
content:
application/json:
schema:
$ref: '#/components/schemas/OK'
'400':
description: invalid request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: connection not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
================================================
FILE: docker/ffmpeg-rpi.Dockerfile
================================================
#################################################################
FROM --platform=linux/amd64 scratch AS binaries
ADD binaries/mediamtx_*_linux_armv6.tar.gz /linux/arm/v6
ADD binaries/mediamtx_*_linux_armv7.tar.gz /linux/arm/v7
ADD binaries/mediamtx_*_linux_arm64.tar.gz /linux/arm64
#################################################################
FROM --platform=linux/arm/v7 debian:bullseye-slim AS base-arm-v7
# even though the base image is arm v7,
# Raspbian libraries and compilers provide arm v6 compatibility.
RUN apt update \
&& apt install -y wget gpg \
&& echo "deb http://archive.raspbian.org/raspbian bullseye main rpi firmware" > /etc/apt/sources.list \
&& echo "deb http://archive.raspberrypi.org/debian bullseye main" > /etc/apt/sources.list.d/raspi.list \
&& wget -O- https://archive.raspbian.org/raspbian.public.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/raspbian.gpg \
&& wget -O- https://archive.raspberrypi.org/debian/raspberrypi.gpg.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/raspberrypi.gpg \
&& rm -rf /var/lib/apt/lists/*
RUN apt update && apt install --reinstall -y \
libc6 \
libc-bin \
libstdc++6 \
&& rm -rf /var/lib/apt/lists/*
#################################################################
FROM --platform=linux/arm64 debian:bullseye-slim AS base-arm64
RUN apt update \
&& apt install -y wget gpg \
&& echo "deb http://archive.raspberrypi.org/debian bullseye main" > /etc/apt/sources.list.d/raspi.list \
&& wget -O- https://archive.raspberrypi.org/debian/raspberrypi.gpg.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/raspberrypi.gpg \
&& rm -rf /var/lib/apt/lists/*
#################################################################
FROM --platform=linux/amd64 scratch AS base
COPY --from=base-arm-v7 / /linux/arm/v6
COPY --from=base-arm-v7 / /linux/arm/v7
COPY --from=base-arm64 / /linux/arm64
#################################################################
FROM scratch
ARG TARGETPLATFORM
COPY --from=base /$TARGETPLATFORM /
RUN apt update \
&& apt install -y --no-install-recommends ffmpeg \
&& rm -rf /var/lib/apt/lists/*
COPY --from=binaries /$TARGETPLATFORM /
ENTRYPOINT [ "/mediamtx" ]
================================================
FILE: docker/ffmpeg.Dockerfile
================================================
#################################################################
FROM --platform=linux/amd64 scratch AS binaries
ADD binaries/mediamtx_*_linux_amd64.tar.gz /linux/amd64
ADD binaries/mediamtx_*_linux_armv6.tar.gz /linux/arm/v6
ADD binaries/mediamtx_*_linux_armv7.tar.gz /linux/arm/v7
ADD binaries/mediamtx_*_linux_arm64.tar.gz /linux/arm64
#################################################################
FROM alpine:3.22
RUN apk add --no-cache ffmpeg
ARG TARGETPLATFORM
COPY --from=binaries /$TARGETPLATFORM /
ENTRYPOINT [ "/mediamtx" ]
================================================
FILE: docker/rpi.Dockerfile
================================================
#################################################################
FROM --platform=linux/amd64 scratch AS binaries
ADD binaries/mediamtx_*_linux_armv6.tar.gz /linux/arm/v6
ADD binaries/mediamtx_*_linux_armv7.tar.gz /linux/arm/v7
ADD binaries/mediamtx_*_linux_arm64.tar.gz /linux/arm64
#################################################################
FROM --platform=linux/arm/v7 debian:bullseye-slim AS base-arm-v7
# even though the base image is arm v7,
# Raspbian libraries and compilers provide arm v6 compatibility.
RUN apt update \
&& apt install -y wget gpg \
&& echo "deb http://archive.raspbian.org/raspbian bullseye main rpi firmware" > /etc/apt/sources.list \
&& echo "deb http://archive.raspberrypi.org/debian bullseye main" > /etc/apt/sources.list.d/raspi.list \
&& wget -O- https://archive.raspbian.org/raspbian.public.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/raspbian.gpg \
&& wget -O- https://archive.raspberrypi.org/debian/raspberrypi.gpg.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/raspberrypi.gpg \
&& rm -rf /var/lib/apt/lists/*
RUN apt update && apt install --reinstall -y \
libc6 \
libc-bin \
libstdc++6 \
&& rm -rf /var/lib/apt/lists/*
#################################################################
FROM --platform=linux/arm64 debian:bullseye-slim AS base-arm64
RUN apt update \
&& apt install -y wget gpg \
&& echo "deb http://archive.raspberrypi.org/debian bullseye main" > /etc/apt/sources.list.d/raspi.list \
&& wget -O- https://archive.raspberrypi.org/debian/raspberrypi.gpg.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/raspberrypi.gpg \
&& rm -rf /var/lib/apt/lists/*
#################################################################
FROM --platform=linux/amd64 scratch AS base
COPY --from=base-arm-v7 / /linux/arm/v6
COPY --from=base-arm-v7 / /linux/arm/v7
COPY --from=base-arm64 / /linux/arm64
#################################################################
FROM scratch
ARG TARGETPLATFORM
COPY --from=base /$TARGETPLATFORM /
COPY --from=binaries /$TARGETPLATFORM /
ENTRYPOINT [ "/mediamtx" ]
================================================
FILE: docker/standard.Dockerfile
================================================
#################################################################
FROM --platform=linux/amd64 scratch AS binaries
ADD binaries/mediamtx_*_linux_amd64.tar.gz /linux/amd64
ADD binaries/mediamtx_*_linux_armv6.tar.gz /linux/arm/v6
ADD binaries/mediamtx_*_linux_armv7.tar.gz /linux/arm/v7
ADD binaries/mediamtx_*_linux_arm64.tar.gz /linux/arm64
#################################################################
FROM scratch
ARG TARGETPLATFORM
COPY --from=binaries /$TARGETPLATFORM /
ENTRYPOINT [ "/mediamtx" ]
================================================
FILE: docs/1-kickoff/1-introduction.md
================================================
# Introduction
Welcome to the MediaMTX documentation!
_MediaMTX_ is a ready-to-use and zero-dependency live media server and media proxy. It has been conceived as a "media router" that routes media streams from one end to the other, with a focus on efficiency and portability.
Main features:
- [Publish](../2-publish/01-overview.md) live streams to the server with SRT, WebRTC, RTSP, RTMP, HLS, MPEG-TS, RTP, using FFmpeg, GStreamer, OBS Studio, Python , Golang, Unity, Web browsers, Raspberry Pi Cameras and more.
- [Read](../3-read/01-overview.md) live streams from the server with SRT, WebRTC, RTSP, RTMP, HLS, using FFmpeg, GStreamer, VLC, OBS Studio, Python , Golang, Unity, Web browsers and more.
- Streams are automatically converted from a protocol to another
- Serve several streams at once in separate paths
- Reload the configuration without disconnecting existing clients (hot reloading)
- [Serve always-available streams](../4-other/05-always-available.md) even when the publisher is offline
- [Record](../4-other/06-record.md) streams to disk in fMP4 or MPEG-TS format
- [Playback](../4-other/07-playback.md) recorded streams
- [Authenticate](../4-other/03-authentication.md) users with internal, HTTP or JWT authentication
- [Forward](../4-other/08-forward.md) streams to other servers
- [Proxy](../4-other/09-proxy.md) requests to other servers
- [Control](../4-other/18-control-api.md) the server through the Control API
- [Extract metrics](../4-other/19-metrics.md) from the server in a Prometheus-compatible format
- [Monitor performance](../4-other/20-performance.md) to investigate CPU and RAM consumption
- [Run hooks](../4-other/17-hooks.md) (external commands) when clients connect, disconnect, read or publish streams
- Compatible with Linux, Windows and macOS, does not require any dependency or interpreter, it's a single executable
Use the menu to navigate through the documentation.
================================================
FILE: docs/1-kickoff/2-install.md
================================================
# Install
There are several installation methods available:
- [Standalone binary](#standalone-binary): use this if you are running Windows, macOS or you just want to try out _MediaMTX_.
- [Docker image](#docker-image): use this if you want to run _MediaMTX_ in an isolated and deterministic way. This is recommended for production environments.
- [Arch Linux package](#arch-linux-package): use this if you are running Arch Linux.
- [FreeBSD package](#freebsd-package): use this if you are running FreeBSD.
- [OpenWrt binary](#openwrt-binary): use this if you are running OpenWrt.
## Standalone binary
1. Visit the [Releases page](https://github.com/bluenviron/mediamtx/releases) on GitHub, download and extract a standalone binary that corresponds to your operating system and architecture (example: `mediamtx_{version_tag}_linux_amd64.tar.gz`).
2. Start the server by double clicking on `mediamtx` (`mediamtx.exe` on Windows) or writing in the terminal:
```sh
./mediamtx
```
## Docker image
Download and launch the `bluenviron/mediamtx:1` image with the following environment variables and ports:
```sh
docker run --rm -it \
-e MTX_RTSPTRANSPORTS=tcp \
-e MTX_WEBRTCADDITIONALHOSTS=192.168.x.x \
-p 8554:8554 \
-p 1935:1935 \
-p 8888:8888 \
-p 8889:8889 \
-p 8890:8890/udp \
-p 8189:8189/udp \
bluenviron/mediamtx:1
```
Fill the `MTX_WEBRTCADDITIONALHOSTS` environment variable with the IP that will be used to connect to the server.
The `MTX_RTSPTRANSPORTS=tcp` environment variable is meant to disable the UDP transport protocol of the RTSP server (which requires the real IP address and port of incoming UDP packets, that are sometimes replaced by the Docker network stack). If you want to use it, you need to bypass the Docker network stack through the `--network=host` flag (which is not compatible with Windows, macOS and Kubernetes):
```sh
docker run --rm -it --network=host bluenviron/mediamtx:1
```
There are four image variants:
| name | FFmpeg included | RPI Camera support |
| -------------------------------- | ------------------ | ------------------ |
| bluenviron/mediamtx:1 | :x: | :x: |
| bluenviron/mediamtx:1-ffmpeg | :heavy_check_mark: | :x: |
| bluenviron/mediamtx:1-rpi | :x: | :heavy_check_mark: |
| bluenviron/mediamtx:1-ffmpeg-rpi | :heavy_check_mark: | :heavy_check_mark: |
The `1` tag corresponds to the latest `1.x.x` release, that should guarantee backward compatibility when upgrading. It is also possible to bind the image to a specific release, by using the release name as tag (`bluenviron/mediamtx:{docker_version_tag}`).
The base image does not contain any utility, in order to minimize size and frequency of updates. If you need additional software (like curl, wget, GStreamer), you can build a custom image by creating a file named `Dockerfile` with this content:
```Dockerfile
FROM bluenviron/mediamtx:1 AS mediamtx
FROM ubuntu:24.04
COPY --from=mediamtx /mediamtx /
COPY --from=mediamtx /mediamtx.yml /
# add anything you need.
RUN apt update && apt install -y \
gstreamer1.0-tools
ENTRYPOINT [ "/mediamtx" ]
```
And then build it:
```sh
docker build . -t my-mediamtx
```
In particular, the custom image is using the official _MediaMTX_ image as a base stage, and then adds a Linux-based operating system on top of it. Since _MediaMTX_ binaries are not tied to a specific Linux distribution or version, you can use anything you like.
## Arch Linux package
If you are running the Arch Linux distribution, launch:
```sh
git clone https://aur.archlinux.org/mediamtx.git
cd mediamtx
makepkg -si
```
## FreeBSD package
Available via ports tree or using packages (2025Q2 and later) as listed below:
```sh
cd /usr/ports/multimedia/mediamtx && make install clean
pkg install mediamtx
```
## OpenWrt binary
If the architecture of the OpenWrt device is amd64, armv6, armv7 or arm64, use the [standalone binary method](#standalone-binary) and download a Linux binary that corresponds to your architecture.
Otherwise, [compile the server from source](../6-misc/1-compile.md).
================================================
FILE: docs/1-kickoff/3-upgrade.md
================================================
# Upgrade
If you have an existing _MediaMTX_ installation, you can upgrade it to the latest version. The procedure depends on how _MediaMTX_ was installed.
## Standalone binary
The standalone binary comes with an upgrade utility that can be launched with:
```sh
./mediamtx --upgrade
```
This will replace the _MediaMTX_ executable with its latest version. Privileges to write to the executable location are required.
## Docker image
Stop and remove the container:
```sh
docker stop id-of-mediamtx-container
docker rm id-of-mediamtx-container
```
Remove the _MediaMTX_ image from cache:
```sh
docker rm bluenviron/mediamtx:1
```
Then recreate the container as described in [Install](2-install.md#docker-image).
## Arch Linux package
Repeat the installation procedure.
## FreeBSD package
Repeat the installation procedure.
## OpenWrt binary
If the architecture of the OpenWrt device is amd64, armv6, armv7 or arm64, you can use the standalone binary method.
Otherwise, recompile the server from source.
================================================
FILE: docs/1-kickoff/4-basic-usage.md
================================================
# Basic usage
1. [Publish](../2-publish/01-overview.md) a stream. For instance, you can publish a stream from a MP4 file with _FFmpeg_:
```sh
ffmpeg -re -stream_loop -1 -i file.mp4 -c copy \
-f rtsp rtsp://localhost:8554/mystream
```
or _GStreamer_:
```sh
gst-launch-1.0 rtspclientsink name=s location=rtsp://localhost:8554/mystream filesrc location=file.mp4 \
! qtdemux name=d d.video_0 ! queue ! s.sink_0 d.audio_0 ! queue ! s.sink_1
```
2. [Read](../3-read/01-overview.md) the stream. For instance, you can read the stream with _VLC_:
```sh
vlc --network-caching=50 rtsp://localhost:8554/mystream
```
or _GStreamer_:
```sh
gst-play-1.0 rtsp://localhost:8554/mystream
```
or _FFmpeg_:
```sh
ffmpeg -i rtsp://localhost:8554/mystream -c copy output.mp4
```
================================================
FILE: docs/1-kickoff/index.md
================================================
# Kickoff
================================================
FILE: docs/2-publish/01-overview.md
================================================
# Publish a stream
Live streams can be published to the server with the following protocols and codecs:
| protocol | variants | codecs |
| ---------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [SRT clients](02-srt-clients.md) | | **Video**: H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3 **Other**: KLV |
| [SRT cameras and servers](03-srt-cameras-and-servers.md) | | **Video**: H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3 **Other**: KLV |
| [WebRTC clients](04-webrtc-clients.md) | WHIP | **Video**: AV1, VP9, VP8, H265, H264 **Audio**: Opus, G722, G711 (PCMA, PCMU) |
| [WebRTC servers](05-webrtc-servers.md) | WHEP | **Video**: AV1, VP9, VP8, H265, H264 **Audio**: Opus, G722, G711 (PCMA, PCMU) |
| [RTSP clients](06-rtsp-clients.md) | UDP, TCP, RTSPS | **Video**: AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, MJPEG **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711 (PCMA, PCMU), LPCM **Other**: KLV, MPEG-TS, any RTP-compatible codec |
| [RTSP cameras and servers](07-rtsp-cameras-and-servers.md) | UDP, UDP-Multicast, TCP, RTSPS | **Video**: AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, MJPEG **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711 (PCMA, PCMU), LPCM **Other**: KLV, MPEG-TS, any RTP-compatible codec |
| [RTMP clients](08-rtmp-clients.md) | RTMP, RTMPS, Enhanced RTMP | **Video**: AV1, VP9, H265, H264 **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
| [RTMP cameras and servers](09-rtmp-cameras-and-servers.md) | RTMP, RTMPS, Enhanced RTMP | **Video**: AV1, VP9, H265, H264 **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
| [HLS cameras and servers](10-hls-cameras-and-servers.md) | Low-Latency HLS, MP4-based HLS, legacy HLS | **Video**: AV1, VP9, H265, H264 **Audio**: Opus, MPEG-4 Audio (AAC) |
| [MPEG-TS](11-mpeg-ts.md) | MPEG-TS over UDP, MPEG-TS over Unix socket | **Video**: H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3 **Other**: KLV |
| [RTP](12-rtp.md) | RTP over UDP | **Video**: AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711 (PCMA, PCMU), LPCM **Other**: KLV, MPEG-TS, any RTP-compatible codec |
We provide instructions for publishing with the following devices:
- [Raspberry Pi Cameras](13-raspberry-pi-cameras.md)
- [Generic webcams](14-generic-webcams.md)
We provide instructions for publishing with the following software:
- [FFmpeg](15-ffmpeg.md)
- [GStreamer](16-gstreamer.md)
- [OBS Studio](17-obs-studio.md)
- [Python and OpenCV](18-python-opencv.md)
- [Golang](19-golang.md)
- [Unity](20-unity.md)
- [Web browsers](21-web-browsers.md)
================================================
FILE: docs/2-publish/02-srt-clients.md
================================================
# SRT clients
SRT is a protocol that allows to publish and read live data stream, providing encryption, integrity and a retransmission mechanism. It is usually used to transfer media streams encoded with MPEG-TS. In order to publish a stream to the server with the SRT protocol, use this URL:
```
srt://localhost:8890?streamid=publish:mystream&pkt_size=1316
```
Replace `mystream` with any name you want. The resulting stream will be available on path `/mystream`.
If you need to use the standard stream ID syntax instead of the custom one in use by this server, read [Standard stream ID syntax](../4-other/21-srt-specific-features.md#standard-stream-id-syntax).
If you want to publish a stream by using a client in listening mode (i.e. with `mode=listener` appended to the URL), read the next section.
Some clients that can publish with SRT are [FFmpeg](15-ffmpeg.md), [GStreamer](16-gstreamer.md), [OBS Studio](17-obs-studio.md).
================================================
FILE: docs/2-publish/03-srt-cameras-and-servers.md
================================================
# SRT cameras and servers
In order to ingest a SRT stream from a remote server, camera or client in listening mode (i.e. with `mode=listener` appended to the URL), add the corresponding URL into the `source` parameter of a path:
```yml
paths:
proxied:
# url of the source stream, in the format srt://host:port?streamid=streamid&other_parameters
source: srt://original-url
```
================================================
FILE: docs/2-publish/04-webrtc-clients.md
================================================
# WebRTC clients
WebRTC is an API that makes use of a set of protocols and methods to connect two clients together and allow them to exchange live media or data streams. You can publish a stream with WebRTC and a web browser by visiting:
```
http://localhost:8889/mystream/publish
```
The resulting stream will be available on path `/mystream`.
WHIP is a WebRTC extension that allows to publish streams by using a URL, without passing through a web page. This allows to use WebRTC as a general purpose streaming protocol. If you are using a software that supports WHIP (for instance, latest versions of OBS Studio), you can publish a stream to the server by using this URL:
```
http://localhost:8889/mystream/whip
```
Be aware that not all browsers can read any codec, check [Supported browsers](../4-other/22-webrtc-specific-features.md#supported-browsers).
Depending on the network it might be difficult to establish a connection between server and clients, read [Solving WebRTC connectivity issues](../4-other/22-webrtc-specific-features.md#solving-webrtc-connectivity-issues).
Some clients that can publish with WebRTC and WHIP are [FFmpeg](15-ffmpeg.md), [GStreamer](16-gstreamer.md), [OBS Studio](17-obs-studio.md), [Unity](20-unity.md) and [Web browsers](21-web-browsers.md).
================================================
FILE: docs/2-publish/05-webrtc-servers.md
================================================
# WebRTC servers
In order to ingest a WebRTC stream from a remote server, add the corresponding WHEP URL into the `source` parameter of a path:
```yml
paths:
proxied:
# url of the source stream, in the format whep://host:port/path (HTTP) or wheps:// (HTTPS)
source: wheps://host:port/path
```
If the remote server is a _MediaMTX_ instance, remember to add a `/whep` suffix after the stream name, since in _MediaMTX_ [it's part of the WHEP URL](../3-read/03-webrtc.md):
```yml
paths:
proxied:
source: whep://host:port/mystream/whep
```
================================================
FILE: docs/2-publish/06-rtsp-clients.md
================================================
# RTSP clients
RTSP is a protocol that allows to publish and read streams. It supports several underlying transport protocols and encryption. In order to publish a stream to the server with the RTSP protocol, use this URL:
```
rtsp://localhost:8554/mystream
```
The resulting stream will be available on path `/mystream`.
Some clients that can publish with RTSP are [FFmpeg](15-ffmpeg.md), [GStreamer](16-gstreamer.md), [OBS Studio](17-obs-studio.md), [Python and OpenCV](18-python-opencv.md).
Advanced RTSP features and settings are described in [RTSP-specific features](../4-other/23-rtsp-specific-features.md).
## MPEG-TS inside RTSP
Some RTSP clients encode tracks with MPEG-TS before sending them to the server, causing the server to see a single "MPEG-TS" track, and preventing track conversion from a protocol to another.
It's possible to automatically demux these MPEG-TS-encoded streams, by toggling `rtspDemuxMpegts`:
```yml
pathDefaults:
# Demux MPEG-TS over RTSP into elementary streams.
# When enabled, RTSP publishers sending MP2T/90000 will be demultiplexed
# and their elementary streams (H.264, H.265, AAC, etc.) exposed as native tracks.
# This allows HLS, WebRTC, and other outputs to work transparently with MPEG-TS sources.
rtspDemuxMpegts: true
```
================================================
FILE: docs/2-publish/07-rtsp-cameras-and-servers.md
================================================
# RTSP cameras and servers
Most IP cameras expose their video stream by using a RTSP server that is embedded into the camera itself. In particular, cameras that are compliant with ONVIF profile S or T meet this requirement. You can use _MediaMTX_ to connect to one or several existing RTSP servers and read their media streams:
```yml
paths:
proxied:
# url of the source stream, in the format rtsp://user:pass@host:port/path
source: rtsp://original-url
```
The resulting stream will be available on path `/proxied`.
It is possible to tune the connection by using some additional parameters:
```yml
paths:
proxied:
# url of the source stream, in the format rtsp://user:pass@host:port/path
source: rtsp://original-url
# Transport protocol used to pull the stream. available values are "automatic", "udp", "multicast", "tcp".
rtspTransport: automatic
# Support sources that don't provide server ports or use random server ports. This is a security issue
# and must be used only when interacting with sources that require it.
rtspAnyPort: no
# Range header to send to the source, in order to start streaming from the specified offset.
# available values:
# * clock: Absolute time
# * npt: Normal Play Time
# * smpte: SMPTE timestamps relative to the start of the recording
rtspRangeType:
# Available values:
# * clock: UTC ISO 8601 combined date and time string, e.g. 20230812T120000Z
# * npt: duration such as "300ms", "1.5m" or "2h45m", valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h"
# * smpte: duration such as "300ms", "1.5m" or "2h45m", valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h"
rtspRangeStart:
# Size of the UDP buffer of the RTSP client.
# This can be increased to mitigate packet losses.
# It defaults to the default value of the operating system.
rtspUDPReadBufferSize: 0
# Range of ports used as source port in outgoing UDP packets.
rtspUDPSourcePortRange: [10000, 65535]
```
All available parameters are listed in the [configuration file](../5-references/1-configuration-file.md).
Advanced RTSP features and settings are described in [RTSP-specific features](../4-other/23-rtsp-specific-features.md).
================================================
FILE: docs/2-publish/08-rtmp-clients.md
================================================
# RTMP clients
RTMP is a protocol that allows to read and publish streams. It supports encryption, read [RTMP-specific features](../4-other/24-rtmp-specific-features.md). Streams can be published to the server by using the URL:
```
rtmp://localhost/mystream
```
The resulting stream will be available on path `/mystream`.
Some clients that can publish with RTMP are [FFmpeg](15-ffmpeg.md), [GStreamer](16-gstreamer.md), [OBS Studio](17-obs-studio.md).
================================================
FILE: docs/2-publish/09-rtmp-cameras-and-servers.md
================================================
# RTMP cameras and servers
You can use _MediaMTX_ to connect to one or several existing RTMP servers and read their media streams:
```yml
paths:
proxied:
# url of the source stream, in the format rtmp://user:pass@host:port/path
source: rtmp://original-url
```
The resulting stream will be available on path `/proxied`.
================================================
FILE: docs/2-publish/10-hls-cameras-and-servers.md
================================================
# HLS cameras and servers
HLS is a streaming protocol that works by splitting streams into segments, and by serving these segments and a playlist with the HTTP protocol. You can use _MediaMTX_ to connect to one or several existing HLS servers and read their media streams:
```yml
paths:
proxied:
# url of the playlist of the stream, in the format http://user:pass@host:port/path
source: http://original-url/stream/index.m3u8
```
The resulting stream will be available on path `/proxied`.
================================================
FILE: docs/2-publish/11-mpeg-ts.md
================================================
# MPEG-TS
The server supports ingesting MPEG-TS streams, shipped in two different ways (UDP packets or Unix sockets).
In order to read a UDP MPEG-TS stream, edit `mediamtx.yml` and replace everything inside section `paths` with the following content:
```yml
paths:
mypath:
source: udp+mpegts://238.0.0.1:1234
```
Where `238.0.0.1` is the IP for listening packets, in this case a multicast IP.
If the listening IP is a multicast IP, _MediaMTX_ will listen for incoming packets on the default multicast interface, picked by the operating system. It is possible to specify the interface manually by using the `interface` parameter:
```yml
paths:
mypath:
source: udp+mpegts://238.0.0.1:1234?interface=eth0
```
It is possible to restrict who can send packets by using the `source` parameter:
```yml
paths:
mypath:
source: udp+mpegts://0.0.0.0:1234?source=192.168.3.5
```
Some clients that can publish with UDP and MPEG-TS are [FFmpeg](15-ffmpeg.md) and [GStreamer](16-gstreamer.md).
Unix sockets are more efficient than UDP packets and can be used as transport by specifying the `unix+mpegts` scheme:
```yml
paths:
mypath:
source: unix+mpegts:///tmp/socket.sock
```
================================================
FILE: docs/2-publish/12-rtp.md
================================================
# RTP
The server supports ingesting RTP streams, transmitted with UDP packets.
In order to read a UDP RTP stream, edit `mediamtx.yml` and replace everything inside section `paths` with the following content:
```yml
paths:
mypath:
source: udp+rtp://238.0.0.1:1234
rtpSDP: |
v=0
o=- 123456789 123456789 IN IP4 192.168.1.100
s=H264 Video Stream
c=IN IP4 192.168.1.100
t=0 0
m=video 5004 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=42e01e;packetization-mode=1;sprop-parameter-sets=Z0LAHtkDxWhAAAADAEAAAAwDxYuS,aMuMsg==
```
`rtpSDP` must contain a valid SDP, that is a description of the RTP session.
Some clients that can publish with UDP and MPEG-TS are [FFmpeg](15-ffmpeg.md) and [GStreamer](16-gstreamer.md).
================================================
FILE: docs/2-publish/13-raspberry-pi-cameras.md
================================================
# Raspberry Pi Cameras
_MediaMTX_ natively supports most Raspberry Pi Camera models, enabling high-quality and low-latency video streaming from the camera to any user, for any purpose. There are some additional requirements:
1. The server must run on a Raspberry Pi, with one of the following operating systems:
- Raspberry Pi OS Trixie
- Raspberry Pi OS Bookworm
- Raspberry Pi OS Bullseye
Both 32-bit and 64-bit architectures are supported.
2. If you are using Raspberry Pi OS Bullseye, make sure that the legacy camera stack is disabled. Type `sudo raspi-config`, then go to `Interfacing options`, `enable/disable legacy camera support`, choose `no`. Reboot the system.
The setup procedure depends on whether you want to run the server outside or inside Docker:
- If you want to run the standard (non-Dockerized) version of the server:
1. Download the server executable. If you're using 64-bit version of the operative system, make sure to pick the `arm64` variant.
2. Edit `mediamtx.yml` and replace everything inside section `paths` with the following content:
```yml
paths:
cam:
source: rpiCamera
```
The resulting stream will be available on path `/cam`.
- If you want to run the server inside Docker, you need to use the `1-rpi` image and launch the container with some additional flags:
```sh
docker run --rm -it \
--network=host \
--privileged \
--tmpfs /dev/shm:exec \
-v /run/udev:/run/udev:ro \
-e MTX_PATHS_CAM_SOURCE=rpiCamera \
bluenviron/mediamtx:1-rpi
```
The Raspberry Pi Camera can be controlled through a wide range of parameters, that are listed in the [configuration file](../5-references/1-configuration-file.md).
Be aware that cameras that require a custom `libcamera` (like some ArduCam products) are not compatible with precompiled binaries and Docker images of _MediaMTX_, since these come with a bundled `libcamera`. If you want to use a custom one, you need to [compile from source](../6-misc/1-compile.md#custom-libcamera).
## Adding audio
In order to add audio from a USB microphone, install GStreamer and alsa-utils:
```sh
sudo apt install -y gstreamer1.0-tools gstreamer1.0-rtsp gstreamer1.0-alsa alsa-utils
```
list available audio cards with:
```sh
arecord -L
```
Sample output:
```
surround51:CARD=ICH5,DEV=0
Intel ICH5, Intel ICH5
5.1 Surround output to Front, Center, Rear and Subwoofer speakers
default:CARD=U0x46d0x809
USB Device 0x46d:0x809, USB Audio
Default Audio Device
```
Find the audio card of the microphone and take note of its name, for instance `default:CARD=U0x46d0x809`. Then create a new path that takes the video stream from the camera and audio from the microphone:
```yml
paths:
cam:
source: rpiCamera
cam_with_audio:
runOnInit: >
gst-launch-1.0
rtspclientsink name=s location=rtsp://localhost:$RTSP_PORT/cam_with_audio
rtspsrc location=rtsp://127.0.0.1:$RTSP_PORT/cam latency=0 ! rtph264depay ! s.
alsasrc device=default:CARD=U0x46d0x809 ! opusenc bitrate=16000 ! s.
runOnInitRestart: yes
```
The resulting stream will be available on path `/cam_with_audio`.
## Secondary stream
It is possible to enable a secondary stream from the same camera, with a different resolution, FPS and codec. Configuration is the same of a primary stream, with `rpiCameraSecondary` set to `true` and parameters adjusted accordingly:
```yml
paths:
# primary stream
rpi:
source: rpiCamera
# Width of frames.
rpiCameraWidth: 1920
# Height of frames.
rpiCameraHeight: 1080
# FPS.
rpiCameraFPS: 30
# secondary stream
secondary:
source: rpiCamera
# This is a secondary stream.
rpiCameraSecondary: true
# Width of frames.
rpiCameraWidth: 640
# Height of frames.
rpiCameraHeight: 480
# FPS.
rpiCameraFPS: 10
# Codec. in case of secondary streams, it defaults to M-JPEG.
rpiCameraCodec: auto
# JPEG quality.
rpiCameraMJPEGQuality: 60
```
The secondary stream will be available on path `/secondary`.
================================================
FILE: docs/2-publish/14-generic-webcams.md
================================================
# Generic webcams
If the operating system is Linux, edit `mediamtx.yml` and replace everything inside section `paths` with the following content:
```yml
paths:
cam:
runOnInit: ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH
runOnInitRestart: yes
```
If the operating system is Windows:
```yml
paths:
cam:
runOnInit: ffmpeg -f dshow -i video="USB2.0 HD UVC WebCam" -c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH
runOnInitRestart: yes
```
Where `USB2.0 HD UVC WebCam` is the name of a webcam, that can be obtained with:
```sh
ffmpeg -list_devices true -f dshow -i dummy
```
The resulting stream will be available on path `/cam`.
================================================
FILE: docs/2-publish/15-ffmpeg.md
================================================
# FFmpeg
FFmpeg can publish a stream to the server in several ways. The recommended one consists in publishing with RTSP.
## FFmpeg and RTSP
```sh
ffmpeg -re -stream_loop -1 -i file.mp4 -c copy -f rtsp rtsp://localhost:8554/mystream
```
The resulting stream will be available on path `/mystream`.
## FFmpeg and RTMP
```sh
ffmpeg -re -stream_loop -1 -i file.mp4 -c copy -f flv rtmp://localhost:1935/mystream
```
## FFmpeg and MPEG-TS over UDP
In _MediaMTX_ configuration, add a path with `source: udp+mpegts://238.0.0.1:1234`. Then:
```sh
ffmpeg -re -stream_loop -1 -i file.mp4 -c copy -f mpegts 'udp://238.0.0.1:1234?pkt_size=1316'
```
## FFmpeg and MPEG-TS over Unix socket
In _MediaMTX_ configuration, add a path with `source: unix+mpegts:///tmp/socket.sock`. Then:
```sh
ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
-c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k \
-f mpegts unix:/tmp/socket.sock
```
## FFmpeg and RTP over UDP
In _MediaMTX_ configuration, add a path with `source: udp+rtp://238.0.0.1:1234` and a valid `rtpSDP` (read [RTP](12-rtp.md)). Then:
```sh
ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
-c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k \
-f rtp udp://238.0.0.1:1234?pkt_size=1316
```
## FFmpeg and SRT
```sh
ffmpeg -re -stream_loop -1 -i file.mp4 -c copy -f mpegts 'srt://localhost:8890?streamid=publish:stream&pkt_size=1316'
```
## FFmpeg and WebRTC
```sh
ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
-f lavfi -i "sine=frequency=1000:sample_rate=48000" \
-c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k \
-c:a libopus -ar 48000 -ac 2 -b:a 128k \
-f whip http://localhost:8889/stream/whip
```
WARNING: in case of FFmpeg 8.0, a video track and an audio track must both be present.
================================================
FILE: docs/2-publish/16-gstreamer.md
================================================
# GStreamer
GStreamer can publish a stream to the server in several ways. The recommended one consists in publishing with RTSP.
## GStreamer and RTSP
```sh
gst-launch-1.0 rtspclientsink name=s location=rtsp://localhost:8554/mystream \
filesrc location=file.mp4 ! qtdemux name=d \
d.video_0 ! queue ! s.sink_0 \
d.audio_0 ! queue ! s.sink_1
```
If the stream is video only:
```sh
gst-launch-1.0 filesrc location=file.mp4 ! qtdemux name=d \
d.video_0 ! rtspclientsink location=rtsp://localhost:8554/mystream
```
The resulting stream will be available on path `/mystream`.
For advanced options, read [RTSP-specific features](../4-other/23-rtsp-specific-features.md).
## GStreamer and RTMP
```sh
gst-launch-1.0 -v flvmux name=mux ! rtmpsink location=rtmp://localhost/stream \
videotestsrc ! video/x-raw,width=1280,height=720,format=I420 ! x264enc speed-preset=ultrafast bitrate=3000 key-int-max=60 ! video/x-h264,profile=high ! mux. \
audiotestsrc ! audioconvert ! avenc_aac ! mux.
```
## GStreamer and MPEG-TS over UDP
```sh
gst-launch-1.0 -v mpegtsmux name=mux alignment=1 ! udpsink host=238.0.0.1 port=1234 \
videotestsrc ! video/x-raw,width=1280,height=720,format=I420 ! x264enc speed-preset=ultrafast bitrate=3000 key-int-max=60 ! video/x-h264,profile=high ! mux. \
audiotestsrc ! audioconvert ! avenc_aac ! mux.
```
For advanced options, read [RTSP-specific features](../4-other/23-rtsp-specific-features.md).
## GStreamer and WebRTC
Make sure that GStreamer version is at least 1.22, and that if the codec is H264, the profile is baseline. Use the `whipclientsink` element:
```sh
gst-launch-1.0 videotestsrc \
! video/x-raw,width=1920,height=1080,format=I420 \
! x264enc speed-preset=ultrafast bitrate=2000 \
! video/x-h264,profile=baseline \
! whipclientsink signaller::whip-endpoint=http://localhost:8889/mystream/whip
```
================================================
FILE: docs/2-publish/17-obs-studio.md
================================================
# OBS Studio
OBS Studio can publish streams to the server in several ways. The recommended one consists in publishing with RTMP.
## OBS Studio and RTMP
In `Settings -> Stream` (or in the Auto-configuration Wizard), use the following parameters:
- Service: `Custom...`
- Server: `rtmp://localhost/mystream`
- Stream key: (empty)
Save the configuration and click `Start streaming`.
The resulting stream will be available on path `/mystream`.
If you want to generate a stream that can be read with WebRTC, open `Settings -> Output -> Recording` and use the following parameters:
- FFmpeg output type: `Output to URL`
- File path or URL: `rtsp://localhost:8554/mystream`
- Container format: `rtsp`
- Check `show all codecs (even if potentially incompatible)`
- Video encoder: `h264_nvenc (libx264)`
- Video encoder settings (if any): `bf=0`
- Audio track: `1`
- Audio encoder: `libopus`
Then use the button `Start Recording` (instead of `Start Streaming`) to start streaming.
## OBS Studio and RTMP, multitrack video
OBS Studio can publish multiple video tracks or renditions at once (simulcast). Make sure that the OBS Studio version is ≥ 31.0.0. Open `Settings -> Stream` and use the following parameters:
- Service: `Custom...`
- Server: `rtmp://localhost/mystream`
- Stream key: (empty)
- Turn on `Enable Multitrack Video`
- Leave `Maximum Streaming Bandwidth` and `Maximum Video Tracks` to `Auto`
- Turn on `Enable Config Override`
- Fill `Config Override (JSON)` with the following text:
```json
{
"encoder_configurations": [
{
"type": "obs_x264",
"width": 1920,
"height": 1080,
"framerate": {
"numerator": 30,
"denominator": 1
},
"settings": {
"rate_control": "CBR",
"bitrate": 6000,
"keyint_sec": 2,
"preset": "veryfast",
"profile": "high",
"tune": "zerolatency"
},
"canvas_index": 0
},
{
"type": "obs_x264",
"width": 640,
"height": 480,
"framerate": {
"numerator": 30,
"denominator": 1
},
"settings": {
"rate_control": "CBR",
"bitrate": 3000,
"keyint_sec": 2,
"preset": "veryfast",
"profile": "main",
"tune": "zerolatency"
},
"canvas_index": 0
}
],
"audio_configurations": {
"live": [
{
"codec": "ffmpeg_aac",
"track_id": 1,
"channels": 2,
"settings": {
"bitrate": 160
}
}
]
}
}
```
This can be adjusted according to specific needs. In particular, the `type` field is used to set the video encoder, and these are the available parameters:
- `obs_nvenc_av1_tex`: NVIDIA NVENC AV1
- `obs_nvenc_hevc_tex`: NVIDIA NVENC H265
- `obs_nvenc_h264_tex`: NVIDIA NVENC H264
- `av1_texture_amf`: AMD AV1
- `h265_texture_amf`: AMD H265
- `h264_texture_amf`: AMD H264
- `obs_qsv11_av1`: QuickSync AV1
- `obs_qsv11_v2`: QuickSync H264
- `obs_x264`: software H264
Save the configuration and click `Start streaming`.
The resulting stream will be available on path `/mystream`.
## OBS Studio and WebRTC
Recent versions of OBS Studio can also publish streams to the server with the [WebRTC / WHIP protocol](04-webrtc-clients.md) Use the following parameters:
- Service: `WHIP`
- Server: `http://localhost:8889/mystream/whip`
Save the configuration and click `Start streaming`.
The resulting stream will be available on path `/mystream`.
## OBS Studio and WebRTC, multitrack video
OBS Studio can publish multiple video tracks or renditions at once (simulcast) with WebRTC / WHIP too. Make sure that the OBS Studio version is ≥ 32.1.0. Open `Settings -> Stream` and use the following parameters:
- Service: `WHIP`
- Server: `http://localhost:8889/mystream/whip`
- Simulcast, Total Layers: `2` (or greater)
Currently it's not possible to change resolution or bitrate (or canvas) of renditions, since quality of secondary renditions is hardcoded as a percentage of the main one. You can find details on the [OBS documentation](https://obsproject.com/kb/whip-streaming-guide).
Save the configuration and click `Start streaming`.
The resulting stream will be available on path `/mystream`.
================================================
FILE: docs/2-publish/18-python-opencv.md
================================================
# Python and OpenCV
Python-based software can publish streams to the server with the OpenCV library and its GStreamer plugin, acting as a [RTSP client](06-rtsp-clients.md). OpenCV must be compiled with support for GStreamer, by following this procedure:
```sh
sudo apt install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-ugly gstreamer1.0-rtsp python3-dev python3-numpy
git clone --depth=1 -b 4.5.4 https://github.com/opencv/opencv
cd opencv
mkdir build && cd build
cmake -D CMAKE_INSTALL_PREFIX=/usr -D WITH_GSTREAMER=ON ..
make -j$(nproc)
sudo make install
```
You can check that OpenCV has been installed correctly by running:
```sh
python3 -c 'import cv2; print(cv2.getBuildInformation())'
```
Check that the output contains `GStreamer: YES`.
Videos can then be published with `cv2.VideoWriter`:
```python
from datetime import datetime
from time import sleep, time
import cv2
import numpy as np
fps = 15
width = 800
height = 600
colors = [
(0, 0, 255),
(255, 0, 0),
(0, 255, 0),
]
out = cv2.VideoWriter('appsrc ! videoconvert' + \
' ! video/x-raw,format=I420' + \
' ! x264enc speed-preset=ultrafast bitrate=600 key-int-max=' + str(fps * 2) + \
' ! video/x-h264,profile=baseline' + \
' ! rtspclientsink location=rtsp://localhost:8554/mystream',
cv2.CAP_GSTREAMER, 0, fps, (width, height), True)
if not out.isOpened():
raise Exception("can't open video writer")
curcolor = 0
start = time()
while True:
frame = np.zeros((height, width, 3), np.uint8)
# create a rectangle
color = colors[curcolor]
curcolor += 1
curcolor %= len(colors)
for y in range(0, int(frame.shape[0] / 2)):
for x in range(0, int(frame.shape[1] / 2)):
frame[y][x] = color
out.write(frame)
print("%s frame written to the server" % datetime.now())
now = time()
diff = (1 / fps) - now - start
if diff > 0:
sleep(diff)
start = now
```
The resulting stream will be available on path `/mystream`.
================================================
FILE: docs/2-publish/19-golang.md
================================================
# Golang
You can publish a stream to the server by using the Go programming language and the following libraries:
- [gortsplib](https://github.com/bluenviron/gortsplib) to publish with RTSP.
- [gortmplib](https://github.com/bluenviron/gortmplib) to publish with RTMP.
Both powers _MediaMTX_ itself. In the repositories of these projects there are several examples on how to connect to a server and push data.
================================================
FILE: docs/2-publish/20-unity.md
================================================
# Unity
Software written with the Unity Engine can publish a stream to the server by using the [WebRTC protocol](04-webrtc-clients.md).
Create a new Unity project or open an existing one.
Open _Window -> Package Manager_, click on the plus sign, _Add Package by name..._ and insert `com.unity.webrtc`. Wait for the package to be installed.
In the _Project_ window, under `Assets`, create a new C# Script called `WebRTCPublisher.cs` with this content:
```cs
using System.Collections;
using UnityEngine;
using Unity.WebRTC;
using UnityEngine.Networking;
public class WebRTCPublisher : MonoBehaviour
{
public string url = "http://localhost:8889/unity/whip";
public int videoWidth = 1280;
public int videoHeight = 720;
private RTCPeerConnection pc;
private MediaStream videoStream;
void Start()
{
pc = new RTCPeerConnection();
Camera sourceCamera = gameObject.GetComponent();
videoStream = sourceCamera.CaptureStream(videoWidth, videoHeight);
foreach (var track in videoStream.GetTracks())
{
pc.AddTrack(track);
}
StartCoroutine(WebRTC.Update());
StartCoroutine(createOffer());
}
private IEnumerator createOffer()
{
var op = pc.CreateOffer();
yield return op;
if (op.IsError) {
Debug.LogError("CreateOffer() failed");
yield break;
}
yield return setLocalDescription(op.Desc);
}
private IEnumerator setLocalDescription(RTCSessionDescription offer)
{
var op = pc.SetLocalDescription(ref offer);
yield return op;
if (op.IsError) {
Debug.LogError("SetLocalDescription() failed");
yield break;
}
yield return postOffer(offer);
}
private IEnumerator postOffer(RTCSessionDescription offer)
{
var content = new System.Net.Http.StringContent(offer.sdp);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/sdp");
var client = new System.Net.Http.HttpClient();
var task = System.Threading.Tasks.Task.Run(async () => {
var res = await client.PostAsync(new System.UriBuilder(url).Uri, content);
res.EnsureSuccessStatusCode();
return await res.Content.ReadAsStringAsync();
});
yield return new WaitUntil(() => task.IsCompleted);
if (task.Exception != null) {
Debug.LogError(task.Exception);
yield break;
}
yield return setRemoteDescription(task.Result);
}
private IEnumerator setRemoteDescription(string answer)
{
RTCSessionDescription desc = new RTCSessionDescription();
desc.type = RTCSdpType.Answer;
desc.sdp = answer;
var op = pc.SetRemoteDescription(ref desc);
yield return op;
if (op.IsError) {
Debug.LogError("SetRemoteDescription() failed");
yield break;
}
yield break;
}
void OnDestroy()
{
pc?.Close();
pc?.Dispose();
videoStream?.Dispose();
}
}
```
In the _Hierarchy_ window, find or create a scene and a camera, then add the `WebRTCPublisher.cs` script as component of the camera, by dragging it inside the _Inspector_ window. then Press the _Play_ button at the top of the page.
The resulting stream will be available on path `/unity`.
================================================
FILE: docs/2-publish/21-web-browsers.md
================================================
# Web browsers
Web browsers can publish a stream to the server by using the [WebRTC protocol](04-webrtc-clients.md). Start the server and open the web page:
```
http://localhost:8889/mystream/publish
```
The resulting stream will be available on path `/mystream`.
This web page can be embedded into another web page by using an iframe:
```html
```
For more advanced setups, you can create and serve a custom web page by starting from the [source code of the WebRTC publish page](https://github.com/bluenviron/mediamtx/blob/{version_tag}/internal/servers/webrtc/publish_index.html). In particular, there's a ready-to-use, standalone JavaScript class for publishing streams with WebRTC, available in [publisher.js](https://github.com/bluenviron/mediamtx/blob/{version_tag}/internal/servers/webrtc/publisher.js).
================================================
FILE: docs/2-publish/index.md
================================================
# Publish
================================================
FILE: docs/3-read/01-overview.md
================================================
# Read a stream
Live streams can be read from the server with the following protocols and codecs:
| protocol | variants | codecs |
| ------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [SRT clients](02-srt.md) | | **Video**: H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3 **Other**: KLV |
| [WebRTC clients](03-webrtc.md) | WHEP | **Video**: AV1, VP9, VP8, H265, H264 **Audio**: Opus, G722, G711 (PCMA, PCMU) **Other**: KLV |
| [RTSP clients](04-rtsp.md) | UDP, UDP-Multicast, TCP, RTSPS | **Video**: AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711 (PCMA, PCMU), LPCM **Other**: KLV, MPEG-TS, any RTP-compatible codec |
| [RTMP clients](05-rtmp.md) | RTMP, RTMPS, Enhanced RTMP | **Video**: AV1, VP9, H265, H264 **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
| [HLS](06-hls.md) | Low-Latency HLS, MP4-based HLS, legacy HLS | **Video**: AV1, VP9, H265, H264 **Audio**: Opus, MPEG-4 Audio (AAC) |
We provide instructions for reading with the following software:
- [FFmpeg](07-ffmpeg.md)
- [GStreamer](08-gstreamer.md)
- [VLC](09-vlc.md)
- [OBS Studio](10-obs-studio.md)
- [Python and OpenCV](11-python-opencv.md)
- [Golang](12-golang.md)
- [Unity](13-unity.md)
- [Web browsers](14-web-browsers.md)
================================================
FILE: docs/3-read/02-srt.md
================================================
# SRT clients
SRT is a protocol that allows to publish and read live data stream, providing encryption, integrity and a retransmission mechanism. It is usually used to transfer media streams encoded with MPEG-TS. In order to read a stream from the server with the SRT protocol, use this URL:
```
srt://localhost:8890?streamid=read:mystream
```
Replace `mystream` with the path name.
If you need to use the standard stream ID syntax instead of the custom one in use by this server, read [Standard stream ID syntax](../4-other/21-srt-specific-features.md#standard-stream-id-syntax).
Some clients that can read with SRT are [FFmpeg](07-ffmpeg.md), [GStreamer](08-gstreamer.md) and [VLC](09-vlc.md).
================================================
FILE: docs/3-read/03-webrtc.md
================================================
# WebRTC clients
WebRTC is an API that makes use of a set of protocols and methods to connect two clients together and allow them to exchange live media or data streams. You can read a stream with WebRTC and a web browser by visiting:
```
http://localhost:8889/mystream
```
WHEP is a WebRTC extension that allows to read streams by using a URL, without passing through a web page. This allows to use WebRTC as a general purpose streaming protocol. If you are using a software that supports WHEP, you can read a stream from the server by using this URL:
```
http://localhost:8889/mystream/whep
```
Be aware that not all browsers can read any codec, check [Supported browsers](../4-other/22-webrtc-specific-features.md#supported-browsers).
Depending on the network it may be difficult to establish a connection between server and clients, read [Solving WebRTC connectivity issues](../4-other/22-webrtc-specific-features.md#solving-webrtc-connectivity-issues).
Some clients that can read with WebRTC and WHEP are [FFmpeg](07-ffmpeg.md), [GStreamer](08-gstreamer.md), [Unity](13-unity.md) and [web browsers](14-web-browsers.md).
================================================
FILE: docs/3-read/04-rtsp.md
================================================
# RTSP clients
RTSP is a protocol that allows to publish and read streams. It supports several underlying transport protocols and encryption (read [RTSP-specific features](../4-other/23-rtsp-specific-features.md)). In order to read a stream with the RTSP protocol, use this URL:
```
rtsp://localhost:8554/mystream
```
Some clients that can read with RTSP are [FFmpeg](07-ffmpeg.md), [GStreamer](08-gstreamer.md) and [VLC](09-vlc.md).
================================================
FILE: docs/3-read/05-rtmp.md
================================================
# RTMP clients
RTMP is a protocol that allows to read and publish streams. It supports encryption, read [RTMP-specific features](../4-other/24-rtmp-specific-features.md). Streams can be read from the server by using the URL:
```
rtmp://localhost/mystream
```
Some clients that can read with RTMP are [FFmpeg](07-ffmpeg.md), [GStreamer](08-gstreamer.md) and [VLC](09-vlc.md).
================================================
FILE: docs/3-read/06-hls.md
================================================
# HLS
HLS is a protocol that works by splitting streams into segments, and by serving these segments and a playlist with the HTTP protocol. You can use _MediaMTX_ to generate an HLS stream, that is accessible through a web page:
```
http://localhost:8888/mystream
```
and can also be accessed without using the browsers, by software that supports the HLS protocol (for instance VLC or _MediaMTX_ itself) by using this URL:
```
http://localhost:8888/mystream/index.m3u8
```
Some clients that can read with HLS are [FFmpeg](07-ffmpeg.md), [GStreamer](08-gstreamer.md), [VLC](09-vlc.md) and [web browsers](14-web-browsers.md).
================================================
FILE: docs/3-read/07-ffmpeg.md
================================================
# FFmpeg
FFmpeg can read a stream from the server in several ways. The recommended one consists in reading with RTSP.
## FFmpeg and RTSP
```sh
ffmpeg -i rtsp://localhost:8554/mystream -c copy output.mp4
```
## FFmpeg and RTMP
```sh
ffmpeg -i rtmp://localhost/mystream -c copy output.mp4
```
In order to read AV1, VP9, H265, Opus, AC3 tracks and in order to read multiple video or audio tracks, the `-rtmp_enhanced_codecs` flag must be present:
```sh
ffmpeg -rtmp_enhanced_codecs ac-3,av01,avc1,ec-3,fLaC,hvc1,.mp3,mp4a,Opus,vp09 \
-i rtmp://localhost/mystream -c copy output.mp4
```
## FFmpeg and SRT
```sh
ffmpeg -i 'srt://localhost:8890?streamid=read:test' -c copy output.mp4
```
================================================
FILE: docs/3-read/08-gstreamer.md
================================================
# GStreamer
GStreamer can read a stream from the server in several ways. The recommended one consists in reading with RTSP.
## GStreamer and RTSP
```sh
gst-launch-1.0 rtspsrc location=rtsp://127.0.0.1:8554/mystream latency=0 ! decodebin ! autovideosink
```
For advanced options, read [RTSP-specific features](../4-other/23-rtsp-specific-features.md).
## GStreamer and WebRTC
GStreamer also supports reading streams with WebRTC/WHEP, although track codecs must be specified in advance through the `video-caps` and `audio-caps` parameters. Furthermore, if audio is not present, `audio-caps` must be set anyway and must point to a PCMU codec. For instance, the command for reading a video-only H264 stream is:
```sh
gst-launch-1.0 whepsrc whep-endpoint=http://127.0.0.1:8889/stream/whep use-link-headers=true \
video-caps="application/x-rtp,media=video,encoding-name=H264,payload=127,clock-rate=90000" \
audio-caps="application/x-rtp,media=audio,encoding-name=PCMU,payload=0,clock-rate=8000" \
! rtph264depay ! decodebin ! autovideosink
```
While the command for reading an audio-only Opus stream is:
```sh
gst-launch-1.0 whepsrc whep-endpoint="http://127.0.0.1:8889/stream/whep" use-link-headers=true \
audio-caps="application/x-rtp,media=audio,encoding-name=OPUS,payload=111,clock-rate=48000,encoding-params=(string)2" \
! rtpopusdepay ! decodebin ! autoaudiosink
```
While the command for reading a H264 and Opus stream is:
```sh
gst-launch-1.0 whepsrc whep-endpoint=http://127.0.0.1:8889/stream/whep use-link-headers=true \
video-caps="application/x-rtp,media=video,encoding-name=H264,payload=127,clock-rate=90000" \
audio-caps="application/x-rtp,media=audio,encoding-name=OPUS,payload=111,clock-rate=48000,encoding-params=(string)2" \
! decodebin ! autovideosink
```
================================================
FILE: docs/3-read/09-vlc.md
================================================
# VLC
VLC can read a stream from the server in several ways. The recommended one consists in reading with RTSP:
```sh
vlc --network-caching=50 rtsp://localhost:8554/mystream
```
## RTSP and Ubuntu compatibility
The VLC shipped with Ubuntu 21.10 doesn't support playing RTSP due to a license issue (read [here](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=982299) and [here](https://stackoverflow.com/questions/69766748/cvlc-cannot-play-rtsp-omxplayer-instead-can)). To fix the issue, remove the default VLC instance and install the snap version:
```sh
sudo apt purge -y vlc
snap install vlc
```
## Encrypted RTSP compatibility
At the moment VLC doesn't support reading encrypted RTSP streams. However, you can use a proxy like [stunnel](https://www.stunnel.org) or [nginx](https://nginx.org/) or a local _MediaMTX_ instance to decrypt streams before reading them.
================================================
FILE: docs/3-read/10-obs-studio.md
================================================
# OBS Studio
OBS Studio can read streams from the server by using the [RTSP protocol](04-rtsp.md).
Open OBS, click on _Add Source_, _Media source_, _OK_, uncheck _Local file_, insert in _Input_:
```
rtsp://localhost:8554/stream
```
Then _Ok_.
================================================
FILE: docs/3-read/11-python-opencv.md
================================================
# Python and OpenCV
Python-based software can read streams from the server with the OpenCV library, acting as a [RTSP client](04-rtsp.md).
```python
import cv2
cap = cv2.VideoCapture('rtsp://localhost:8554/mystream')
if not cap.isOpened():
raise Exception("can't open video capture")
while True:
ret, frame = cap.read()
if not ret:
raise Exception("can't receive frame")
cv2.imshow('frame', frame)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
```
================================================
FILE: docs/3-read/12-golang.md
================================================
# Golang
You can read a stream from the server by using the Go programming language and the following libraries:
- [gortsplib](https://github.com/bluenviron/gortsplib) to read with RTSP.
- [gortmplib](https://github.com/bluenviron/gortmplib) to read with RTMP.
- [gohlslib](https://github.com/bluenviron/gohlslib) to read with HLS.
All these power _MediaMTX_ itself. In the repositories of these projects there are several examples on how to connect to a server and read data.
================================================
FILE: docs/3-read/13-unity.md
================================================
# Unity
Software written with the Unity Engine can read a stream from the server by using the [WebRTC protocol](03-webrtc.md).
Create a new Unity project or open an existing one.
Open _Window -> Package Manager_, click on the plus sign, _Add Package by name..._ and insert `com.unity.webrtc`. Wait for the package to be installed.
In the _Project_ window, under `Assets`, create a new C# Script called `WebRTCReader.cs` with this content:
```cs
using System.Collections;
using UnityEngine;
using Unity.WebRTC;
public class WebRTCReader : MonoBehaviour
{
public string url = "http://localhost:8889/stream/whep";
private RTCPeerConnection pc;
private MediaStream receiveStream;
void Start()
{
UnityEngine.UI.RawImage rawImage = gameObject.GetComponentInChildren();
AudioSource audioSource = gameObject.GetComponentInChildren();
pc = new RTCPeerConnection();
receiveStream = new MediaStream();
pc.OnTrack = e =>
{
receiveStream.AddTrack(e.Track);
};
receiveStream.OnAddTrack = e =>
{
if (e.Track is VideoStreamTrack videoTrack)
{
videoTrack.OnVideoReceived += (tex) =>
{
rawImage.texture = tex;
};
}
else if (e.Track is AudioStreamTrack audioTrack)
{
audioSource.SetTrack(audioTrack);
audioSource.loop = true;
audioSource.Play();
}
};
RTCRtpTransceiverInit init = new RTCRtpTransceiverInit();
init.direction = RTCRtpTransceiverDirection.RecvOnly;
pc.AddTransceiver(TrackKind.Audio, init);
pc.AddTransceiver(TrackKind.Video, init);
StartCoroutine(WebRTC.Update());
StartCoroutine(createOffer());
}
private IEnumerator createOffer()
{
var op = pc.CreateOffer();
yield return op;
if (op.IsError) {
Debug.LogError("CreateOffer() failed");
yield break;
}
yield return setLocalDescription(op.Desc);
}
private IEnumerator setLocalDescription(RTCSessionDescription offer)
{
var op = pc.SetLocalDescription(ref offer);
yield return op;
if (op.IsError) {
Debug.LogError("SetLocalDescription() failed");
yield break;
}
yield return postOffer(offer);
}
private IEnumerator postOffer(RTCSessionDescription offer)
{
var content = new System.Net.Http.StringContent(offer.sdp);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/sdp");
var client = new System.Net.Http.HttpClient();
var task = System.Threading.Tasks.Task.Run(async () => {
var res = await client.PostAsync(new System.UriBuilder(url).Uri, content);
res.EnsureSuccessStatusCode();
return await res.Content.ReadAsStringAsync();
});
yield return new WaitUntil(() => task.IsCompleted);
if (task.Exception != null) {
Debug.LogError(task.Exception);
yield break;
}
yield return setRemoteDescription(task.Result);
}
private IEnumerator setRemoteDescription(string answer)
{
RTCSessionDescription desc = new RTCSessionDescription();
desc.type = RTCSdpType.Answer;
desc.sdp = answer;
var op = pc.SetRemoteDescription(ref desc);
yield return op;
if (op.IsError) {
Debug.LogError("SetRemoteDescription() failed");
yield break;
}
yield break;
}
void OnDestroy()
{
pc?.Close();
pc?.Dispose();
receiveStream?.Dispose();
}
}
```
Edit the `url` variable according to your needs.
In the _Hierarchy_ window, find or create a scene. Inside the scene, add a _Canvas_. Inside the Canvas, add a _Raw Image_ and an _Audio Source_. Then add the `WebRTCReader.cs` script as component of the canvas, by dragging it inside the _Inspector_ window. then Press the _Play_ button at the top of the page.
================================================
FILE: docs/3-read/14-web-browsers.md
================================================
# Web browsers
Web browsers can read a stream from the server in several ways.
## Web browsers and WebRTC
You can read a stream by using the [WebRTC protocol](03-webrtc.md) by visiting the web page:
```
http://localhost:8889/mystream
```
See [Embed streams in a website](../4-other/14-embed-streams-in-a-website.md) for instructions on how to embed the stream into an external website.
## Web browsers and HLS
Web browsers can also read a stream with the [HLS protocol](06-hls.md). Latency is higher but there are fewer problems related to connectivity between server and clients, furthermore the server load can be balanced by using a common HTTP CDN (like Cloudflare or CloudFront), and this allows to handle an unlimited amount of readers. Visit the web page:
```
http://localhost:8888/mystream
```
See [Embed streams in a website](../4-other/14-embed-streams-in-a-website.md) for instructions on how to embed the stream into an external website.
================================================
FILE: docs/3-read/index.md
================================================
# Read
================================================
FILE: docs/4-other/02-configuration.md
================================================
# Configuration
All the configuration parameters are listed and commented in the [configuration file](../5-references/1-configuration-file.md) (`mediamtx.yml`).
## Change the configuration
There are several ways to change the configuration:
1. By editing the configuration file, that is
- included into the release bundle
- available in the root folder of the Docker image (`/mediamtx.yml`); it can be overridden in this way:
```sh
docker run --rm -it --network=host -v "$PWD/mediamtx.yml:/mediamtx.yml:ro" bluenviron/mediamtx:1
```
The configuration can be changed dynamically when the server is running (hot reloading) by writing to the configuration file. Changes are detected and applied without disconnecting existing clients, whenever it's possible.
2. By overriding configuration parameters with environment variables, in the format `MTX_PARAMNAME`, where `PARAMNAME` is the uppercase name of a parameter. For instance, the `rtspAddress` parameter can be overridden in the following way:
```
MTX_RTSPADDRESS="127.0.0.1:8554" ./mediamtx
```
Parameters that have array as value can be overridden by setting a comma-separated list. For example:
```
MTX_RTSPTRANSPORTS="tcp,udp"
```
Parameters in maps can be overridden by using underscores, in the following way:
```
MTX_PATHS_TEST_SOURCE=rtsp://myurl ./mediamtx
```
Parameters in lists can be overridden in the same way as parameters in maps, using their position like an additional key. This is particularly useful if you want to use internal users but define credentials through environment variables:
```
MTX_AUTHINTERNALUSERS_0_USER=username
MTX_AUTHINTERNALUSERS_0_PASS=password
```
This method is particularly useful when using Docker; any configuration parameter can be changed by passing environment variables with the `-e` flag:
```
docker run --rm -it --network=host -e MTX_PATHS_TEST_SOURCE=rtsp://myurl bluenviron/mediamtx:1
```
3. By using the [Control API](18-control-api.md).
## Encrypt the configuration
The configuration file can be entirely encrypted for security purposes by using the `crypto_secretbox` function of the NaCL function. An online tool for performing this operation is [available here](https://play.golang.org/p/rX29jwObNe4).
After performing the encryption, put the base64-encoded result into the configuration file, and launch the server with the `MTX_CONFKEY` variable:
```
MTX_CONFKEY=mykey ./mediamtx
```
================================================
FILE: docs/4-other/03-authentication.md
================================================
# Authentication
_MediaMTX_ can be configured to ask clients for credentials, either in the form of username/password or a string-based token. These credentials are then validated through a chosen method.
## Credential validation
Credentials can be validated through one of these methods:
- Internal database: credentials are stored in the configuration file
- External HTTP server: an external HTTP URL is contacted to perform authentication
- External JWT provider: an external identity server provides signed tokens that are then verified by the server
### Internal database
The internal authentication method is the default one. Users are stored inside the configuration file, in this format:
```yml
authInternalUsers:
# Username. 'any' means any user, including anonymous ones.
- user: any
# Password. Not used in case of 'any' user.
pass:
# IPs or networks allowed to use this user. An empty list means any IP.
ips: []
# Permissions.
permissions:
# Available actions are: publish, read, playback, api, metrics, pprof.
- action: publish
# Paths can be set to further restrict access to a specific path.
# An empty path means any path.
# Regular expressions can be used by using a tilde as prefix.
path:
- action: read
path:
- action: playback
path:
```
Only clients that provide a valid username and password will be able to perform a certain action.
If storing plain credentials in the configuration file is a security problem, username and passwords can be stored as hashed strings. The Argon2 and SHA256 hashing algorithms are supported. To use Argon2, the string must be hashed using Argon2id (recommended) or Argon2i:
```
echo -n "mypass" | argon2 saltItWithSalt -id -l 32 -e
```
Then stored with the `argon2:` prefix:
```yml
authInternalUsers:
- user: argon2:$argon2id$v=19$m=4096,t=3,p=1$MTIzNDU2Nzg$OGGO0eCMN0ievb4YGSzvS/H+Vajx1pcbUmtLp2tRqRU
pass: argon2:$argon2i$v=19$m=4096,t=3,p=1$MTIzNDU2Nzg$oct3kOiFywTdDdt19kT07hdvmsPTvt9zxAUho2DLqZw
permissions:
- action: publish
```
To use SHA256, the string must be hashed with SHA256 and encoded with base64:
```
echo -n "mypass" | openssl dgst -binary -sha256 | openssl base64
```
Then stored with the `sha256:` prefix:
```yml
authInternalUsers:
- user: sha256:j1tsRqDEw9xvq/D7/9tMx6Jh/jMhk3UfjwIB2f1zgMo=
pass: sha256:BdSWkrdV+ZxFBLUQQY7+7uv9RmiSVA8nrPmjGjJtZQQ=
permissions:
- action: publish
```
**WARNING**: enable encryption or use a VPN to ensure that no one is intercepting the credentials in transit.
### External HTTP server
Authentication can be delegated to an external HTTP server:
```yml
authMethod: http
authHTTPAddress: http://myauthserver/auth
```
Each time a user needs to be authenticated, the specified URL will be requested with the POST method and this payload:
```json
{
"user": "user",
"password": "password",
"token": "token",
"ip": "ip",
"action": "publish|read|playback|api|metrics|pprof",
"path": "path",
"protocol": "rtsp|rtmp|hls|webrtc|srt",
"id": "id",
"query": "query"
}
```
If the URL returns a status code that begins with `20` (i.e. `200`), authentication is successful, otherwise it fails. Be aware that it's perfectly normal for the authentication server to receive requests with empty users and passwords, i.e.:
```json
{
"user": "",
"password": ""
}
```
This happens because RTSP clients don't provide credentials until they are asked to. In order to receive the credentials, the authentication server must reply with status code `401`, then the client will send credentials.
Some actions can be excluded from the process:
```yml
# Actions to exclude from HTTP-based authentication.
# Format is the same as the one of user permissions.
authHTTPExclude:
- action: api
- action: metrics
- action: pprof
```
If the authentication server uses HTTPS and has a self-signed or invalid TLS certificate, you can provide the fingerprint of the certificate to validate it anyway:
```yml
authMethod: http
authHTTPAddress: https://myauthserver/auth
authHTTPFingerprint: 33949e05fffb5ff3e8aa16f8213a6251b4d9363804ba53233c4da9a46d6f2739
```
The fingerprint can be obtained with:
```sh
openssl s_client -connect myauthserver:443 /dev/null | sed -n '/BEGIN/,/END/p' > server.crt
openssl x509 -in server.crt -noout -fingerprint -sha256 | cut -d "=" -f2 | tr -d ':'
```
### External JWT provider
Authentication can be delegated to an external identity server, that is capable of generating JWTs and provides a JWKS endpoint. With respect to the HTTP-based method, this has the advantage that the external server is contacted once, and not for every request, greatly improving performance. In order to use the JWT-based authentication method, set `authMethod` and `authJWTJWKS`:
```yml
authMethod: jwt
authJWTJWKS: http://my_identity_server/jwks_endpoint
authJWTClaimKey: mediamtx_permissions
```
Users are expected to pass the encoded JWT as token.
The JWT is expected to contain a claim, with a list of permissions in the same format as the one of user permissions:
```json
{
"mediamtx_permissions": [
{
"action": "publish",
"path": ""
}
]
}
```
If the JWKS server uses TLS and has a self-signed or invalid TLS certificate, you can provide the fingerprint of the certificate to validate it anyway:
```yml
authMethod: jwt
authJWTJWKS: https://my_identity_server/jwks_endpoint
authJWTJWKSFingerprint: 33949e05fffb5ff3e8aa16f8213a6251b4d9363804ba53233c4da9a46d6f2739
authJWTClaimKey: mediamtx_permissions
```
The fingerprint can be obtained with:
```sh
openssl s_client -connect my_identity_server:443 /dev/null | sed -n '/BEGIN/,/END/p' > server.crt
openssl x509 -in server.crt -noout -fingerprint -sha256 | cut -d "=" -f2 | tr -d ':'
```
Optionally, the JWT `iss` (issuer) and `aud` (audience) claims can be validated by setting `authJWTIssuer` and `authJWTAudience`. When set, tokens that don't contain the expected values will be rejected:
```yml
authMethod: jwt
authJWTJWKS: http://my_identity_server/jwks_endpoint
authJWTClaimKey: mediamtx_permissions
authJWTIssuer: http://my_identity_server
authJWTAudience: mediamtx
```
Leave these fields empty to skip validation of the respective claims.
#### Keycloak setup
Here's a tutorial on how to setup the [Keycloak identity server](https://www.keycloak.org/) in order to provide JWTs.
1. Start Keycloak:
```sh
docker run --name=keycloak -p 8080:8080 \
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:23.0.7 start-dev
```
2. Open the Keycloak web UI on http://localhost:8080, click on _Administration Console_ and log in.
3. Click on _master_ in the top left corner, _Create realm_, set realm name to `mediamtx`, _Create_.
4. Open page _Client scopes_, _Create client scope_, set name to `mediamtx`, _Save_.
5. Open tab _Mappers_, _Configure a new Mapper_, _User Attribute_:
- Name: `mediamtx_permissions`
- User Attribute: `mediamtx_permissions`
- Token Claim Name: `mediamtx_permissions`
- Claim JSON Type: `JSON`
- Multivalued: `On`
Save.
6. Open page _Clients_, _Create client_, set Client ID to `mediamtx`, _Next_, _Client authentication_ `On`, _Next_, _Save_.
7. Open tab _Credentials_, copy client secret somewhere.
8. Open tab _Client scopes_, set _Assigned type_ of all existing client scopes to _Optional_. This decreases the length of the JWT, since many clients impose limits on it.
9. In tab _Client scopes_, _Add client scope_, Select `mediamtx`, _Add_, _Default_.
10. Open page _Users_, _Add user_, Username `testuser`, _Create_, Tab _Credentials_, _Set password_, pick a password, _Save_.
11. Open tab _Attributes_, _Add an attribute_:
- Key: `mediamtx_permissions`
- Value: `{"action":"publish", "path": ""}`
You can add as many attributes with key `mediamtx_permissions` as you want, each with a single permission in it.
12. In MediaMTX, use the following JWKS URL:
```yml
authJWTJWKS: http://localhost:8080/realms/mediamtx/protocol/openid-connect/certs
```
13. Perform authentication on Keycloak:
```
curl \
-d "client_id=mediamtx" \
-d "client_secret=$CLIENT_SECRET" \
-d "username=$USER" \
-d "password=$PASS" \
-d "grant_type=password" \
http://localhost:8080/realms/mediamtx/protocol/openid-connect/token
```
The JWT is inside the `access_token` key of the response:
```json
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIyNzVjX3ptOVlOdHQ0TkhwWVk4Und6ZndUclVGSzRBRmQwY3lsM2wtY3pzIn0.eyJleHAiOjE3MDk1NTUwOTIsImlhdCI6MTcwOTU1NDc5MiwianRpIjoiMzE3ZTQ1NGUtNzczMi00OTM1LWExNzAtOTNhYzQ2ODhhYWIxIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tZWRpYW10eCIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI2NTBhZDA5Zi03MDgxLTQyNGItODI4Ni0xM2I3YTA3ZDI0MWEiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJtZWRpYW10eCIsInNlc3Npb25fc3RhdGUiOiJjYzJkNDhjYy1kMmU5LTQ0YjAtODkzZS0wYTdhNjJiZDI1YmQiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIi8qIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiZGVmYXVsdC1yb2xlcy1tZWRpYW10eCJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoibWVkaWFtdHggcHJvZmlsZSBlbWFpbCIsInNpZCI6ImNjMmQ0OGNjLWQyZTktNDRiMC04OTNlLTBhN2E2MmJkMjViZCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibWVkaWFtdHhfcGVybWlzc2lvbnMiOlt7ImFjdGlvbiI6InB1Ymxpc2giLCJwYXRocyI6ImFsbCJ9XSwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdHVzZXIifQ.Gevz7rf1qHqFg7cqtSfSP31v_NS0VH7MYfwAdra1t6Yt5rTr9vJzqUeGfjYLQWR3fr4XC58DrPOhNnILCpo7jWRdimCnbPmuuCJ0AYM-Aoi3PAsWZNxgmtopq24_JokbFArY9Y1wSGFvF8puU64lt1jyOOyxf2M4cBHCs_EarCKOwuQmEZxSf8Z-QV9nlfkoTUszDCQTiKyeIkLRHL2Iy7Fw7_T3UI7sxJjVIt0c6HCNJhBBazGsYzmcSQ_GrmhbUteMTg00o6FicqkMBe99uZFnx9wIBm_QbO9hbAkkzF923I-DTAQrFLxT08ESMepDwmzFrmnwWYBLE3u8zuUlCA",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI3OTI3Zjg4Zi05YWM4LTRlNmEtYWE1OC1kZmY0MDQzZDRhNGUifQ.eyJleHAiOjE3MDk1NTY1OTIsImlhdCI6MTcwOTU1NDc5MiwianRpIjoiMGVhZWFhMWItYzNhMC00M2YxLWJkZjAtZjI2NTRiODlkOTE3IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tZWRpYW10eCIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9yZWFsbXMvbWVkaWFtdHgiLCJzdWIiOiI2NTBhZDA5Zi03MDgxLTQyNGItODI4Ni0xM2I3YTA3ZDI0MWEiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoibWVkaWFtdHgiLCJzZXNzaW9uX3N0YXRlIjoiY2MyZDQ4Y2MtZDJlOS00NGIwLTg5M2UtMGE3YTYyYmQyNWJkIiwic2NvcGUiOiJtZWRpYW10eCBwcm9maWxlIGVtYWlsIiwic2lkIjoiY2MyZDQ4Y2MtZDJlOS00NGIwLTg5M2UtMGE3YTYyYmQyNWJkIn0.yuXV8_JU0TQLuosNdp5xlYMjn7eO5Xq-PusdHzE7bsQ",
"token_type": "Bearer",
"not-before-policy": 0,
"session_state": "cc2d48cc-d2e9-44b0-893e-0a7a62bd25bd",
"scope": "mediamtx profile email"
}
```
## Providing username and password
### RTSP
Prepend username and password and a `@` to the host:
```
rtsp rtsp://myuser:mypass@localhost:8554/mystream
```
### RTMP
Use the `user` and `pass` query parameters:
```
rtmp://localhost/mystream?user=myuser&pass=mypass
```
### SRT
Append username and password to `streamid`:
```
srt://localhost:8890?streamid=publish:mystream:user:pass&pkt_size=1316
```
### HLS and WebRTC
Username and password can be passed through the `Authorization: Basic` HTTP header:
```
Authorization: Basic base64(user:pass)
```
When using a web browser, a dialog is first shown to users, asking for credentials, and then the header is automatically inserted into every request. If you need to automatically fill credentials from a parent web page, read [Embed streams in a website](14-embed-streams-in-a-website.md).
If the `Authorization: Basic` header cannot be used (for instance, in software like OBS Studio, which only allows to provide a "Bearer Token"), credentials can be passed through the `Authorization: Bearer` header (i.e. the "Bearer Token" in OBS), where the value is the concatenation of username and password, separated by a colon:
```
Authorization: Bearer username:password
```
## Providing tokens / JWTs
### RTSP
Pass the token as a query parameter:
```
rtsp://localhost:8554/mystream?jwt=jwt
```
WARNING: FFmpeg implementation of RTSP does not support URLs that are longer than 4096 characters (this is the [MAX_URL_SIZE constant](https://github.com/FFmpeg/FFmpeg/blob/f951aa9ef382d6bb517e05d04d52710f751de427/libavformat/internal.h#L30)), therefore you have to configure your identity server in order to produce JWTs that are shorter than this threshold.
### RTMP
Pass the token as a query parameter:
```
rtmp://localhost/mystream?jwt=jwt
```
WARNING: FFmpeg implementation of RTMP does not support URLs that are longer than 1024 characters (this is the [TCURL_MAX_LENGTH constant](https://github.com/FFmpeg/FFmpeg/blob/f951aa9ef382d6bb517e05d04d52710f751de427/libavformat/rtmpproto.c#L55)), therefore you have to configure your identity server in order to produce JWTs that are shorter than this threshold.
### SRT
Pass the token as password, with an arbitrary user:
```
srt://localhost:8890?streamid=publish:mystream:user:jwt&pkt_size=1316
```
WARNING: SRT does not support Stream IDs that are longer than 512 characters, therefore you have to configure your identity server in order to produce JWTs that are shorter than this threshold.
### HLS and WebRTC
The token can be passed through the `Authorization: Bearer` header:
```
Authorization: Bearer MY_JWT
```
In OBS Studio, this is the "Bearer Token" field.
If the `Authorization: Bearer` token cannot be directly provided (for instance, with web browsers that directly access _MediaMTX_ and show a credential dialog), you can pass the token as password, using an arbitrary user.
In web browsers, if you need to automatically fill credentials from a parent web page, read [Embed streams in a website](14-embed-streams-in-a-website.md).
================================================
FILE: docs/4-other/04-remuxing-reencoding-compression.md
================================================
# Re-encoding
To change the format, codec or compression of a stream, use _FFmpeg_ or _GStreamer_ together with _MediaMTX_. For instance, to re-encode an existing stream, that is available in the `/original` path, and publish the resulting stream in the `/compressed` path, edit `mediamtx.yml` and replace everything inside section `paths` with the following content:
```yml
paths:
compressed:
original:
runOnReady: >
ffmpeg -i rtsp://localhost:$RTSP_PORT/$MTX_PATH
-c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k
-max_muxing_queue_size 1024 -f rtsp rtsp://localhost:$RTSP_PORT/compressed
runOnReadyRestart: yes
```
================================================
FILE: docs/4-other/05-always-available.md
================================================
# Always-available
When the publisher or source of a stream is offline, the server can be configured to fill gaps in the stream with an offline segment that is played on repeat until a publisher comes back online. This allows readers to stay connected regardless of the state of the stream. The offline segment and online stream are concatenated without re-encoding any frame, using the original codec.
This feature can be enabled by toggling the `alwaysAvailable` flag and filling `alwaysAvailableTracks`:
```yml
paths:
mypath:
alwaysAvailable: true
alwaysAvailableTracks:
# Available values are: AV1, VP9, H265, H264, Opus, MPEG4Audio, G711, LPCM
- codec: H264
# in case of MPEG4Audio, G711, LPCM, sampleRate and ChannelCount must be provided too.
# sampleRate: 48000
# channelCount: 2
# in case of G711, muLaw must be provided too.
# muLaw: false
```
By default, the server uses a default offline segment with the text "STREAM IS OFFLINE". The segment can be replaced with an external MP4 file:
```yml
paths:
mypath:
alwaysAvailable: true
alwaysAvailableFile: "./h264.mp4"
```
================================================
FILE: docs/4-other/06-record.md
================================================
# Record
Live streams be recorded to disk and played back with the following file containers and codecs:
| container | codecs |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| fMP4 | **Video**: AV1, VP9, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
| MPEG-TS | **Video**: H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video **Audio**: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3 |
## Usage
To record available streams to disk, set the `record` parameter in the configuration file:
```yml
pathDefaults:
# Record streams to disk.
record: yes
```
It's also possible to specify additional parameters:
```yml
pathDefaults:
# Record streams to disk.
record: yes
# Path of recording segments.
# Extension is added automatically.
# Available variables are %path (path name), %Y %m %d (year, month, day),
# %H %M %S (hours, minutes, seconds), %f (microseconds), %z (time zone), %s (unix epoch).
recordPath: ./recordings/%path/%Y-%m-%d_%H-%M-%S-%f
# Format of recorded segments.
# Available formats are "fmp4" (fragmented MP4) and "mpegts" (MPEG-TS).
recordFormat: fmp4
# fMP4 segments are concatenation of small MP4 files (parts), each with this duration.
# MPEG-TS segments are concatenation of 188-bytes packets, flushed to disk with this period.
# When a system failure occurs, the last part gets lost.
# Therefore, the part duration is equal to the RPO (recovery point objective).
recordPartDuration: 1s
# This prevents RAM exhaustion.
recordMaxPartSize: 50M
# Minimum duration of each segment.
recordSegmentDuration: 1h
# Delete segments after this timespan.
# Set to 0s to disable automatic deletion.
recordDeleteAfter: 1d
```
All available recording parameters are listed in the [configuration file](../5-references/1-configuration-file.md).
## Remote upload
To upload recordings to a remote location, you can use _MediaMTX_ together with [rclone](https://github.com/rclone/rclone), a command line tool that provides file synchronization capabilities with a huge variety of services (including S3, FTP, SMB, Google Drive):
1. Download and install [rclone](https://github.com/rclone/rclone).
2. Configure _rclone_:
```sh
rclone config
```
3. Place `rclone` into the `runOnInit` and `runOnRecordSegmentComplete` hooks:
```yml
pathDefaults:
# this is needed to sync segments after a crash.
# replace myconfig with the name of the rclone config.
runOnInit: rclone sync -v ./recordings myconfig:/my-path/recordings
# this is called when a segment has been finalized.
# replace myconfig with the name of the rclone config.
runOnRecordSegmentComplete: rclone sync -v --min-age=1ms ./recordings myconfig:/my-path/recordings
```
If you want to delete local segments after they are uploaded, replace `rclone sync` with `rclone move`.
================================================
FILE: docs/4-other/07-playback.md
================================================
# Playback
Existing recordings can be played back to users through a dedicated HTTP server, that can be enabled inside the configuration:
```yml
playback: yes
playbackAddress: :9996
```
The server provides an endpoint to list recorded timespans:
```
http://localhost:9996/list?path=[mypath]&start=[start]&end=[end]
```
Where:
- [mypath] is the name of a path
- [start] (optional) is the start date in [RFC3339 format](https://www.utctime.net/)
- [end] (optional) is the end date in [RFC3339 format](https://www.utctime.net/)
The server will return a list of timespans in JSON format:
```json
[
{
"start": "2006-01-02T15:04:05Z07:00",
"duration": 60.0,
"url": "http://localhost:9996/get?path=[mypath]&start=2006-01-02T15%3A04%3A05Z07%3A00&duration=60.0"
},
{
"start": "2006-01-02T15:07:05Z07:00",
"duration": 32.33,
"url": "http://localhost:9996/get?path=[mypath]&start=2006-01-02T15%3A07%3A05Z07%3A00&duration=32.33"
}
]
```
The server provides an endpoint to download recordings:
```
http://localhost:9996/get?path=[mypath]&start=[start]&duration=[duration]&format=[format]
```
Where:
- [mypath] is the path name
- [start] is the start date in [RFC3339 format](https://www.utctime.net/)
- [duration] is the maximum duration of the recording in seconds
- [format] (optional) is the output format of the stream. Available values are "fmp4" (default) and "mp4"
All parameters must be [url-encoded](https://www.urlencoder.org/). For instance:
```
http://localhost:9996/get?path=mypath&start=2024-01-14T16%3A33%3A17%2B00%3A00&duration=200.5
```
The resulting stream uses the fMP4 format, that is natively compatible with any browser, therefore its URL can be directly inserted into a \