Skip to content

Commit a42d174

Browse files
boks1971yoonsio
andauthored
Add argument for h26x streaming format. (#720)
* Add argument for h62x streaming format. Bumping version to match version of server-sdk-go. Added H26x streaming format in server-sdk-go in livekit/server-sdk-go#793 livekit/server-sdk-go#796 * rename h26xFormat -> h26xStreamingFormat * remove local * error log * fix build log output format (#721) * Add argument for h62x streaming format. Bumping version to match version of server-sdk-go. Added H26x streaming format in server-sdk-go in livekit/server-sdk-go#793 livekit/server-sdk-go#796 * rename h26xFormat -> h26xStreamingFormat * remove local * error log * v2.12.8 --------- Co-authored-by: Steve Yoon <[email protected]>
1 parent 93e40a3 commit a42d174

File tree

5 files changed

+91
-52
lines changed

5 files changed

+91
-52
lines changed

cmd/lk/join.go

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ func _deprecatedJoinRoom(ctx context.Context, cmd *cli.Command) error {
170170

171171
if cmd.StringSlice("publish") != nil {
172172
fps := cmd.Float("fps")
173+
h26xStreamingFormat := cmd.String("h26x-streaming-format")
173174
for _, pub := range cmd.StringSlice("publish") {
174175
onPublishComplete := func(pub *lksdk.LocalTrackPublication) {
175176
if cmd.Bool("exit-after-publish") {
@@ -181,7 +182,7 @@ func _deprecatedJoinRoom(ctx context.Context, cmd *cli.Command) error {
181182
_ = room.LocalParticipant.UnpublishTrack(pub.SID())
182183
}
183184
}
184-
if err = handlePublish(room, pub, fps, onPublishComplete); err != nil {
185+
if err = handlePublish(room, pub, fps, h26xStreamingFormat, onPublishComplete); err != nil {
185186
return err
186187
}
187188
}
@@ -194,16 +195,17 @@ func _deprecatedJoinRoom(ctx context.Context, cmd *cli.Command) error {
194195
func handlePublish(room *lksdk.Room,
195196
name string,
196197
fps float64,
198+
h26xStreamingFormat string,
197199
onPublishComplete func(pub *lksdk.LocalTrackPublication),
198200
) error {
199201
if isSocketFormat(name) {
200202
mimeType, socketType, address, err := parseSocketFromName(name)
201203
if err != nil {
202204
return err
203205
}
204-
return publishSocket(room, mimeType, socketType, address, fps, onPublishComplete)
206+
return publishSocket(room, mimeType, socketType, address, fps, h26xStreamingFormat, onPublishComplete)
205207
}
206-
return publishFile(room, name, fps, onPublishComplete)
208+
return publishFile(room, name, fps, h26xStreamingFormat, onPublishComplete)
207209
}
208210

209211
func publishDemo(room *lksdk.Room) error {
@@ -235,6 +237,7 @@ func publishDemo(room *lksdk.Room) error {
235237
func publishFile(room *lksdk.Room,
236238
filename string,
237239
fps float64,
240+
h26xStreamingFormat string,
238241
onPublishComplete func(pub *lksdk.LocalTrackPublication),
239242
) error {
240243
// Configure provider
@@ -260,6 +263,15 @@ func publishFile(room *lksdk.Room,
260263
frameDuration := time.Second / time.Duration(fps)
261264
opts = append(opts, lksdk.ReaderTrackWithFrameDuration(frameDuration))
262265
}
266+
267+
switch h26xStreamingFormat {
268+
case "annex-b":
269+
opts = append(opts, lksdk.ReaderTrackWithH26xStreamingFormat(lksdk.H26xStreamingFormatAnnexB))
270+
case "length-prefixed":
271+
opts = append(opts, lksdk.ReaderTrackWithH26xStreamingFormat(lksdk.H26xStreamingFormatLengthPrefixed))
272+
default:
273+
return fmt.Errorf("unsupported h26x streaming format: %s", h26xStreamingFormat)
274+
}
263275
}
264276

265277
// Create track and publish
@@ -312,6 +324,7 @@ func publishSocket(room *lksdk.Room,
312324
socketType string,
313325
address string,
314326
fps float64,
327+
h26xStreamingFormat string,
315328
onPublishComplete func(pub *lksdk.LocalTrackPublication),
316329
) error {
317330
var mime string
@@ -333,14 +346,15 @@ func publishSocket(room *lksdk.Room,
333346
}
334347

335348
// Publish to room
336-
err = publishReader(room, sock, mime, fps, onPublishComplete)
349+
err = publishReader(room, sock, mime, fps, h26xStreamingFormat, onPublishComplete)
337350
return err
338351
}
339352

340353
func publishReader(room *lksdk.Room,
341354
in io.ReadCloser,
342355
mime string,
343356
fps float64,
357+
h26xStreamingFormat string,
344358
onPublishComplete func(pub *lksdk.LocalTrackPublication),
345359
) error {
346360
// Configure provider
@@ -358,6 +372,15 @@ func publishReader(room *lksdk.Room,
358372
frameDuration := time.Second / time.Duration(fps)
359373
opts = append(opts, lksdk.ReaderTrackWithFrameDuration(frameDuration))
360374
}
375+
376+
switch h26xStreamingFormat {
377+
case "annex-b":
378+
opts = append(opts, lksdk.ReaderTrackWithH26xStreamingFormat(lksdk.H26xStreamingFormatAnnexB))
379+
case "length-prefixed":
380+
opts = append(opts, lksdk.ReaderTrackWithH26xStreamingFormat(lksdk.H26xStreamingFormatLengthPrefixed))
381+
default:
382+
return fmt.Errorf("unsupported h26x streaming format: %s", h26xStreamingFormat)
383+
}
361384
}
362385

363386
// Create track and publish
@@ -414,7 +437,7 @@ func parseSimulcastURL(url string) (*simulcastURLParts, error) {
414437
}
415438

416439
// createSimulcastVideoTrack creates a simulcast video track from a TCP or Unix socket H.264 streams
417-
func createSimulcastVideoTrack(urlParts *simulcastURLParts, quality livekit.VideoQuality, fps float64, onComplete func()) (*lksdk.LocalTrack, error) {
440+
func createSimulcastVideoTrack(urlParts *simulcastURLParts, quality livekit.VideoQuality, fps float64, h26xStreamingFormat string, onComplete func()) (*lksdk.LocalTrack, error) {
418441
conn, err := net.Dial(urlParts.network, urlParts.address)
419442
if err != nil {
420443
return nil, fmt.Errorf("failed to connect to %s://%s: %w", urlParts.network, urlParts.address, err)
@@ -433,6 +456,15 @@ func createSimulcastVideoTrack(urlParts *simulcastURLParts, quality livekit.Vide
433456
opts = append(opts, lksdk.ReaderTrackWithFrameDuration(frameDuration))
434457
}
435458

459+
switch h26xStreamingFormat {
460+
case "annex-b":
461+
opts = append(opts, lksdk.ReaderTrackWithH26xStreamingFormat(lksdk.H26xStreamingFormatAnnexB))
462+
case "length-prefixed":
463+
opts = append(opts, lksdk.ReaderTrackWithH26xStreamingFormat(lksdk.H26xStreamingFormatLengthPrefixed))
464+
default:
465+
return nil, fmt.Errorf("unsupported h26x streaming format: %s", h26xStreamingFormat)
466+
}
467+
436468
// Configure simulcast layer
437469
opts = append(opts, lksdk.ReaderTrackWithSampleOptions(lksdk.WithSimulcast("simulcast", &livekit.VideoLayer{
438470
Quality: quality,
@@ -452,7 +484,7 @@ type simulcastLayer struct {
452484
}
453485

454486
// handleSimulcastPublish handles publishing multiple H.264 streams as a simulcast track
455-
func handleSimulcastPublish(room *lksdk.Room, urls []string, fps float64, onPublishComplete func(*lksdk.LocalTrackPublication)) error {
487+
func handleSimulcastPublish(room *lksdk.Room, urls []string, fps float64, h26xStreamingFormat string, onPublishComplete func(*lksdk.LocalTrackPublication)) error {
456488
// Parse all URLs
457489
var layers []simulcastLayer
458490
for _, url := range urls {
@@ -515,7 +547,7 @@ func handleSimulcastPublish(room *lksdk.Room, urls []string, fps float64, onPubl
515547
}
516548

517549
for _, layer := range layers {
518-
track, err := createSimulcastVideoTrack(layer.parts, layer.quality, fps, signalCompletion)
550+
track, err := createSimulcastVideoTrack(layer.parts, layer.quality, fps, h26xStreamingFormat, signalCompletion)
519551
if err != nil {
520552
// Clean up any tracks we've already created
521553
for _, t := range tracks {

cmd/lk/room.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ var (
172172
Name: "fps",
173173
Usage: "If video files are published, indicates `FPS` of video",
174174
},
175+
&cli.StringFlag{
176+
Name: "h26x-streaming-format",
177+
Usage: "Format to use when reading H.264 from file or socket, \"annex-b\" OR \"length-prefixed\"",
178+
Value: "annex-b",
179+
},
175180
&cli.BoolFlag{
176181
Name: "exit-after-publish",
177182
Usage: "When publishing, exit after file or stream is complete",
@@ -995,6 +1000,7 @@ func joinRoom(ctx context.Context, cmd *cli.Command) error {
9951000
if simulcastMode {
9961001
// Handle simulcast publishing
9971002
fps := cmd.Float("fps")
1003+
h26xStreamingFormat := cmd.String("h26x-streaming-format")
9981004
onPublishComplete := func(pub *lksdk.LocalTrackPublication) {
9991005
if exitAfterPublish {
10001006
close(done)
@@ -1006,12 +1012,13 @@ func joinRoom(ctx context.Context, cmd *cli.Command) error {
10061012
}
10071013
}
10081014

1009-
if err = handleSimulcastPublish(room, publishUrls, fps, onPublishComplete); err != nil {
1015+
if err = handleSimulcastPublish(room, publishUrls, fps, h26xStreamingFormat, onPublishComplete); err != nil {
10101016
return err
10111017
}
10121018
} else {
10131019
// Handle single publish
10141020
fps := cmd.Float("fps")
1021+
h26xStreamingFormat := cmd.String("h26x-streaming-format")
10151022
for _, pub := range publishUrls {
10161023
onPublishComplete := func(pub *lksdk.LocalTrackPublication) {
10171024
if exitAfterPublish {
@@ -1023,7 +1030,7 @@ func joinRoom(ctx context.Context, cmd *cli.Command) error {
10231030
_ = room.LocalParticipant.UnpublishTrack(pub.SID())
10241031
}
10251032
}
1026-
if err = handlePublish(room, pub, fps, onPublishComplete); err != nil {
1033+
if err = handlePublish(room, pub, fps, h26xStreamingFormat, onPublishComplete); err != nil {
10271034
return err
10281035
}
10291036
}

go.mod

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ require (
1212
github.com/go-logr/logr v1.4.3
1313
github.com/go-task/task/v3 v3.44.1
1414
github.com/joho/godotenv v1.5.1
15-
github.com/livekit/protocol v1.42.3-0.20251024111301-1e3becbff5d1
16-
github.com/livekit/server-sdk-go/v2 v2.12.7
15+
github.com/livekit/protocol v1.42.3-0.20251031205738-4e56a139a2c5
16+
github.com/livekit/server-sdk-go/v2 v2.12.8
1717
github.com/moby/patternmatcher v0.6.0
1818
github.com/pelletier/go-toml v1.9.5
19-
github.com/pion/rtcp v1.2.15
20-
github.com/pion/rtp v1.8.23
19+
github.com/pion/rtcp v1.2.16
20+
github.com/pion/rtp v1.8.25
2121
github.com/pion/webrtc/v4 v4.1.6
2222
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
2323
github.com/pkg/errors v0.9.1
@@ -36,7 +36,7 @@ require (
3636
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1 // indirect
3737
buf.build/go/protovalidate v1.0.0 // indirect
3838
buf.build/go/protoyaml v0.6.0 // indirect
39-
cel.dev/expr v0.24.0 // indirect
39+
cel.dev/expr v0.25.0 // indirect
4040
dario.cat/mergo v1.0.2 // indirect
4141
github.com/Ladicle/tabwriter v1.0.0 // indirect
4242
github.com/Microsoft/go-winio v0.6.2 // indirect
@@ -108,12 +108,12 @@ require (
108108
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
109109
github.com/jxskiss/base62 v1.1.0 // indirect
110110
github.com/kevinburke/ssh_config v1.2.0 // indirect
111-
github.com/klauspost/compress v1.18.0 // indirect
111+
github.com/klauspost/compress v1.18.1 // indirect
112112
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
113113
github.com/lithammer/shortuuid/v4 v4.2.0 // indirect
114114
github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731 // indirect
115-
github.com/livekit/mediatransportutil v0.0.0-20250825135402-7bc31f107ade // indirect
116-
github.com/livekit/psrpc v0.7.0 // indirect
115+
github.com/livekit/mediatransportutil v0.0.0-20250922175932-f537f0880397 // indirect
116+
github.com/livekit/psrpc v0.7.1-0.20251021235041-bdebea7dacf4 // indirect
117117
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
118118
github.com/magefile/mage v1.15.0 // indirect
119119
github.com/mattn/go-colorable v0.1.14 // indirect
@@ -144,9 +144,9 @@ require (
144144
github.com/pion/sctp v1.8.40 // indirect
145145
github.com/pion/sdp/v3 v3.0.16 // indirect
146146
github.com/pion/srtp/v3 v3.0.8 // indirect
147-
github.com/pion/stun/v3 v3.0.0 // indirect
147+
github.com/pion/stun/v3 v3.0.1 // indirect
148148
github.com/pion/transport/v3 v3.0.8 // indirect
149-
github.com/pion/turn/v4 v4.1.1 // indirect
149+
github.com/pion/turn/v4 v4.1.2 // indirect
150150
github.com/pjbgf/sha1cd v0.4.0 // indirect
151151
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
152152
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
@@ -155,7 +155,7 @@ require (
155155
github.com/prometheus/common v0.64.0 // indirect
156156
github.com/prometheus/procfs v0.16.1 // indirect
157157
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
158-
github.com/redis/go-redis/v9 v9.14.0 // indirect
158+
github.com/redis/go-redis/v9 v9.16.0 // indirect
159159
github.com/rivo/uniseg v0.4.7 // indirect
160160
github.com/sajari/fuzzy v1.0.0 // indirect
161161
github.com/secure-systems-lab/go-securesystemslib v0.6.0 // indirect
@@ -188,14 +188,14 @@ require (
188188
go.uber.org/zap v1.27.0 // indirect
189189
go.uber.org/zap/exp v0.3.0 // indirect
190190
golang.org/x/crypto v0.43.0 // indirect
191-
golang.org/x/exp v0.0.0-20251009144603-d2f985daa21b // indirect
191+
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
192192
golang.org/x/mod v0.29.0 // indirect
193193
golang.org/x/net v0.46.0 // indirect
194194
golang.org/x/sys v0.37.0 // indirect
195195
golang.org/x/term v0.36.0 // indirect
196196
golang.org/x/text v0.30.0 // indirect
197-
google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f // indirect
198-
google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f // indirect
197+
google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda // indirect
198+
google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect
199199
google.golang.org/grpc v1.76.0 // indirect
200200
gopkg.in/inf.v0 v0.9.1 // indirect
201201
gopkg.in/warnings.v0 v0.1.2 // indirect

0 commit comments

Comments
 (0)