fix: configure Opus encoder bitrate from available bandwidth
Replace SetBitrateToMax() with dynamic bitrate configuration based on the per-frame byte budget (AudioDataBytes). Previously, the encoder always targeted maximum bitrate (~510 kbps) and relied on output truncation when frames exceeded the available bandwidth. This could produce truncated/invalid Opus frames when the server's max bandwidth is lower than the encoder's target. The bitrate is now recalculated on every Encode() call as: maxDataBytes * 8 * 100 (bits per second for 10ms frames) This ensures the encoder produces frames that fit within the byte budget without truncation.
This commit is contained in:
committed by
Brandon McGinty
parent
679127bcf1
commit
5c1cd69d65
+9
-4
@@ -29,9 +29,8 @@ func (*generator) ID() int {
|
|||||||
func (*generator) NewEncoder() gumble.AudioEncoder {
|
func (*generator) NewEncoder() gumble.AudioEncoder {
|
||||||
// Force mono for voice transmission
|
// Force mono for voice transmission
|
||||||
e, _ := opus.NewEncoder(gumble.AudioSampleRate, VoiceChannels, opus.AppVoIP)
|
e, _ := opus.NewEncoder(gumble.AudioSampleRate, VoiceChannels, opus.AppVoIP)
|
||||||
_ = e.SetBitrateToMax()
|
|
||||||
return &Encoder{
|
return &Encoder{
|
||||||
e,
|
Encoder: e,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,9 +38,8 @@ func (*generator) NewEncoder() gumble.AudioEncoder {
|
|||||||
func NewStereoEncoder() gumble.AudioEncoder {
|
func NewStereoEncoder() gumble.AudioEncoder {
|
||||||
// Create stereo encoder for file playback
|
// Create stereo encoder for file playback
|
||||||
e, _ := opus.NewEncoder(gumble.AudioSampleRate, gumble.AudioChannels, opus.AppAudio)
|
e, _ := opus.NewEncoder(gumble.AudioSampleRate, gumble.AudioChannels, opus.AppAudio)
|
||||||
_ = e.SetBitrateToMax()
|
|
||||||
return &Encoder{
|
return &Encoder{
|
||||||
e,
|
Encoder: e,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +63,13 @@ func (*Encoder) ID() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) Encode(pcm []int16, _, maxDataBytes int) ([]byte, error) {
|
func (e *Encoder) Encode(pcm []int16, _, maxDataBytes int) ([]byte, error) {
|
||||||
|
// Set the encoder bitrate to match the available bandwidth per frame.
|
||||||
|
// The bitrate is: maxDataBytes * 8 (bits per byte) * 100 (10ms frames per second).
|
||||||
|
// Opus encodes best when the bitrate target is set properly rather than
|
||||||
|
// relying on truncation, which can produce incomplete or corrupt frames.
|
||||||
|
bitrate := maxDataBytes * 8 * 100
|
||||||
|
_ = e.Encoder.SetBitrate(bitrate)
|
||||||
|
|
||||||
buf := make([]byte, maxDataBytes)
|
buf := make([]byte, maxDataBytes)
|
||||||
n, err := e.Encoder.Encode(pcm, buf)
|
n, err := e.Encoder.Encode(pcm, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user