Summary
When publishing an audio track created from a stereo AudioSource (numChannels=2), the Rust SDK never adds AudioTrackFeature::TfStereo to the AddTrackRequest.audio_features. This means the LiveKit server doesn't know the track is stereo, Opus defaults to mono encoding, and the subscriber receives mono audio duplicated to both channels.
Reproduction
- Create a stereo AudioSource:
AudioSource::new(48000, 2, 1000)
- Feed interleaved stereo PCM frames via
capture_frame()
- Publish the track to a room
- Subscribe from another participant
- Observe that received audio has identical L/R channels (mono downmixed)
Root cause
In livekit/src/room/participant/local_participant.rs, publish_track() only conditionally pushes TfPreconnectBuffer:
if options.preconnect_buffer {
req.audio_features.push(proto::AudioTrackFeature::TfPreconnectBuffer as i32);
}
It never inspects the audio source's num_channels to push TfStereo. The enum and conversion code exist (added in #634) but are never used for publishing.
Expected behavior
When a LocalAudioTrack is created from an AudioSource with num_channels >= 2, the SDK should automatically include AudioTrackFeature::TfStereo in the AddTrackRequest.audio_features so the server configures Opus for stereo encoding.
Alternatively, expose a stereo or audio_features field on TrackPublishOptions (similar to the JS SDK's forceStereo) so callers can explicitly opt in.
Environment
@livekit/rtc-node: 0.13.24 (wraps the Rust FFI layer)
- LiveKit server: Cloud (development)
- Use case: CT-e1 telephony middleware publishing separated customer/operator audio channels
Workaround
Publishing two separate mono tracks ("customer-audio", "operator-audio") instead of one stereo track.
Summary
When publishing an audio track created from a stereo
AudioSource(numChannels=2), the Rust SDK never addsAudioTrackFeature::TfStereoto theAddTrackRequest.audio_features. This means the LiveKit server doesn't know the track is stereo, Opus defaults to mono encoding, and the subscriber receives mono audio duplicated to both channels.Reproduction
AudioSource::new(48000, 2, 1000)capture_frame()Root cause
In
livekit/src/room/participant/local_participant.rs,publish_track()only conditionally pushesTfPreconnectBuffer:It never inspects the audio source's
num_channelsto pushTfStereo. The enum and conversion code exist (added in #634) but are never used for publishing.Expected behavior
When a
LocalAudioTrackis created from anAudioSourcewithnum_channels >= 2, the SDK should automatically includeAudioTrackFeature::TfStereoin theAddTrackRequest.audio_featuresso the server configures Opus for stereo encoding.Alternatively, expose a
stereooraudio_featuresfield onTrackPublishOptions(similar to the JS SDK'sforceStereo) so callers can explicitly opt in.Environment
@livekit/rtc-node: 0.13.24 (wraps the Rust FFI layer)Workaround
Publishing two separate mono tracks ("customer-audio", "operator-audio") instead of one stereo track.