tangled
alpha
login
or
join now
stream.place
/
streamplace
74
fork
atom
Live video on the AT Protocol
74
fork
atom
overview
issues
1
pulls
pipelines
media: proof-of-concept embedded rtmp server
Eli Mallon
3 months ago
383d5cb9
3b15cef8
+231
-50
4 changed files
expand all
collapse all
unified
split
go.mod
go.sum
pkg
cmd
streamplace.go
media
rtmp.go
+20
-16
go.mod
···
17
17
github.com/NYTimes/gziphandler v1.1.1
18
18
github.com/ThalesGroup/crypto11 v0.0.0-00010101000000-000000000000
19
19
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
20
20
+
github.com/bluenviron/gortmplib v0.1.2
21
21
+
github.com/bluenviron/gortsplib/v5 v5.2.1
20
22
github.com/bluesky-social/indigo v0.0.0-20251206005924-d49b45419635
21
23
github.com/cenkalti/backoff v2.2.1+incompatible
22
24
github.com/cenkalti/backoff/v5 v5.0.2
···
48
50
github.com/patrickmn/go-cache v2.1.0+incompatible
49
51
github.com/peterbourgon/ff/v3 v3.4.0
50
52
github.com/pion/interceptor v0.1.37
51
51
-
github.com/pion/rtcp v1.2.15
53
53
+
github.com/pion/rtcp v1.2.16
52
54
github.com/pion/webrtc/v4 v4.0.11
53
55
github.com/piprate/json-gold v0.5.0
54
56
github.com/prometheus/client_golang v1.23.0
···
59
61
github.com/starttoaster/prometheus-exporter-scraper v0.0.1
60
62
github.com/streamplace/atproto-oauth-golang v0.0.0-20250619231223-a9c04fb888ac
61
63
github.com/streamplace/oatproxy v0.0.0-20251207230012-236e9bd6dae6
62
62
-
github.com/stretchr/testify v1.10.0
64
64
+
github.com/stretchr/testify v1.11.1
63
65
github.com/tdewolff/canvas v0.0.0-20250728095813-50d4cb1eee71
64
66
github.com/whyrusleeping/cbor-gen v0.3.1
65
67
github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6
···
69
71
go.opentelemetry.io/otel/sdk v1.36.0
70
72
go.uber.org/goleak v1.3.0
71
73
golang.org/x/image v0.30.0
72
72
-
golang.org/x/net v0.43.0
73
73
-
golang.org/x/sync v0.16.0
74
74
-
golang.org/x/term v0.34.0
74
74
+
golang.org/x/net v0.47.0
75
75
+
golang.org/x/sync v0.18.0
76
76
+
golang.org/x/term v0.37.0
75
77
golang.org/x/time v0.12.0
76
76
-
golang.org/x/tools v0.36.0
78
78
+
golang.org/x/tools v0.38.0
77
79
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da
78
80
google.golang.org/api v0.228.0
79
81
gorm.io/datatypes v1.2.4
···
86
88
github.com/jinzhu/inflection v1.0.0 // indirect
87
89
github.com/jinzhu/now v1.1.5 // indirect
88
90
github.com/mattn/go-isatty v0.0.20
89
89
-
golang.org/x/sys v0.35.0 // indirect
91
91
+
golang.org/x/sys v0.38.0 // indirect
90
92
gorm.io/gorm v1.26.1
91
93
)
92
94
···
137
139
github.com/RussellLuo/slidingwindow v0.0.0-20200528002341-535bb99d338b // indirect
138
140
github.com/StackExchange/wmi v1.2.1 // indirect
139
141
github.com/VictoriaMetrics/fastcache v1.13.0 // indirect
142
142
+
github.com/abema/go-mp4 v1.4.1 // indirect
140
143
github.com/agnivade/levenshtein v1.2.0 // indirect
141
144
github.com/alecthomas/chroma/v2 v2.17.2 // indirect
142
145
github.com/alecthomas/go-check-sumtype v0.3.1 // indirect
···
149
152
github.com/ashanbrown/forbidigo v1.6.0 // indirect
150
153
github.com/ashanbrown/makezero v1.2.0 // indirect
151
154
github.com/asticode/go-astikit v0.30.0 // indirect
152
152
-
github.com/asticode/go-astits v1.13.0 // indirect
155
155
+
github.com/asticode/go-astits v1.14.0 // indirect
153
156
github.com/aws/aws-sdk-go v1.44.273 // indirect
154
157
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
155
158
github.com/benoitkugler/textlayout v0.3.1 // indirect
···
159
162
github.com/bkielbasa/cyclop v1.2.3 // indirect
160
163
github.com/blizzy78/varnamelen v0.8.0 // indirect
161
164
github.com/bluenviron/gortsplib/v4 v4.12.3 // indirect
162
162
-
github.com/bluenviron/mediacommon/v2 v2.4.0 // indirect
165
165
+
github.com/bluenviron/mediacommon/v2 v2.5.2 // indirect
163
166
github.com/bombsimon/wsl/v4 v4.7.0 // indirect
164
167
github.com/breml/bidichk v0.3.3 // indirect
165
168
github.com/breml/errchkjson v0.4.1 // indirect
···
398
401
github.com/pion/logging v0.2.4 // indirect
399
402
github.com/pion/mdns/v2 v2.0.7 // indirect
400
403
github.com/pion/randutil v0.1.0 // indirect
401
401
-
github.com/pion/rtp v1.8.21 // indirect
404
404
+
github.com/pion/rtp v1.8.26 // indirect
402
405
github.com/pion/sctp v1.8.37 // indirect
403
403
-
github.com/pion/sdp/v3 v3.0.10 // indirect
404
404
-
github.com/pion/srtp/v3 v3.0.4 // indirect
406
406
+
github.com/pion/sdp/v3 v3.0.16 // indirect
407
407
+
github.com/pion/srtp/v3 v3.0.9 // indirect
405
408
github.com/pion/stun/v3 v3.0.0 // indirect
406
406
-
github.com/pion/transport/v3 v3.0.7 // indirect
409
409
+
github.com/pion/transport/v3 v3.1.1 // indirect
407
410
github.com/pion/turn/v4 v4.0.0 // indirect
408
411
github.com/pjbgf/sha1cd v0.3.0 // indirect
409
412
github.com/pkg/errors v0.9.1 // indirect
···
507
510
go.uber.org/automaxprocs v1.6.0 // indirect
508
511
go.uber.org/multierr v1.11.0 // indirect
509
512
go.uber.org/zap v1.27.0 // indirect
510
510
-
golang.org/x/crypto v0.41.0 // indirect
513
513
+
golang.org/x/crypto v0.44.0 // indirect
511
514
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
512
515
golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect
513
513
-
golang.org/x/mod v0.27.0 // indirect
516
516
+
golang.org/x/mod v0.29.0 // indirect
514
517
golang.org/x/oauth2 v0.30.0 // indirect
515
515
-
golang.org/x/text v0.28.0 // indirect
518
518
+
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect
519
519
+
golang.org/x/text v0.31.0 // indirect
516
520
gonum.org/v1/plot v0.16.0 // indirect
517
521
google.golang.org/appengine/v2 v2.0.2 // indirect
518
522
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
+47
-34
go.sum
···
130
130
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
131
131
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
132
132
github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
133
133
+
github.com/abema/go-mp4 v1.4.1 h1:YoS4VRqd+pAmddRPLFf8vMk74kuGl6ULSjzhsIqwr6M=
134
134
+
github.com/abema/go-mp4 v1.4.1/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws=
133
135
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
134
136
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
135
137
github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY=
···
182
184
github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4=
183
185
github.com/asticode/go-astikit v0.30.0 h1:DkBkRQRIxYcknlaU7W7ksNfn4gMFsB0tqMJflxkRsZA=
184
186
github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
185
185
-
github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c=
186
186
-
github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
187
187
+
github.com/asticode/go-astits v1.14.0 h1:zkgnZzipx2XX5mWycqsSBeEyDH58+i4HtyF4j2ROb00=
188
188
+
github.com/asticode/go-astits v1.14.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
187
189
github.com/aws/aws-sdk-go v1.44.273 h1:CX8O0gK+cGrgUyv7bgJ6QQP9mQg7u5mweHdNzULH47c=
188
190
github.com/aws/aws-sdk-go v1.44.273/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
189
191
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
···
209
211
github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo=
210
212
github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M=
211
213
github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k=
214
214
+
github.com/bluenviron/gortmplib v0.1.2 h1:bJ+5pUxKnHjEoKPbNs7lDLyYy5R9Z1lISJ1n54DsjWE=
215
215
+
github.com/bluenviron/gortmplib v0.1.2/go.mod h1:oVOWgfs7wsZNoKYLttyqLar7a71ZTohO1JOVXkNxtHg=
212
216
github.com/bluenviron/gortsplib/v4 v4.12.3 h1:3EzbyGb5+MIOJQYiWytRegFEP4EW5paiyTrscQj63WE=
213
217
github.com/bluenviron/gortsplib/v4 v4.12.3/go.mod h1:SkZPdaMNr+IvHt2PKRjUXxZN6FDutmSZn4eT0GmF0sk=
214
214
-
github.com/bluenviron/mediacommon/v2 v2.4.0 h1:Ss1T7AMxTrICJ+a/N5urS/1lp1ZpsF+3iJq3B/RLDMw=
215
215
-
github.com/bluenviron/mediacommon/v2 v2.4.0/go.mod h1:a6MbPmXtYda9mKibKVMZlW20GYLLrX2R7ZkUE+1pwV0=
218
218
+
github.com/bluenviron/gortsplib/v5 v5.2.1 h1:VrFC5RU8npiyKiqLFKXZmdUFChSmbjO5eZBfOUgxwjo=
219
219
+
github.com/bluenviron/gortsplib/v5 v5.2.1/go.mod h1:sK4+00XQaSpU2iPIKjmhj6Yye+sVbNWEU2IJWYEZI9U=
220
220
+
github.com/bluenviron/mediacommon/v2 v2.5.2 h1:eq7LHJFksDAVtVdTrwOUl7dO7LE8eKwLgYKYi5MmYaY=
221
221
+
github.com/bluenviron/mediacommon/v2 v2.5.2/go.mod h1:5V15TiOfeaNVmZPVuOqAwqQSWyvMV86/dijDKu5q9Zs=
216
222
github.com/bluesky-social/indigo v0.0.0-20251206005924-d49b45419635 h1:kNeRrgGJH2g5OvjLqtaQ744YXqduliZYpFkJ/ld47c0=
217
223
github.com/bluesky-social/indigo v0.0.0-20251206005924-d49b45419635/go.mod h1:Pm2I1+iDXn/hLbF7XCg/DsZi6uDCiOo7hZGWprSM7k0=
218
224
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
···
299
305
github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
300
306
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
301
307
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM=
308
308
+
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
302
309
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
303
310
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
304
311
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
···
860
867
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
861
868
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
862
869
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
870
870
+
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
863
871
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
864
872
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
865
873
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
···
1053
1061
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
1054
1062
github.com/orandin/slog-gorm v1.4.0 h1:FgA8hJufF9/jeNSYoEXmHPPBwET2gwlF3B85JdpsTUU=
1055
1063
github.com/orandin/slog-gorm v1.4.0/go.mod h1:MoZ51+b7xE9lwGNPYEhxcUtRNrYzjdcKvA8QXQQGEPA=
1064
1064
+
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGdY0Y6qfTeUKhDawdHDpK9RGBdx80qN4Ttw=
1065
1065
+
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
1056
1066
github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
1057
1067
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
1058
1068
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
···
1094
1104
github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
1095
1105
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
1096
1106
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
1097
1097
-
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
1098
1098
-
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
1099
1099
-
github.com/pion/rtp v1.8.21 h1:3yrOwmZFyUpcIosNcWRpQaU+UXIJ6yxLuJ8Bx0mw37Y=
1100
1100
-
github.com/pion/rtp v1.8.21/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk=
1107
1107
+
github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo=
1108
1108
+
github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo=
1109
1109
+
github.com/pion/rtp v1.8.26 h1:VB+ESQFQhBXFytD+Gk8cxB6dXeVf2WQzg4aORvAvAAc=
1110
1110
+
github.com/pion/rtp v1.8.26/go.mod h1:rF5nS1GqbR7H/TCpKwylzeq6yDM+MM6k+On5EgeThEM=
1101
1111
github.com/pion/sctp v1.8.37 h1:ZDmGPtRPX9mKCiVXtMbTWybFw3z/hVKAZgU81wcOrqs=
1102
1112
github.com/pion/sctp v1.8.37/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
1103
1103
-
github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
1104
1104
-
github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
1105
1105
-
github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
1106
1106
-
github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
1113
1113
+
github.com/pion/sdp/v3 v3.0.16 h1:0dKzYO6gTAvuLaAKQkC02eCPjMIi4NuAr/ibAwrGDCo=
1114
1114
+
github.com/pion/sdp/v3 v3.0.16/go.mod h1:9tyKzznud3qiweZcD86kS0ff1pGYB3VX+Bcsmkx6IXo=
1115
1115
+
github.com/pion/srtp/v3 v3.0.9 h1:lRGF4G61xxj+m/YluB3ZnBpiALSri2lTzba0kGZMrQY=
1116
1116
+
github.com/pion/srtp/v3 v3.0.9/go.mod h1:E+AuWd7Ug2Fp5u38MKnhduvpVkveXJX6J4Lq4rxUYt8=
1107
1117
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
1108
1118
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
1109
1119
github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0=
···
1112
1122
github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
1113
1123
github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
1114
1124
github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
1115
1115
-
github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
1116
1116
-
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
1125
1125
+
github.com/pion/transport/v3 v3.1.1 h1:Tr684+fnnKlhPceU+ICdrw6KKkTms+5qHMgw6bIkYOM=
1126
1126
+
github.com/pion/transport/v3 v3.1.1/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ=
1117
1127
github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
1118
1128
github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
1119
1129
github.com/pion/webrtc/v4 v4.0.11 h1:0i7BNFH2n8LVp08q/dqM5iyZBXW4TITbD1+RwNqk/iY=
···
1307
1317
github.com/streamplace/atproto-oauth-golang v0.0.0-20250619231223-a9c04fb888ac/go.mod h1:9LlKkqciiO5lRfbX0n4Wn5KNY9nvFb4R3by8FdW2TWc=
1308
1318
github.com/streamplace/go-dpop v0.0.0-20250510031900-c897158a8ad4 h1:L1fS4HJSaAyNnkwfuZubgfeZy8rkWmA0cMtH5Z0HqNc=
1309
1319
github.com/streamplace/go-dpop v0.0.0-20250510031900-c897158a8ad4/go.mod h1:bGUXY9Wd4mnd+XUrOYZr358J2f6z9QO/dLhL1SsiD+0=
1310
1310
-
github.com/streamplace/oatproxy v0.0.0-20251201231246-9e9aa13c659d h1:xVIF467970izRZBXBC+/XWyCB6zBtxwZ1KGytEp1rTc=
1311
1311
-
github.com/streamplace/oatproxy v0.0.0-20251201231246-9e9aa13c659d/go.mod h1:pXi24hA7xBHj8eEywX6wGqJOR9FaEYlGwQ/72rN6okw=
1312
1320
github.com/streamplace/oatproxy v0.0.0-20251207230012-236e9bd6dae6 h1:Y81F18H+qQGWk58Vqangsw75XQ6G1shJOsUEqgKQdYI=
1313
1321
github.com/streamplace/oatproxy v0.0.0-20251207230012-236e9bd6dae6/go.mod h1:pXi24hA7xBHj8eEywX6wGqJOR9FaEYlGwQ/72rN6okw=
1314
1322
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
···
1328
1336
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
1329
1337
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
1330
1338
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
1331
1331
-
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
1332
1332
-
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
1339
1339
+
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
1340
1340
+
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
1333
1341
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
1334
1342
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
1335
1343
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
1344
1344
+
github.com/sunfish-shogi/bufseekio v0.0.0-20210207115823-a4185644b365/go.mod h1:dEzdXgvImkQ3WLI+0KQpmEx8T/C/ma9KeS3AfmU899I=
1336
1345
github.com/supranational/blst v0.3.15 h1:rd9viN6tfARE5wv3KZJ9H8e1cg0jXW8syFCcsbHa76o=
1337
1346
github.com/supranational/blst v0.3.15/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
1338
1347
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
···
1520
1529
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
1521
1530
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
1522
1531
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
1523
1523
-
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
1524
1524
-
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
1532
1532
+
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
1533
1533
+
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
1525
1534
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
1526
1535
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
1527
1536
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
···
1573
1582
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
1574
1583
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
1575
1584
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
1576
1576
-
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
1577
1577
-
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
1585
1585
+
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
1586
1586
+
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
1578
1587
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
1579
1588
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
1580
1589
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
···
1627
1636
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
1628
1637
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
1629
1638
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
1630
1630
-
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
1631
1631
-
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
1639
1639
+
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
1640
1640
+
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
1632
1641
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
1633
1642
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
1634
1643
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
···
1658
1667
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
1659
1668
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
1660
1669
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
1661
1661
-
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
1662
1662
-
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
1670
1670
+
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
1671
1671
+
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
1663
1672
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
1664
1673
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
1665
1674
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
···
1722
1731
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1723
1732
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1724
1733
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1725
1725
-
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
1726
1726
-
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
1734
1734
+
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
1735
1735
+
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
1727
1736
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
1737
1737
+
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU=
1738
1738
+
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
1728
1739
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
1729
1740
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
1730
1741
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
···
1736
1747
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
1737
1748
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
1738
1749
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
1739
1739
-
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
1740
1740
-
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
1750
1750
+
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
1751
1751
+
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
1741
1752
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
1742
1753
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
1743
1754
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
···
1754
1765
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
1755
1766
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
1756
1767
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
1757
1757
-
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
1758
1758
-
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
1768
1768
+
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
1769
1769
+
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
1759
1770
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
1760
1771
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
1761
1772
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
···
1823
1834
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
1824
1835
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
1825
1836
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
1826
1826
-
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
1827
1827
-
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
1837
1837
+
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
1838
1838
+
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
1828
1839
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
1829
1840
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
1830
1841
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
···
1946
1957
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
1947
1958
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
1948
1959
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
1960
1960
+
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
1961
1961
+
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
1949
1962
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
1950
1963
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
1951
1964
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
+4
pkg/cmd/streamplace.go
···
448
448
})
449
449
450
450
group.Go(func() error {
451
451
+
return media.StartRTMPServer(ctx)
452
452
+
})
453
453
+
454
454
+
group.Go(func() error {
451
455
return replicator.Start(ctx, &cli)
452
456
})
453
457
+160
pkg/media/rtmp.go
···
1
1
+
// Package main contains an example.
2
2
+
package media
3
3
+
4
4
+
import (
5
5
+
"context"
6
6
+
"fmt"
7
7
+
"net"
8
8
+
"time"
9
9
+
10
10
+
"github.com/bluenviron/gortmplib"
11
11
+
"github.com/bluenviron/gortsplib/v5/pkg/format"
12
12
+
"stream.place/streamplace/pkg/log"
13
13
+
)
14
14
+
15
15
+
// This example shows how to:
16
16
+
// 1. create a RTMP server
17
17
+
// 2. accept a stream from a reader.
18
18
+
// 3. broadcast the stream to readers.
19
19
+
20
20
+
// var (
21
21
+
// mutex sync.Mutex
22
22
+
// publisher *gortmplib.ServerConn
23
23
+
// tracks []format.Format
24
24
+
// readers []*gortmplib.Writer
25
25
+
// )
26
26
+
27
27
+
func handlePublisher(ctx context.Context, sc *gortmplib.ServerConn) error {
28
28
+
sc.RW.(net.Conn).SetReadDeadline(time.Now().Add(10 * time.Second))
29
29
+
30
30
+
r := &gortmplib.Reader{
31
31
+
Conn: sc,
32
32
+
}
33
33
+
err := r.Initialize()
34
34
+
if err != nil {
35
35
+
return err
36
36
+
}
37
37
+
38
38
+
log.Log(ctx, "conn %v is publishing:", sc.RW.(net.Conn).RemoteAddr())
39
39
+
40
40
+
for _, track := range r.Tracks() {
41
41
+
log.Log(ctx, "get track", "track", track)
42
42
+
43
43
+
switch track := track.(type) {
44
44
+
case *format.AV1:
45
45
+
r.OnDataAV1(track, func(pts time.Duration, tu [][]byte) {
46
46
+
log.Log(ctx, "got AV1", "len", len(tu), "pts", pts)
47
47
+
})
48
48
+
49
49
+
case *format.VP9:
50
50
+
r.OnDataVP9(track, func(pts time.Duration, frame []byte) {
51
51
+
52
52
+
log.Log(ctx, "got VP9", "len", len(frame), "pts", pts)
53
53
+
})
54
54
+
55
55
+
case *format.H265:
56
56
+
r.OnDataH265(track, func(pts time.Duration, dts time.Duration, au [][]byte) {
57
57
+
log.Log(ctx, "got H265", "len", len(au), "pts", pts, "dts", dts)
58
58
+
})
59
59
+
60
60
+
case *format.H264:
61
61
+
r.OnDataH264(track, func(pts time.Duration, dts time.Duration, au [][]byte) {
62
62
+
log.Log(ctx, "got H264", "len", len(au), "pts", pts, "dts", dts)
63
63
+
})
64
64
+
65
65
+
case *format.Opus:
66
66
+
r.OnDataOpus(track, func(pts time.Duration, packet []byte) {
67
67
+
log.Log(ctx, "got Opus", "len", len(packet), "pts", pts)
68
68
+
})
69
69
+
70
70
+
case *format.MPEG4Audio:
71
71
+
r.OnDataMPEG4Audio(track, func(pts time.Duration, au []byte) {
72
72
+
log.Log(ctx, "got MPEG4Au", "len", len(au), "pts", pts)
73
73
+
})
74
74
+
75
75
+
case *format.MPEG1Audio:
76
76
+
r.OnDataMPEG1Audio(track, func(pts time.Duration, frame []byte) {
77
77
+
log.Log(ctx, "got MPEG1Au", "len", len(frame), "pts", pts)
78
78
+
})
79
79
+
80
80
+
case *format.AC3:
81
81
+
r.OnDataAC3(track, func(pts time.Duration, frame []byte) {
82
82
+
log.Log(ctx, "got AC3", "len", len(frame), "pts", pts)
83
83
+
})
84
84
+
85
85
+
case *format.G711:
86
86
+
r.OnDataG711(track, func(pts time.Duration, samples []byte) {
87
87
+
log.Log(ctx, "got G711", "len", len(samples), "pts", pts)
88
88
+
})
89
89
+
90
90
+
case *format.LPCM:
91
91
+
r.OnDataLPCM(track, func(pts time.Duration, samples []byte) {
92
92
+
log.Log(ctx, "got LPCM", "len", len(samples), "pts", pts)
93
93
+
})
94
94
+
}
95
95
+
}
96
96
+
97
97
+
for {
98
98
+
sc.RW.(net.Conn).SetReadDeadline(time.Now().Add(10 * time.Second))
99
99
+
err = r.Read()
100
100
+
if err != nil {
101
101
+
return err
102
102
+
}
103
103
+
}
104
104
+
}
105
105
+
106
106
+
func handleConnInner(ctx context.Context, conn net.Conn) error {
107
107
+
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
108
108
+
109
109
+
sc := &gortmplib.ServerConn{
110
110
+
RW: conn,
111
111
+
}
112
112
+
err := sc.Initialize()
113
113
+
if err != nil {
114
114
+
return err
115
115
+
}
116
116
+
117
117
+
err = sc.Accept()
118
118
+
if err != nil {
119
119
+
return err
120
120
+
}
121
121
+
122
122
+
if sc.Publish {
123
123
+
return handlePublisher(ctx, sc)
124
124
+
}
125
125
+
return fmt.Errorf("RTMP playback is not supported")
126
126
+
}
127
127
+
128
128
+
func handleConn(ctx context.Context, conn net.Conn) {
129
129
+
defer conn.Close()
130
130
+
131
131
+
log.Log(ctx, "conn %v opened", conn.RemoteAddr())
132
132
+
err := handleConnInner(ctx, conn)
133
133
+
log.Log(ctx, "conn %v closed: %v", conn.RemoteAddr(), err)
134
134
+
}
135
135
+
136
136
+
func StartRTMPServer(ctx context.Context) error {
137
137
+
ln, err := net.Listen("tcp", ":1935")
138
138
+
if err != nil {
139
139
+
return fmt.Errorf("failed to listen: %w", err)
140
140
+
}
141
141
+
defer ln.Close()
142
142
+
143
143
+
log.Log(ctx, "listening on :1935")
144
144
+
145
145
+
// Accept loop in a goroutine so we can select on context.Done
146
146
+
go func() {
147
147
+
for {
148
148
+
conn, err := ln.Accept()
149
149
+
if err != nil {
150
150
+
log.Error(ctx, "error accepting RTMP connection", "error", err)
151
151
+
}
152
152
+
153
153
+
go handleConn(ctx, conn)
154
154
+
}
155
155
+
}()
156
156
+
157
157
+
<-ctx.Done()
158
158
+
159
159
+
return ln.Close()
160
160
+
}