@@ -21,10 +21,10 @@ We provide instructions for publishing with the following devices:
|
||||
|
||||
We provide instructions for publishing with the following software:
|
||||
|
||||
- [FFmpeg](../3-publish/14-ffmpeg.md)
|
||||
- [GStreamer](../3-publish/15-gstreamer.md)
|
||||
- [OBS Studio](../3-publish/16-obs-studio.md)
|
||||
- [Python and OpenCV](../3-publish/17-python-opencv.md)
|
||||
- [Golang](../3-publish/18-golang.md)
|
||||
- [Unity](../3-publish/19-unity.md)
|
||||
- [Web browsers](../3-publish/20-web-browsers.md)
|
||||
- [Web browsers](../3-publish/14-web-browsers.md)
|
||||
- [FFmpeg](../3-publish/15-ffmpeg.md)
|
||||
- [GStreamer](../3-publish/16-gstreamer.md)
|
||||
- [OBS Studio](../3-publish/17-obs-studio.md)
|
||||
- [Python and OpenCV](../3-publish/18-python-opencv.md)
|
||||
- [Golang](../3-publish/19-golang.md)
|
||||
- [Unity](../3-publish/20-unity.md)
|
||||
|
||||
@@ -10,11 +10,11 @@ Live streams can be read from the server with the following protocols:
|
||||
|
||||
We provide instructions for reading with the following software:
|
||||
|
||||
- [FFmpeg](../4-read/06-ffmpeg.md)
|
||||
- [GStreamer](../4-read/07-gstreamer.md)
|
||||
- [VLC](../4-read/08-vlc.md)
|
||||
- [OBS Studio](../4-read/09-obs-studio.md)
|
||||
- [Python and OpenCV](../4-read/10-python-opencv.md)
|
||||
- [Golang](../4-read/11-golang.md)
|
||||
- [Unity](../4-read/12-unity.md)
|
||||
- [Web browsers](../4-read/13-web-browsers.md)
|
||||
- [Web browsers](../4-read/06-web-browsers.md)
|
||||
- [FFmpeg](../4-read/07-ffmpeg.md)
|
||||
- [GStreamer](../4-read/08-gstreamer.md)
|
||||
- [VLC](../4-read/09-vlc.md)
|
||||
- [OBS Studio](../4-read/10-obs-studio.md)
|
||||
- [Python and OpenCV](../4-read/11-python-opencv.md)
|
||||
- [Golang](../4-read/12-golang.md)
|
||||
- [Unity](../4-read/13-unity.md)
|
||||
|
||||
@@ -298,7 +298,7 @@ Username and password can be passed through the `Authorization: Basic` HTTP head
|
||||
Authorization: Basic base64(myuser:mypass)
|
||||
```
|
||||
|
||||
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 in a website](../4-read/13-web-browsers.md#embed-in-a-website).
|
||||
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 in a website](../4-read/06-web-browsers.md#embed-in-a-website).
|
||||
|
||||
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:
|
||||
|
||||
@@ -350,4 +350,4 @@ 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 in a website](../4-read/13-web-browsers.md#embed-in-a-website).
|
||||
In web browsers, if you need to automatically fill credentials from a parent web page, read [Embed in a website](../4-read/06-web-browsers.md#embed-in-a-website).
|
||||
|
||||
@@ -18,4 +18,4 @@ If you need to use the standard stream ID syntax instead of the custom one in us
|
||||
|
||||
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](14-ffmpeg.md), [GStreamer](15-gstreamer.md), [OBS Studio](16-obs-studio.md).
|
||||
Some clients that can publish with SRT are [FFmpeg](15-ffmpeg.md), [GStreamer](16-gstreamer.md), [OBS Studio](17-obs-studio.md).
|
||||
|
||||
@@ -23,4 +23,4 @@ Be aware that not all browsers can read any codec, check [Codec support in brows
|
||||
|
||||
Depending on the network it might be difficult to establish a connection between server and clients, read [Solving WebRTC connectivity issues](../2-features/26-webrtc-specific-features.md#solving-webrtc-connectivity-issues).
|
||||
|
||||
Some clients that can publish with WebRTC and WHIP are [FFmpeg](14-ffmpeg.md), [GStreamer](15-gstreamer.md), [OBS Studio](16-obs-studio.md), [Unity](19-unity.md) and [Web browsers](20-web-browsers.md).
|
||||
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](14-web-browsers.md).
|
||||
|
||||
@@ -14,7 +14,7 @@ rtsp://localhost:8554/mystream
|
||||
|
||||
The resulting stream will be available on path `/mystream`.
|
||||
|
||||
Some clients that can publish with RTSP are [FFmpeg](14-ffmpeg.md), [GStreamer](15-gstreamer.md), [OBS Studio](16-obs-studio.md), [Python and OpenCV](17-python-opencv.md).
|
||||
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](../2-features/27-rtsp-specific-features.md).
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# RTMP clients
|
||||
|
||||
| | supported codecs |
|
||||
| --------- | ----------------------------------------------------------------------------- |
|
||||
| **video** | AV1, VP9, H265, H264 |
|
||||
| **audio** | Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
|
||||
| | supported codecs |
|
||||
| --------- | ----------------------------------------------------------------------------------- |
|
||||
| **video** | AV1, VP9, H265, H264 |
|
||||
| **audio** | Opus, FLAC, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
|
||||
|
||||
RTMP is a protocol that allows to read and publish streams. It has been expanded to support modern codecs (Enhanced RTMP) and it supports encryption, read [RTMP-specific features](../2-features/28-rtmp-specific-features.md). Streams can be published to the server by using the URL:
|
||||
|
||||
@@ -13,4 +13,4 @@ rtmp://localhost/mystream
|
||||
|
||||
The resulting stream will be available on path `/mystream`.
|
||||
|
||||
Some clients that can publish with RTMP are [FFmpeg](14-ffmpeg.md), [GStreamer](15-gstreamer.md), [OBS Studio](16-obs-studio.md).
|
||||
Some clients that can publish with RTMP are [FFmpeg](15-ffmpeg.md), [GStreamer](16-gstreamer.md) and [OBS Studio](17-obs-studio.md).
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# RTMP cameras and servers
|
||||
|
||||
| | supported codecs |
|
||||
| --------- | ----------------------------------------------------------------------------- |
|
||||
| **video** | AV1, VP9, H265, H264 |
|
||||
| **audio** | Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
|
||||
| | supported codecs |
|
||||
| --------- | ----------------------------------------------------------------------------------- |
|
||||
| **video** | AV1, VP9, H265, H264 |
|
||||
| **audio** | Opus, FLAC, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
|
||||
|
||||
You can use _MediaMTX_ to connect to one or several existing RTMP servers and read their media streams:
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ paths:
|
||||
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](14-ffmpeg.md) and [GStreamer](15-gstreamer.md).
|
||||
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:
|
||||
|
||||
|
||||
@@ -27,4 +27,4 @@ paths:
|
||||
|
||||
`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](14-ffmpeg.md) and [GStreamer](15-gstreamer.md).
|
||||
Some clients that can publish with UDP and MPEG-TS are [FFmpeg](15-ffmpeg.md) and [GStreamer](16-gstreamer.md).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# FFmpeg
|
||||
|
||||
FFmpeg can publish a stream to the server in several ways. The recommended one consists in publishing with RTSP.
|
||||
FFmpeg can publish a stream to the server by using the [RTSP](05-rtsp-clients.md), [RTMP](07-rtmp-clients.md), [MPEG-TS](10-mpeg-ts.md), [RTP](11-rtp.md), [SRT](01-srt-clients.md) and [WebRTC](03-webrtc-clients.md) protocols. The recommended one is RTSP.
|
||||
|
||||
## FFmpeg and RTSP
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GStreamer
|
||||
|
||||
GStreamer can publish a stream to the server in several ways. The recommended one consists in publishing with RTSP.
|
||||
GStreamer can publish a stream to the server by using the [RTSP](05-rtsp-clients.md), [RTMP](07-rtmp-clients.md), [SRT](01-srt-clients.md), [MPEG-TS](10-mpeg-ts.md) and [WebRTC](03-webrtc-clients.md) protocols. The recommended one is RTSP.
|
||||
|
||||
## GStreamer and RTSP
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# OBS Studio
|
||||
|
||||
OBS Studio can publish streams to the server in several ways. The recommended one consists in publishing with RTMP.
|
||||
OBS Studio can publish streams to the server by using the [RTMP](07-rtmp-clients.md) and [WebRTC](03-webrtc-clients.md) protocols. The recommended one is RTMP.
|
||||
|
||||
## OBS Studio and RTMP
|
||||
|
||||
@@ -16,4 +16,4 @@ 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](../2-features/25-srt-specific-features.md#standard-stream-id-syntax).
|
||||
|
||||
Some clients that can read with SRT are [FFmpeg](06-ffmpeg.md), [GStreamer](07-gstreamer.md) and [VLC](08-vlc.md).
|
||||
Some clients that can read with SRT are [FFmpeg](07-ffmpeg.md), [GStreamer](08-gstreamer.md) and [VLC](09-vlc.md).
|
||||
|
||||
@@ -22,4 +22,4 @@ Be aware that not all browsers can read any codec, check [Codec support in brows
|
||||
|
||||
Depending on the network it may be difficult to establish a connection between server and clients, read [Solving WebRTC connectivity issues](../2-features/26-webrtc-specific-features.md#solving-webrtc-connectivity-issues).
|
||||
|
||||
Some clients that can read with WebRTC and WHEP are [GStreamer](07-gstreamer.md), [Unity](12-unity.md) and [web browsers](13-web-browsers.md).
|
||||
Some clients that can read with WebRTC and WHEP are [GStreamer](08-gstreamer.md), [Unity](13-unity.md) and [web browsers](06-web-browsers.md).
|
||||
|
||||
@@ -12,4 +12,4 @@ RTSP is a protocol that allows to publish and read streams. It supports several
|
||||
rtsp://localhost:8554/mystream
|
||||
```
|
||||
|
||||
Some clients that can read with RTSP are [FFmpeg](06-ffmpeg.md), [GStreamer](07-gstreamer.md) and [VLC](08-vlc.md).
|
||||
Some clients that can read with RTSP are [FFmpeg](07-ffmpeg.md), [GStreamer](08-gstreamer.md) and [VLC](09-vlc.md).
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# RTMP clients
|
||||
|
||||
| | supported codecs |
|
||||
| --------- | ----------------------------------------------------------------------------- |
|
||||
| **video** | AV1, VP9, H265, H264 |
|
||||
| **audio** | Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
|
||||
| | supported codecs |
|
||||
| --------- | ----------------------------------------------------------------------------------- |
|
||||
| **video** | AV1, VP9, H265, H264 |
|
||||
| **audio** | Opus, FLAC, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM |
|
||||
|
||||
RTMP is a protocol that allows to read and publish streams. It has been expanded to support modern codecs (Enhanced RTMP) and it supports encryption, read [RTMP-specific features](../2-features/28-rtmp-specific-features.md). Streams can be read from the server by using the URL:
|
||||
|
||||
@@ -11,4 +11,4 @@ RTMP is a protocol that allows to read and publish streams. It has been expanded
|
||||
rtmp://localhost/mystream
|
||||
```
|
||||
|
||||
Some clients that can read with RTMP are [FFmpeg](06-ffmpeg.md), [GStreamer](07-gstreamer.md) and [VLC](08-vlc.md).
|
||||
Some clients that can read with RTMP are [FFmpeg](07-ffmpeg.md), [GStreamer](08-gstreamer.md) and [VLC](09-vlc.md).
|
||||
|
||||
@@ -18,7 +18,7 @@ and can also be accessed without using the browsers, by software that supports t
|
||||
http://localhost:8888/mystream/index.m3u8
|
||||
```
|
||||
|
||||
Some clients that can read with HLS are [FFmpeg](06-ffmpeg.md), [GStreamer](07-gstreamer.md), [VLC](08-vlc.md) and [web browsers](13-web-browsers.md).
|
||||
Some clients that can read with HLS are [FFmpeg](07-ffmpeg.md), [GStreamer](08-gstreamer.md), [VLC](09-vlc.md) and [web browsers](06-web-browsers.md).
|
||||
|
||||
_MediaMTX_ supports generating HLS in several variants (including Low-Latency mode), and provides various parameters to tune HLS generation. These are listed in the [configuration file](../5-references/1-configuration-file.md):
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Web browsers
|
||||
|
||||
Web browsers can read a stream from the server with the WebRTC or the HLS protocol, by directly accessing web pages provided by the server. It is also possible to embed streams into an external website.
|
||||
Web browsers can read a stream from the server with the [WebRTC](02-webrtc.md) and [HLS](05-hls.md) protocols, by accessing web pages hosted by the server. It is also possible to embed streams into an external website.
|
||||
|
||||
## Direct read
|
||||
|
||||
### WebRTC
|
||||
|
||||
Web browsers can read a stream with the [WebRTC protocol](02-webrtc.md) by visiting the web page:
|
||||
Visit the web page:
|
||||
|
||||
```
|
||||
http://localhost:8889/mystream
|
||||
@@ -16,7 +16,7 @@ Replace `mystream` with the path name.
|
||||
|
||||
### HLS
|
||||
|
||||
Web browsers can also read a stream with the [HLS protocol](05-hls.md). Latency is higher but there are fewer problems related to connectivity between server and clients. Visit the web page:
|
||||
The HLS protocol has a higher latency with respect to WebRTC, but there are fewer problems related to connectivity between server and clients. Visit the web page:
|
||||
|
||||
```
|
||||
http://localhost:8888/mystream
|
||||
@@ -1,6 +1,6 @@
|
||||
# FFmpeg
|
||||
|
||||
FFmpeg can read a stream from the server in several ways. The recommended one consists in reading with RTSP.
|
||||
FFmpeg can read a stream from the server the [RTSP](03-rtsp.md), [RTMP](04-rtmp.md), [HLS](05-hls.md) and [SRT](01-srt.md) protocols. The recommended one is RTSP.
|
||||
|
||||
## FFmpeg and RTSP
|
||||
|
||||
@@ -14,7 +14,7 @@ ffmpeg -i rtsp://localhost:8554/mystream -c copy output.mp4
|
||||
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:
|
||||
In order to read tracks that make use of modern codecs (AV1, VP9, H265, Opus, FLAC, AC-3) and in order to read multiple video or audio tracks, the `-rtmp_enhanced_codecs` flag must be present and filled with the following values:
|
||||
|
||||
```sh
|
||||
ffmpeg -rtmp_enhanced_codecs ac-3,av01,avc1,ec-3,fLaC,hvc1,.mp3,mp4a,Opus,vp09 \
|
||||
@@ -1,6 +1,6 @@
|
||||
# GStreamer
|
||||
|
||||
GStreamer can read a stream from the server in several ways. The recommended one consists in reading with RTSP.
|
||||
GStreamer can read a stream from the server by using the [RTSP](03-rtsp.md), [RTMP](04-rtmp.md), [HLS](05-hls.md), [SRT](01-srt.md) and [WebRTC](02-webrtc.md) protocols. The recommended one is RTSP.
|
||||
|
||||
## GStreamer and RTSP
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,45 @@
|
||||
# VLC
|
||||
|
||||
VLC can read a stream from the server by using the [RTSP](03-rtsp.md), [RTMP](04-rtmp.md), [HLS](05-hls.md) and [SRT](01-srt.md) protocols. The recommended one is RTSP.
|
||||
|
||||
In order to minimize latency, it is also suggested to change the `Network caching` parameter of VLC:
|
||||
|
||||
1. Open VLC, _Tools_, _Preferences_, _Show Settings_, _All_, page _Input / Codecs_.
|
||||
2. Find the _Network caching (ms)_ parameter, set it to `50`. Save
|
||||
|
||||
## VLC and RTSP
|
||||
|
||||
Open the following URL:
|
||||
|
||||
```
|
||||
rtsp://localhost:8554/mystream
|
||||
```
|
||||
|
||||
### RTSP and Ubuntu
|
||||
|
||||
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
|
||||
|
||||
At the moment VLC doesn't support reading encrypted RTSP streams (RTSPS). 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.
|
||||
|
||||
## VLC and RTMP
|
||||
|
||||
Open the following URL:
|
||||
|
||||
```
|
||||
rtmp://localhost/mystream
|
||||
```
|
||||
|
||||
## VLC and SRT
|
||||
|
||||
Open the following URL:
|
||||
|
||||
```
|
||||
srt://localhost:8890?streamid=read:mystream
|
||||
```
|
||||
@@ -11,9 +11,9 @@ require (
|
||||
github.com/alecthomas/kong v1.15.0
|
||||
github.com/asticode/go-astits v1.15.0
|
||||
github.com/bluenviron/gohlslib/v2 v2.3.2
|
||||
github.com/bluenviron/gortmplib v0.3.2
|
||||
github.com/bluenviron/gortmplib v0.3.3-0.20260520213319-89bf8b0c2c7f
|
||||
github.com/bluenviron/gortsplib/v5 v5.5.3
|
||||
github.com/bluenviron/mediacommon/v2 v2.8.3
|
||||
github.com/bluenviron/mediacommon/v2 v2.8.4-0.20260520210731-a2f6c851f7b5
|
||||
github.com/datarhei/gosrt v0.11.0
|
||||
github.com/fsnotify/fsnotify v1.10.1
|
||||
github.com/gin-contrib/pprof v1.5.4
|
||||
|
||||
@@ -35,12 +35,12 @@ github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c h1:8XZeJrs4+ZYh
|
||||
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c/go.mod h1:x1vxHcL/9AVzuk5HOloOEPrtJY0MaalYr78afXZ+pWI=
|
||||
github.com/bluenviron/gohlslib/v2 v2.3.2 h1:Q6ZAYRFZ++rSfK0sm8vOEYhtH7KKBpfzQdenWJOgNMY=
|
||||
github.com/bluenviron/gohlslib/v2 v2.3.2/go.mod h1:kA0hTg96hmTZjeZ/Vxwpu/Njy0emAoidEoDGQ/KlMH0=
|
||||
github.com/bluenviron/gortmplib v0.3.2 h1:jtIWdN3FrnVh7Av8aWBIp2l6t1DeEUI80qPpRmONUCU=
|
||||
github.com/bluenviron/gortmplib v0.3.2/go.mod h1:15031Vx53/kjKdbhmLdfggv3thOv6fyRVZafAZfZh6c=
|
||||
github.com/bluenviron/gortmplib v0.3.3-0.20260520213319-89bf8b0c2c7f h1:glyddGmkLFBtsGgNqP8ypnHp9Hpra0Q0EpmMlYbuarA=
|
||||
github.com/bluenviron/gortmplib v0.3.3-0.20260520213319-89bf8b0c2c7f/go.mod h1:6jOS24kmD3TVhmlfy1vpbFTO7L8NJBJYVGt0D2CGSZ8=
|
||||
github.com/bluenviron/gortsplib/v5 v5.5.3 h1:aKdP14cRP8CorUCw2K4Qn/Zrs4AXTbAKUENVqh3B3vM=
|
||||
github.com/bluenviron/gortsplib/v5 v5.5.3/go.mod h1:e4abL49yJF5TR+1m9+0K+UuCSkyJn345Dt2XIJfu4Nc=
|
||||
github.com/bluenviron/mediacommon/v2 v2.8.3 h1:T6xb7ZK3eBixi/HynzhtGRCEIrazwcmGIeu0WDTVISY=
|
||||
github.com/bluenviron/mediacommon/v2 v2.8.3/go.mod h1:CsYjGgzIz8RbloQf4BHR4uReogZsB4PEKWfePVIzJv8=
|
||||
github.com/bluenviron/mediacommon/v2 v2.8.4-0.20260520210731-a2f6c851f7b5 h1:eJynVwJEHnGuQxXvyuf/KU6B6ya4X7/03tcJKBmy7Pg=
|
||||
github.com/bluenviron/mediacommon/v2 v2.8.4-0.20260520210731-a2f6c851f7b5/go.mod h1:syqw4j2RmBCKZgUtGFtB/7gcnh1aaX8I3vd24+bgXWc=
|
||||
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
package formatlabel
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
)
|
||||
@@ -22,6 +24,7 @@ const (
|
||||
MJPEG Label = "M-JPEG"
|
||||
// audio
|
||||
Opus Label = "Opus"
|
||||
FLAC Label = "FLAC"
|
||||
Vorbis Label = "Vorbis"
|
||||
MPEG4Audio Label = "MPEG-4 Audio"
|
||||
MPEG4AudioLATM Label = "MPEG-4 Audio LATM"
|
||||
@@ -86,9 +89,13 @@ func FormatToLabel(forma format.Format) Label {
|
||||
return MPEGTS
|
||||
case *format.KLV:
|
||||
return KLV
|
||||
default:
|
||||
return Generic
|
||||
case *format.Generic:
|
||||
if strings.HasPrefix(strings.ToLower(forma.RTPMap()), "flac/") {
|
||||
return FLAC
|
||||
}
|
||||
}
|
||||
|
||||
return Generic
|
||||
}
|
||||
|
||||
func gatherFormats(medias []*description.Media) []format.Format {
|
||||
|
||||
@@ -19,6 +19,7 @@ func TestFormatToLabel(t *testing.T) {
|
||||
FormatToLabel(&format.MPEG1Video{}),
|
||||
FormatToLabel(&format.MJPEG{}),
|
||||
FormatToLabel(&format.Opus{}),
|
||||
FormatToLabel(&format.Generic{RTPMa: "FLAC/44100/2"}),
|
||||
FormatToLabel(&format.Vorbis{}),
|
||||
FormatToLabel(&format.MPEG4Audio{}),
|
||||
FormatToLabel(&format.MPEG4AudioLATM{}),
|
||||
@@ -44,6 +45,7 @@ func TestFormatToLabel(t *testing.T) {
|
||||
MPEG1Video,
|
||||
MJPEG,
|
||||
Opus,
|
||||
FLAC,
|
||||
Vorbis,
|
||||
MPEG4Audio,
|
||||
MPEG4AudioLATM,
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"errors"
|
||||
"net"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortmplib"
|
||||
@@ -13,6 +15,7 @@ import (
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/ac3"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/flac"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/h264"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/h265"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/mpeg1audio"
|
||||
@@ -26,7 +29,7 @@ import (
|
||||
|
||||
var errNoSupportedCodecsFrom = errors.New(
|
||||
"the stream doesn't contain any supported codec, which are currently " +
|
||||
"AV1, VP9, H265, H264, Opus, MPEG-4 Audio, MPEG-1/2 Audio, AC-3, G711, LPCM")
|
||||
"AV1, VP9, H265, H264, Opus, FLAC, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711, LPCM")
|
||||
|
||||
func multiplyAndDivide2(v, m, d time.Duration) time.Duration {
|
||||
secs := v / d
|
||||
@@ -212,7 +215,11 @@ func FromStream(
|
||||
if slices.Contains(conn.FourCcList, any(fourCCToString(message.FourCCOpus))) {
|
||||
track := &gortmplib.Track{
|
||||
Codec: &codecs.Opus{
|
||||
ChannelCount: forma.ChannelCount,
|
||||
IDHeader: &opus.IDHeader{
|
||||
Version: 0x1,
|
||||
ChannelCount: uint8(forma.ChannelCount),
|
||||
PreSkip: 3840,
|
||||
},
|
||||
},
|
||||
}
|
||||
tracks = append(tracks, track)
|
||||
@@ -453,6 +460,41 @@ func FromStream(
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
case *format.Generic:
|
||||
if strings.HasPrefix(strings.ToLower(forma.RTPMap()), "flac/") &&
|
||||
slices.Contains(conn.FourCcList, any(fourCCToString(message.FourCCFLAC))) {
|
||||
sampleRate, _ := strconv.Atoi(forma.FMTP()["samplerate"])
|
||||
channelCount, _ := strconv.Atoi(forma.FMTP()["channels"])
|
||||
bitDepth, _ := strconv.Atoi(forma.FMTP()["bitdepth"])
|
||||
|
||||
track := &gortmplib.Track{
|
||||
Codec: &codecs.FLAC{
|
||||
StreamInfo: &flac.StreamInfo{
|
||||
SampleRate: uint32(sampleRate),
|
||||
ChannelCount: uint8(channelCount),
|
||||
BitDepth: uint8(bitDepth),
|
||||
},
|
||||
},
|
||||
}
|
||||
tracks = append(tracks, track)
|
||||
|
||||
r.OnData(
|
||||
media,
|
||||
forma,
|
||||
func(u *unit.Unit) error {
|
||||
if u.NilPayload() {
|
||||
return nil
|
||||
}
|
||||
|
||||
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
|
||||
return (*w).WriteFLAC(
|
||||
track,
|
||||
timestampToDuration(u.PTS, forma.ClockRate()),
|
||||
u.Payload.(unit.PayloadFLAC),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ import (
|
||||
"github.com/bluenviron/gortmplib/pkg/codecs"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/flac"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/mpeg4audio"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/opus"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/stream"
|
||||
"github.com/bluenviron/mediamtx/internal/test"
|
||||
@@ -224,7 +226,12 @@ func TestFromStream(t *testing.T) {
|
||||
},
|
||||
expectedTracks: []*gortmplib.Track{
|
||||
{Codec: &codecs.Opus{
|
||||
ChannelCount: 2,
|
||||
IDHeader: &opus.IDHeader{
|
||||
Version: 0x1,
|
||||
ChannelCount: 2,
|
||||
PreSkip: 3840,
|
||||
ChannelMappingTable: []uint8{},
|
||||
},
|
||||
}},
|
||||
},
|
||||
writeUnits: func(medias []*description.Media, subStream *stream.SubStream) {
|
||||
@@ -445,6 +452,40 @@ func TestFromStream(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "flac",
|
||||
medias: []*description.Media{
|
||||
{
|
||||
Formats: []format.Format{&format.Generic{
|
||||
PayloadTyp: 96,
|
||||
RTPMa: "FLAC/90000",
|
||||
ClockRat: 90000,
|
||||
FMT: map[string]string{
|
||||
"samplerate": "44100",
|
||||
"channels": "2",
|
||||
"bitdepth": "16",
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
expectedTracks: []*gortmplib.Track{
|
||||
{Codec: &codecs.FLAC{
|
||||
StreamInfo: &flac.StreamInfo{
|
||||
SampleRate: 44100,
|
||||
ChannelCount: 2,
|
||||
BitDepth: 16,
|
||||
},
|
||||
}},
|
||||
},
|
||||
writeUnits: func(medias []*description.Media, subStream *stream.SubStream) {
|
||||
for i := range 2 {
|
||||
subStream.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
|
||||
PTS: 90000 * 5 * int64(i),
|
||||
Payload: unit.PayloadFLAC{3, 4},
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "h265 + h264 + vp9 + av1 + opus + aac",
|
||||
medias: []*description.Media{
|
||||
@@ -489,7 +530,12 @@ func TestFromStream(t *testing.T) {
|
||||
{Codec: &codecs.VP9{}},
|
||||
{Codec: &codecs.AV1{}},
|
||||
{Codec: &codecs.Opus{
|
||||
ChannelCount: 2,
|
||||
IDHeader: &opus.IDHeader{
|
||||
Version: 0x1,
|
||||
ChannelCount: 2,
|
||||
PreSkip: 3840,
|
||||
ChannelMappingTable: []uint8{},
|
||||
},
|
||||
}},
|
||||
{Codec: &codecs.MPEG4Audio{
|
||||
Config: test.FormatMPEG4Audio.Config,
|
||||
|
||||
@@ -2,6 +2,7 @@ package rtmp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortmplib"
|
||||
@@ -15,7 +16,7 @@ import (
|
||||
|
||||
var errNoSupportedCodecsTo = errors.New(
|
||||
"the stream doesn't contain any supported codec, which are currently " +
|
||||
"AV1, VP9, H265, H264, MPEG-4 Audio, MPEG-1/2 Audio, G711, LPCM")
|
||||
"AV1, VP9, H265, H264, Opus, FLAC, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711, LPCM")
|
||||
|
||||
func multiplyAndDivide(v, m, d int64) int64 {
|
||||
secs := v / d
|
||||
@@ -115,9 +116,13 @@ func ToStream(
|
||||
})
|
||||
|
||||
case *codecs.Opus:
|
||||
channelCount := 2
|
||||
if codec.IDHeader != nil {
|
||||
channelCount = int(codec.IDHeader.ChannelCount)
|
||||
}
|
||||
forma := &format.Opus{
|
||||
PayloadTyp: 96,
|
||||
ChannelCount: codec.ChannelCount,
|
||||
ChannelCount: channelCount,
|
||||
}
|
||||
medi := &description.Media{
|
||||
Type: description.MediaTypeAudio,
|
||||
@@ -132,6 +137,38 @@ func ToStream(
|
||||
})
|
||||
})
|
||||
|
||||
case *codecs.FLAC:
|
||||
sampleRate := 0
|
||||
channelCount := 0
|
||||
bitDepth := 0
|
||||
if codec.StreamInfo != nil {
|
||||
sampleRate = int(codec.StreamInfo.SampleRate)
|
||||
channelCount = int(codec.StreamInfo.ChannelCount)
|
||||
bitDepth = int(codec.StreamInfo.BitDepth)
|
||||
}
|
||||
forma := &format.Generic{
|
||||
PayloadTyp: 96,
|
||||
RTPMa: "flac/90000",
|
||||
ClockRat: 90000,
|
||||
FMT: map[string]string{
|
||||
"samplerate": strconv.Itoa(sampleRate),
|
||||
"channels": strconv.Itoa(channelCount),
|
||||
"bitdepth": strconv.Itoa(bitDepth),
|
||||
},
|
||||
}
|
||||
medi := &description.Media{
|
||||
Type: description.MediaTypeApplication,
|
||||
Formats: []format.Format{forma},
|
||||
}
|
||||
medias = append(medias, medi)
|
||||
|
||||
r.OnDataFLAC(track, func(pts time.Duration, frame []byte) {
|
||||
(*subStream).WriteUnit(medi, forma, &unit.Unit{
|
||||
PTS: durationToTimestamp(pts, forma.ClockRate()),
|
||||
Payload: unit.PayloadFLAC(frame),
|
||||
})
|
||||
})
|
||||
|
||||
case *codecs.MPEG4Audio:
|
||||
forma := &format.MPEG4Audio{
|
||||
PayloadTyp: 96,
|
||||
@@ -235,9 +272,6 @@ func ToStream(
|
||||
Payload: unit.PayloadLPCM(samples),
|
||||
})
|
||||
})
|
||||
|
||||
default:
|
||||
panic("should not happen")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -359,8 +359,7 @@ func newRTPDecoder(forma format.Format) (rtpDecoder, error) {
|
||||
return nil, err
|
||||
}
|
||||
return (*rtpDecoderKLV)(wrapped), nil
|
||||
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package stream
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpac3"
|
||||
@@ -151,6 +152,16 @@ func (e *rtpEncoderKLV) encode(payload unit.Payload) ([]*rtp.Packet, error) {
|
||||
return (*rtpklv.Encoder)(e).Encode(payload.(unit.PayloadKLV))
|
||||
}
|
||||
|
||||
type rtpEncoderEmpty struct{}
|
||||
|
||||
func (e *rtpEncoderEmpty) init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *rtpEncoderEmpty) encode(_ unit.Payload) ([]*rtp.Packet, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func newRTPEncoder(
|
||||
forma format.Format,
|
||||
rtpMaxPayloadSize int,
|
||||
@@ -388,7 +399,16 @@ func newRTPEncoder(
|
||||
|
||||
return (*rtpEncoderKLV)(wrapped), nil
|
||||
|
||||
default:
|
||||
return nil, rtpEncoderNotAvailableError{forma}
|
||||
case *format.Generic:
|
||||
if strings.HasPrefix(strings.ToLower(forma.RTPMap()), "flac/") {
|
||||
enc := &rtpEncoderEmpty{}
|
||||
err := enc.init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return enc, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, rtpEncoderNotAvailableError{forma}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package unit
|
||||
|
||||
// PayloadFLAC is the payload of a FLAC track.
|
||||
type PayloadFLAC []byte
|
||||
|
||||
func (PayloadFLAC) isPayload() {}
|
||||
Reference in New Issue
Block a user