Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions autocomplete/fish_autocomplete
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ complete -c lk -n '__fish_seen_subcommand_from room; and __fish_seen_subcommand_
complete -c lk -n '__fish_seen_subcommand_from room; and __fish_seen_subcommand_from join' -f -l open -r -d 'Open relevant `APP` in browser, supported options: [meet console]'
complete -c lk -n '__fish_seen_subcommand_from room; and __fish_seen_subcommand_from join' -f -l publish-demo -d 'Publish demo video as a loop'
complete -c lk -n '__fish_seen_subcommand_from room; and __fish_seen_subcommand_from join' -l publish -r -d '`FILES` to publish as tracks to room (supports .h264, .ivf, .ogg). Can be used multiple times to publish multiple files. Can publish from Unix or TCP socket using the format \'<codec>:///<socket_path>\' or \'<codec>://<host:port>\' respectively. Valid codecs are "h264", "h265", "vp8", "opus". For simulcast: use 2-3 h264:// or h265:// URLs with format \'<codec>://<host:port>/<width>x<height>\' or \'<codec>:///path/to/<socket_path>/<width>x<height>\' (all layers must use the same codec; quality determined by width order)'
complete -c lk -n '__fish_seen_subcommand_from room; and __fish_seen_subcommand_from join' -f -l track-name -r -d '`NAME` of the published track. Applies to all tracks published via --publish. If unset, file tracks are named after the file and socket tracks are unnamed'
complete -c lk -n '__fish_seen_subcommand_from room; and __fish_seen_subcommand_from join' -f -l publish-data -r -d 'Publish user data to the room.'
complete -c lk -n '__fish_seen_subcommand_from room; and __fish_seen_subcommand_from join' -f -l publish-dtmf -r -d 'Publish DTMF digits to the room. Character \'w\' adds 0.5 sec delay.'
complete -c lk -n '__fish_seen_subcommand_from room; and __fish_seen_subcommand_from join' -f -l fps -r -d 'If video files are published, indicates `FPS` of video'
Expand Down
45 changes: 26 additions & 19 deletions cmd/lk/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func _deprecatedJoinRoom(ctx context.Context, cmd *cli.Command) error {
_ = room.LocalParticipant.UnpublishTrack(pub.SID())
}
}
if err = handlePublish(room, pub, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete); err != nil {
if err = handlePublish(room, pub, "", fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete); err != nil {
return err
}
}
Expand All @@ -200,6 +200,7 @@ func _deprecatedJoinRoom(ctx context.Context, cmd *cli.Command) error {

func handlePublish(room *lksdk.Room,
name string,
trackName string,
fps float64,
h26xStreamingFormat string,
attachFrameMetadata bool,
Expand All @@ -210,9 +211,23 @@ func handlePublish(room *lksdk.Room,
if err != nil {
return err
}
return publishSocket(room, mimeType, socketType, address, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete)
return publishSocket(room, mimeType, socketType, address, trackName, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete)
}
return publishFile(room, name, trackName, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete)
}

// trackPublicationOptions builds publish options, preferring the user-provided
// track name over the per-source default.
func trackPublicationOptions(trackName, defaultName string, attachFrameMetadata bool) *lksdk.TrackPublicationOptions {
name := defaultName
if trackName != "" {
name = trackName
}
return &lksdk.TrackPublicationOptions{
Name: name,
AttachUserTimestamp: attachFrameMetadata,
AttachFrameId: attachFrameMetadata,
}
return publishFile(room, name, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete)
}

func publishDemo(room *lksdk.Room) error {
Expand Down Expand Up @@ -243,6 +258,7 @@ func publishDemo(room *lksdk.Room) error {

func publishFile(room *lksdk.Room,
filename string,
trackName string,
fps float64,
h26xStreamingFormat string,
attachFrameMetadata bool,
Expand Down Expand Up @@ -290,11 +306,7 @@ func publishFile(room *lksdk.Room,
if err != nil {
return err
}
pub, err = room.LocalParticipant.PublishTrack(track, &lksdk.TrackPublicationOptions{
Name: filename,
AttachUserTimestamp: attachFrameMetadata,
AttachFrameId: attachFrameMetadata,
})
pub, err = room.LocalParticipant.PublishTrack(track, trackPublicationOptions(trackName, filename, attachFrameMetadata))
return err
}

Expand Down Expand Up @@ -336,6 +348,7 @@ func publishSocket(room *lksdk.Room,
mimeType string,
socketType string,
address string,
trackName string,
fps float64,
h26xStreamingFormat string,
attachFrameMetadata bool,
Expand All @@ -362,13 +375,14 @@ func publishSocket(room *lksdk.Room,
}

// Publish to room
err = publishReader(room, sock, mime, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete)
err = publishReader(room, sock, mime, trackName, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete)
return err
}

func publishReader(room *lksdk.Room,
in io.ReadCloser,
mime string,
trackName string,
fps float64,
h26xStreamingFormat string,
attachFrameMetadata bool,
Expand Down Expand Up @@ -409,10 +423,7 @@ func publishReader(room *lksdk.Room,
if err != nil {
return err
}
pub, err = room.LocalParticipant.PublishTrack(track, &lksdk.TrackPublicationOptions{
AttachUserTimestamp: attachFrameMetadata,
AttachFrameId: attachFrameMetadata,
})
pub, err = room.LocalParticipant.PublishTrack(track, trackPublicationOptions(trackName, "", attachFrameMetadata))
if err != nil {
return err
}
Expand Down Expand Up @@ -519,7 +530,7 @@ type simulcastLayer struct {
}

// handleSimulcastPublish handles publishing multiple H.264 streams as a simulcast track
func handleSimulcastPublish(room *lksdk.Room, urls []string, fps float64, h26xStreamingFormat string, attachFrameMetadata bool, onPublishComplete func(*lksdk.LocalTrackPublication)) error {
func handleSimulcastPublish(room *lksdk.Room, urls []string, trackName string, fps float64, h26xStreamingFormat string, attachFrameMetadata bool, onPublishComplete func(*lksdk.LocalTrackPublication)) error {
// Parse all URLs
var layers []simulcastLayer
for _, url := range urls {
Expand Down Expand Up @@ -605,11 +616,7 @@ func handleSimulcastPublish(room *lksdk.Room, urls []string, fps float64, h26xSt

// Publish simulcast track
var err error
pub, err = room.LocalParticipant.PublishSimulcastTrack(tracks, &lksdk.TrackPublicationOptions{
Name: "simulcast",
AttachUserTimestamp: attachFrameMetadata,
AttachFrameId: attachFrameMetadata,
})
pub, err = room.LocalParticipant.PublishSimulcastTrack(tracks, trackPublicationOptions(trackName, "simulcast", attachFrameMetadata))
if err != nil {
// Clean up tracks on publish failure
for _, track := range tracks {
Expand Down
21 changes: 21 additions & 0 deletions cmd/lk/join_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,27 @@ func TestParseSocketString(t *testing.T) {
assert.Equal(t, err, nil, "Expected no error for valid vp8 TCP socket")
}

func TestTrackPublicationOptions(t *testing.T) {
// Default name is used when no override is given
opts := trackPublicationOptions("", "video.h264", false)
assert.Equal(t, "video.h264", opts.Name)
assert.False(t, opts.AttachUserTimestamp)
assert.False(t, opts.AttachFrameId)

// Override takes precedence over the default name
opts = trackPublicationOptions("camera-main", "video.h264", false)
assert.Equal(t, "camera-main", opts.Name)

// Socket publishes have no default name unless overridden
opts = trackPublicationOptions("", "", false)
assert.Equal(t, "", opts.Name)

opts = trackPublicationOptions("screen-share", "", true)
assert.Equal(t, "screen-share", opts.Name)
assert.True(t, opts.AttachUserTimestamp)
assert.True(t, opts.AttachFrameId)
}

func TestParseSimulcastURL(t *testing.T) {
// Test TCP format
parts, err := parseSimulcastURL("h264://localhost:8080/640x480")
Expand Down
10 changes: 8 additions & 2 deletions cmd/lk/room.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ var (
"Can publish from Unix or TCP socket using the format '<codec>:///<socket_path>' or '<codec>://<host:port>' respectively. Valid codecs are \"h264\", \"h265\", \"vp8\", \"opus\". " +
"For simulcast: use 2-3 h264:// or h265:// URLs with format '<codec>://<host:port>/<width>x<height>' or '<codec>:///path/to/<socket_path>/<width>x<height>' (all layers must use the same codec; quality determined by width order)",
},
&cli.StringFlag{
Name: "track-name",
Usage: "`NAME` of the published track. Applies to all tracks published via --publish. " +
"If unset, file tracks are named after the file and socket tracks are unnamed",
},
&cli.StringFlag{
Name: "publish-data",
Usage: "Publish user data to the room.",
Expand Down Expand Up @@ -996,6 +1001,7 @@ func joinRoom(ctx context.Context, cmd *cli.Command) error {

// Handle publishing
if len(publishUrls) > 0 {
trackName := cmd.String("track-name")
if simulcastMode {
// Handle simulcast publishing
fps := cmd.Float("fps")
Expand All @@ -1011,7 +1017,7 @@ func joinRoom(ctx context.Context, cmd *cli.Command) error {
}
}

if err = handleSimulcastPublish(room, publishUrls, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete); err != nil {
if err = handleSimulcastPublish(room, publishUrls, trackName, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete); err != nil {
return err
}
} else {
Expand All @@ -1029,7 +1035,7 @@ func joinRoom(ctx context.Context, cmd *cli.Command) error {
_ = room.LocalParticipant.UnpublishTrack(pub.SID())
}
}
if err = handlePublish(room, pub, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete); err != nil {
if err = handlePublish(room, pub, trackName, fps, h26xStreamingFormat, attachFrameMetadata, onPublishComplete); err != nil {
return err
}
}
Expand Down
Loading