rtc

package
v0.0.0-...-e1adb0e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 15, 2026 License: BSD-3-Clause Imports: 20 Imported by: 0

Documentation

Overview

Package rtc connects the audio package to WebRTC tracks.

TrackWriter takes PCM and publishes it: it implements track.AudioSampleProvider, so it plugs straight into track.NewAudioTrack. TrackReader does the reverse, turning a remote track's RTP into PCM.

Between them a voice agent needs no codec or RTP code of its own: write what the text-to-speech engine produced, read what the participant said.

Index

Constants

View Source
const DefaultBufferDuration = 30 * time.Second

DefaultBufferDuration is how much encoded audio a TrackWriter holds before it starts dropping the oldest. It is generous because a text-to-speech engine commonly produces a whole sentence faster than real time.

View Source
const DefaultMaxConceal = 500 * time.Millisecond

DefaultMaxConceal caps how long a run of lost packets is concealed before the reader gives up and resynchronises. Beyond a few hundred milliseconds concealment stops sounding like the speaker and starts sounding like a fault, and the sender has probably stopped rather than been dropped.

View Source
const OpusClockRate = 48000

OpusClockRate is the RTP clock rate for Opus. RFC 7587 fixes it at 48 kHz regardless of the rate the codec is actually running at internally.

Variables

This section is empty.

Functions

func NewAudioTrack

func NewAudioTrack(trackInfo *sfu_models.TrackInfo, w *TrackWriter, opts ...track.Option) (*track.Local, error)

NewAudioTrack builds a local audio track fed by w, wiring up the Opus codec parameters so the caller does not have to restate them.

Types

type RTPSource

type RTPSource interface {
	ReadRTP() (*rtp.Packet, interceptor.Attributes, error)
}

RTPSource is the part of webrtc.TrackRemote a TrackReader uses. Taking an interface lets a reader run over a recorded stream or a test fixture as well as a live track.

type ReaderConfig

type ReaderConfig struct {
	// Opus configures the decoder. Its zero value is 48 kHz mono at 20 ms.
	// Set SampleRate to what your consumer wants, typically 16000 for speech
	// recognition, and the decoder produces it directly instead of making you
	// resample afterwards.
	Opus opus.Config
	// DisableConcealment stops the reader from synthesising audio for lost
	// packets. By default a gap in sequence numbers is filled in, which keeps
	// the output continuous and lets the decoder fade rather than click.
	DisableConcealment bool
	// MaxConceal caps a run of concealed audio. Defaults to
	// [DefaultMaxConceal].
	MaxConceal time.Duration
}

ReaderConfig configures a TrackReader. The zero value decodes to 48 kHz mono with concealment enabled.

type TrackReader

type TrackReader struct {
	// contains filtered or unexported fields
}

TrackReader turns a remote WebRTC audio track into PCM.

It reads RTP, unwraps redundancy when the track carries it, decodes Opus, and fills gaps left by lost packets. TrackReader.Read returns one buffer per call; TrackReader.Frames wraps it as an iterator for a range loop.

A TrackReader is not safe for concurrent use. Run one per track, which is the natural shape anyway since each track arrives on its own callback.

func NewRTPReader

func NewRTPReader(src RTPSource, codec webrtc.RTPCodecCapability, cfg ReaderConfig) (*TrackReader, error)

NewRTPReader returns a reader over any source of Opus RTP packets. codec says what the packets carry, which decides whether they need unwrapping from RED and what clock rate their timestamps use.

func NewTrackReader

func NewTrackReader(remote *webrtc.TrackRemote, cfg ReaderConfig) (*TrackReader, error)

NewTrackReader returns a reader for a remote audio track.

The track comes from the OnTrack callback the SDK invokes when a subscription is established; pass its Track field.

func (*TrackReader) Close

func (r *TrackReader) Close() error

Close releases the reader. The remote track itself is owned by the SDK and is not closed here.

func (*TrackReader) Frames

func (r *TrackReader) Frames() iter.Seq2[audio.PCM, error]

Frames iterates decoded audio until the track ends. The loop stops on the first error; io.EOF is reported as the end of the stream rather than as an error, so a clean shutdown yields no error at all.

func (*TrackReader) Read

func (r *TrackReader) Read() (audio.PCM, error)

Read returns the next buffer of decoded audio. It blocks until a packet arrives, and returns io.EOF once the track has ended.

type TrackWriter

type TrackWriter struct {
	track.BaseSampleProvider
	// contains filtered or unexported fields
}

TrackWriter publishes PCM to a WebRTC audio track.

Call TrackWriter.Write with audio at any sample rate, channel count and format; it is resampled, encoded and queued. The track pulls packets off the queue in real time, so Write never blocks on the network.

When the queue runs dry the writer emits encoded silence rather than stalling, which keeps the RTP timeline continuous. That matters: a receiver that sees a gap in timestamps treats it as loss and starts concealing.

A TrackWriter is safe for concurrent use.

func NewTrackWriter

func NewTrackWriter(cfg WriterConfig) (*TrackWriter, error)

NewTrackWriter returns a writer for cfg.

func (*TrackWriter) Buffered

func (w *TrackWriter) Buffered() time.Duration

Buffered is how much encoded audio is waiting to be sent.

func (*TrackWriter) Clear

func (w *TrackWriter) Clear()

Clear drops everything queued and resets the encoder.

This is barge-in: when a participant interrupts the agent, whatever it was about to say has to stop immediately, and a buffer holding several seconds of speech would otherwise keep playing.

func (*TrackWriter) Close

func (w *TrackWriter) Close() error

Close stops the track's write loop. Queued audio is discarded.

func (*TrackWriter) Codec

Codec is the RTP codec capability this writer produces, ready to hand to track.NewAudioTrack. RFC 7587 signals Opus as opus/48000/2 whatever the encoder's channel count, and a mono stream is a valid stream of that codec, so the capability always says two channels: anything else fails to bind to the codec every peer negotiates.

func (*TrackWriter) CurrentAudioLevel

func (w *TrackWriter) CurrentAudioLevel() uint8

CurrentAudioLevel implements track.AudioSampleProvider. It reports the loudness of the packet most recently handed to the track, on the WebRTC scale where 0 is full scale and 127 is silence.

func (*TrackWriter) Flush

func (w *TrackWriter) Flush() error

Flush pushes out the partial frame the encoder is holding, padded with silence. Call it when a source has finished, so its last few milliseconds are not left waiting for audio that will never come.

func (*TrackWriter) NextSample

func (w *TrackWriter) NextSample(ctx context.Context) (media.Sample, error)

NextSample implements track.SampleProvider. The track calls it on its own goroutine and paces the calls off the returned duration, so it returns immediately with silence rather than waiting for audio to arrive.

func (*TrackWriter) Write

func (w *TrackWriter) Write(pcm audio.PCM) error

Write encodes pcm and queues it for sending. It returns as soon as the audio is queued, not when it has been sent.

Audio that does not fill a whole frame stays in the encoder until the next call. Use TrackWriter.Flush at the end of an utterance to push it out.

type WriterConfig

type WriterConfig struct {
	// Opus configures the encoder. Its zero value is 48 kHz mono at 20 ms,
	// sent as the opus/48000/2 codec that WebRTC negotiates.
	Opus opus.Config
	// BufferDuration caps how much encoded audio is queued. Once it is
	// exceeded the oldest audio is dropped, which bounds both memory and the
	// delay between writing a sample and hearing it. Defaults to
	// [DefaultBufferDuration].
	BufferDuration time.Duration
}

WriterConfig configures a TrackWriter. The zero value is a working 48 kHz mono voice configuration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址