-
Notifications
You must be signed in to change notification settings - Fork 595
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
358 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,8 @@ Ultimate camera streaming application with support RTSP, WebRTC, HomeKit, FFmpeg | |
|
||
- zero-dependency and zero-config [small app](#go2rtc-binary) for all OS (Windows, macOS, Linux, ARM) | ||
- zero-delay for many supported protocols (lowest possible streaming latency) | ||
- streaming from [RTSP](#source-rtsp), [RTMP](#source-rtmp), [MJPEG](#source-ffmpeg), [HLS](#source-ffmpeg), [USB Cameras](#source-ffmpeg-device), [files](#source-ffmpeg) and [other sources](#module-streams) | ||
- streaming to [RTSP](#module-rtsp), [WebRTC](#module-webrtc) or [MSE](#module-mp4) | ||
- streaming from [RTSP](#source-rtsp), [RTMP](#source-rtmp), [MJPEG](#source-ffmpeg), [HLS/HTTP](#source-ffmpeg), [USB Cameras](#source-ffmpeg-device) and [other sources](#module-streams) | ||
- streaming to [RTSP](#module-rtsp), [WebRTC](#module-webrtc), [MSE/MP4](#module-mp4) or [MJPEG](#module-mjpeg) | ||
- first project in the World with support streaming from [HomeKit Cameras](#source-homekit) | ||
- on the fly transcoding for unsupported codecs via [FFmpeg](#source-ffmpeg) | ||
- multi-source 2-way [codecs negotiation](#codecs-negotiation) | ||
|
@@ -327,13 +327,9 @@ api: | |
|
||
### Module: RTSP | ||
|
||
You can get any stream as RTSP-stream with codecs filter: | ||
You can get any stream as RTSP-stream: `rtsp://192.168.1.123:8554/{stream_name}` | ||
|
||
``` | ||
rtsp://192.168.1.123/{stream_name}?video={codec}&audio={codec1}&audio={codec2} | ||
``` | ||
|
||
- you can omit the codecs, so one first video and one first audio will be selected | ||
- you can omit the codec filters, so one first video and one first audio will be selected | ||
- you can set `?video=copy` or just `?video`, so only one first video without audio will be selected | ||
- you can set multiple video or audio, so all of them will be selected | ||
|
||
|
@@ -497,6 +493,19 @@ Provides several features: | |
2. Camera snapshots in MP4 format (single frame), can be sent to [Telegram](https://www.telegram.org/) | ||
3. Progressive MP4 stream - bad format for streaming because of high latency, doesn't work in Safari | ||
|
||
### Module: MJPEG | ||
|
||
**Important.** For stream as MJPEG format, your source MUST contain the MJPEG codec. If your camera outputs H264/H265 - you SHOULD use transcoding. With this example, your stream will have both H264 and MJPEG codecs: | ||
|
||
```yaml | ||
streams: | ||
camera1: | ||
- rtsp://rtsp:[email protected]/av_stream/ch0 | ||
- ffmpeg:rtsp://rtsp:[email protected]/av_stream/ch0#video=mjpeg | ||
``` | ||
|
||
Example link to MJPEG: `http://192.168.1.123:1984/api/stream.mjpeg?src=camera1` | ||
|
||
### Module: Log | ||
|
||
You can set different log levels for different modules. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package mjpeg | ||
|
||
import ( | ||
"github.com/AlexxIT/go2rtc/cmd/api" | ||
"github.com/AlexxIT/go2rtc/cmd/streams" | ||
"github.com/AlexxIT/go2rtc/pkg/mjpeg" | ||
"github.com/rs/zerolog/log" | ||
"net/http" | ||
"strconv" | ||
) | ||
|
||
func Init() { | ||
api.HandleFunc("api/stream.mjpeg", handler) | ||
} | ||
|
||
const header = "--frame\r\nContent-Type: image/jpeg\r\nContent-Length: " | ||
|
||
func handler(w http.ResponseWriter, r *http.Request) { | ||
src := r.URL.Query().Get("src") | ||
stream := streams.GetOrNew(src) | ||
if stream == nil { | ||
return | ||
} | ||
|
||
exit := make(chan struct{}) | ||
|
||
cons := &mjpeg.Consumer{} | ||
cons.Listen(func(msg interface{}) { | ||
switch msg := msg.(type) { | ||
case []byte: | ||
data := []byte(header + strconv.Itoa(len(msg))) | ||
data = append(data, 0x0D, 0x0A, 0x0D, 0x0A) | ||
data = append(data, msg...) | ||
data = append(data, 0x0D, 0x0A) | ||
|
||
if _, err := w.Write(data); err != nil { | ||
exit <- struct{}{} | ||
} | ||
} | ||
}) | ||
|
||
if err := stream.AddConsumer(cons); err != nil { | ||
log.Error().Err(err).Msg("[api.mjpeg] add consumer") | ||
return | ||
} | ||
|
||
w.Header().Set("Content-Type", `multipart/x-mixed-replace; boundary=frame`) | ||
|
||
<-exit | ||
|
||
stream.RemoveConsumer(cons) | ||
|
||
//log.Trace().Msg("[api.mjpeg] close") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## Useful links | ||
|
||
- https://www.rfc-editor.org/rfc/rfc2435 | ||
- https://github.com/GStreamer/gst-plugins-good/blob/master/gst/rtp/gstrtpjpegdepay.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package mjpeg | ||
|
||
import ( | ||
"github.com/AlexxIT/go2rtc/pkg/streamer" | ||
"github.com/pion/rtp" | ||
) | ||
|
||
type Consumer struct { | ||
streamer.Element | ||
|
||
UserAgent string | ||
RemoteAddr string | ||
|
||
codecs []*streamer.Codec | ||
start bool | ||
|
||
send int | ||
} | ||
|
||
func (c *Consumer) GetMedias() []*streamer.Media { | ||
return []*streamer.Media{{ | ||
Kind: streamer.KindVideo, | ||
Direction: streamer.DirectionRecvonly, | ||
Codecs: []*streamer.Codec{{Name: streamer.CodecJPEG}}, | ||
}} | ||
} | ||
|
||
func (c *Consumer) AddTrack(media *streamer.Media, track *streamer.Track) *streamer.Track { | ||
var header, payload []byte | ||
|
||
push := func(packet *rtp.Packet) error { | ||
//fmt.Printf( | ||
// "[RTP] codec: %s, size: %6d, ts: %10d, pt: %2d, ssrc: %d, seq: %d, mark: %v\n", | ||
// track.Codec.Name, len(packet.Payload), packet.Timestamp, | ||
// packet.PayloadType, packet.SSRC, packet.SequenceNumber, packet.Marker, | ||
//) | ||
|
||
// https://www.rfc-editor.org/rfc/rfc2435#section-3.1 | ||
b := packet.Payload | ||
|
||
// 3.1. JPEG header | ||
t := b[4] | ||
|
||
// 3.1.7. Restart Marker header | ||
if 64 <= t && t <= 127 { | ||
b = b[12:] // skip it | ||
} else { | ||
b = b[8:] | ||
} | ||
|
||
if header == nil { | ||
var lqt, cqt []byte | ||
|
||
// 3.1.8. Quantization Table header | ||
q := packet.Payload[5] | ||
if q >= 128 { | ||
lqt = b[4:68] | ||
cqt = b[68:132] | ||
b = b[132:] | ||
} else { | ||
lqt, cqt = MakeTables(q) | ||
} | ||
|
||
w := uint16(packet.Payload[6]) << 3 | ||
h := uint16(packet.Payload[7]) << 3 | ||
//fmt.Printf("t: %d, q: %d, w: %d, h: %d\n", t, q, w, h) | ||
header = MakeHeaders(t, w, h, lqt, cqt) | ||
} | ||
|
||
// 3.1.9. JPEG Payload | ||
payload = append(payload, b...) | ||
|
||
if packet.Marker { | ||
b = append(header, payload...) | ||
if end := b[len(b)-2:]; end[0] != 0xFF && end[1] != 0xD9 { | ||
b = append(b, 0xFF, 0xD9) | ||
} | ||
c.Fire(b) | ||
|
||
header = nil | ||
payload = nil | ||
} | ||
|
||
return nil | ||
} | ||
return track.Bind(push) | ||
} |
Oops, something went wrong.