From 07196ac910de6f11eddf1f41daf3d9345d813386 Mon Sep 17 00:00:00 2001 From: Till Hoffmann Date: Thu, 2 Jul 2026 16:45:10 +0200 Subject: [PATCH 1/3] feat: register Opus codec in media-sdk opus package Mirrors the g711/g722/dtmf pattern: an init() in the codec's own package calls RegisterCodec so importers get the codec registered by side-effect. Opus is registered Disabled:true (opt-in) since SIP infrastructure interoperability varies; callers enable it via msdk.CodecSetEnabled. Co-Authored-By: Claude Sonnet 4.6 --- opus/codec.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 opus/codec.go diff --git a/opus/codec.go b/opus/codec.go new file mode 100644 index 0000000..2d61e11 --- /dev/null +++ b/opus/codec.go @@ -0,0 +1,49 @@ +// Copyright 2024 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build cgo + +package opus + +import ( + "github.com/livekit/protocol/logger" + + media "github.com/livekit/media-sdk" +) + +const SDPName = "opus/48000/2" + +func init() { + media.RegisterCodec(media.NewAudioCodec(media.CodecInfo{ + SDPName: SDPName, + SampleRate: 48000, + RTPClockRate: 48000, + RTPIsStatic: false, + Priority: 10, + Disabled: true, + FileExt: "opus", + }, func(w media.PCM16Writer) media.WriteCloser[Sample] { + dec, err := Decode(w, 1, logger.GetLogger()) + if err != nil { + return nil + } + return dec + }, func(w media.WriteCloser[Sample]) media.PCM16Writer { + enc, err := Encode(w, 1, logger.GetLogger()) + if err != nil { + return nil + } + return enc + })) +} From 4d6bc9acac55fc164ddd93f97418de30dcdfd93b Mon Sep 17 00:00:00 2001 From: Till Hoffmann Date: Fri, 3 Jul 2026 13:22:42 +0200 Subject: [PATCH 2/3] feat(opus): add EncodeWith and EncodeOptions for configurable encoder Co-Authored-By: Claude Sonnet 4.6 --- opus/opus.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/opus/opus.go b/opus/opus.go index b0dfb0a..78fbcc5 100644 --- a/opus/opus.go +++ b/opus/opus.go @@ -64,11 +64,47 @@ func Decode(w media.PCM16Writer, targetChannels int, logger logger.Logger) (Writ }, nil } +// EncodeOptions tunes the Opus encoder. Zero values keep libopus defaults. +type EncodeOptions struct { + // Bitrate is the target encoder bitrate in bits/sec (e.g. 24000). 0 = auto. + Bitrate int + // Complexity is the encoder computational complexity 1-10. 0 = default. + Complexity int + // FEC enables in-band Forward Error Correction. + FEC bool + // PacketLossPercent is the expected packet loss 0-100, used to tune FEC. + PacketLossPercent int +} + func Encode(w Writer, channels int, logger logger.Logger) (media.PCM16Writer, error) { + return EncodeWith(w, channels, EncodeOptions{}, logger) +} + +func EncodeWith(w Writer, channels int, opts EncodeOptions, logger logger.Logger) (media.PCM16Writer, error) { enc, err := opus.NewEncoder(w.SampleRate(), channels, opus.AppVoIP) if err != nil { return nil, err } + if opts.Bitrate > 0 { + if err = enc.SetBitrate(opts.Bitrate); err != nil { + return nil, fmt.Errorf("opus set bitrate: %w", err) + } + } + if opts.Complexity > 0 { + if err = enc.SetComplexity(opts.Complexity); err != nil { + return nil, fmt.Errorf("opus set complexity: %w", err) + } + } + if opts.FEC { + if err = enc.SetInBandFEC(true); err != nil { + return nil, fmt.Errorf("opus set fec: %w", err) + } + if opts.PacketLossPercent > 0 { + if err = enc.SetPacketLossPerc(opts.PacketLossPercent); err != nil { + return nil, fmt.Errorf("opus set packet loss: %w", err) + } + } + } return &encoder{ w: w, enc: enc, From 31b2466c74f028a912ed9e43bad68f33a81eb154 Mon Sep 17 00:00:00 2001 From: Dean Bloembergen Date: Fri, 28 Aug 2026 14:30:46 -0700 Subject: [PATCH 3/3] fix(opus): address codec registration review --- opus/codec.go | 13 ++++++------- opus/opus.go | 2 ++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/opus/codec.go b/opus/codec.go index 2d61e11..c0ac9e7 100644 --- a/opus/codec.go +++ b/opus/codec.go @@ -26,13 +26,12 @@ const SDPName = "opus/48000/2" func init() { media.RegisterCodec(media.NewAudioCodec(media.CodecInfo{ - SDPName: SDPName, - SampleRate: 48000, - RTPClockRate: 48000, - RTPIsStatic: false, - Priority: 10, - Disabled: true, - FileExt: "opus", + SDPName: SDPName, + SampleRate: 48000, + RTPIsStatic: false, + Priority: 10, + Disabled: true, + FileExt: "opus", }, func(w media.PCM16Writer) media.WriteCloser[Sample] { dec, err := Decode(w, 1, logger.GetLogger()) if err != nil { diff --git a/opus/opus.go b/opus/opus.go index 78fbcc5..c1a1b41 100644 --- a/opus/opus.go +++ b/opus/opus.go @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build cgo + package opus import (