Documentation
¶
Overview ¶
Package media is the RTP side of a call: G.711 audio sent from a shared scheduler, RFC 3550 receive statistics, RFC 4733 DTMF and detection of whether any audio arrives at all.
Index ¶
- Variables
- func AlawDecode(a byte) int16
- func AlawEncode(sample int16) byte
- func UlawDecode(u byte) int16
- func UlawEncode(sample int16) byte
- type Audio
- type Codec
- type Config
- type Direction
- type NetStats
- type Quality
- type Recording
- type Remote
- type Scheduler
- type Stats
- type Stream
- func (s *Stream) Answer(r Remote) ([]byte, error)
- func (s *Stream) ApplyAnswer(r Remote) error
- func (s *Stream) Close() Stats
- func (s *Stream) Codec() string
- func (s *Stream) Digits() string
- func (s *Stream) Direction() Direction
- func (s *Stream) Offer(dir Direction) []byte
- func (s *Stream) Port() int
- func (s *Stream) Recording() (Recording, bool)
- func (s *Stream) SendDTMF(digits string, dur time.Duration) error
- func (s *Stream) SetDirection(d Direction)
- func (s *Stream) Start()
- func (s *Stream) Stats() Stats
- func (s *Stream) Update(r Remote) []byte
- func (s *Stream) WaitDigits(want string, timeout time.Duration) bool
- func (s *Stream) WaitHeard(timeout time.Duration) bool
Constants ¶
This section is empty.
Variables ¶
var ( PCMU = Codec{Name: "PCMU", PT: 0, /* contains filtered or unexported fields */} PCMA = Codec{Name: "PCMA", PT: 8, /* contains filtered or unexported fields */} )
var DefaultAudio = sync.OnceValue(func() *Audio { return Tone(1000, -20, time.Second) })
DefaultAudio is what calls send unless told otherwise: a 1 kHz tone at -20 dBFS, so the far end can tell that audio arrives.
Functions ¶
func AlawDecode ¶
func AlawEncode ¶
AlawEncode converts a 16-bit linear sample to A-law.
func UlawDecode ¶
UlawDecode and AlawDecode convert one G.711 byte to a linear sample.
func UlawEncode ¶
UlawEncode converts a 16-bit linear sample to μ-law.
Types ¶
type Audio ¶
type Audio struct {
// contains filtered or unexported fields
}
Audio is an 8 kHz mono source that streams loop over. It is encoded once per codec and shared read-only by all streams, so thousands of calls cost no encoding CPU.
type Codec ¶
type Codec struct {
Name string // as in rtpmap: PCMU, PCMA
PT uint8 // static payload type
// contains filtered or unexported fields
}
Codec is an audio codec we can send and analyse. Only 8 kHz G.711 for now.
func CodecByName ¶
CodecByName accepts "PCMU"/"PCMA" and the common aliases "ulaw"/"alaw".
func ParseCodecs ¶
ParseCodecs parses a preference list like "PCMA,PCMU".
type Config ¶
type Config struct {
IP string // local address for the socket and the SDP
Codecs []Codec // preference order; default PCMU, PCMA
Audio *Audio // what we send; default DefaultAudio()
Scheduler *Scheduler
// HeardLevel is the level in dBFS above which a received frame counts
// as audio; default -45.
HeardLevel float64
// NoLatch disables symmetric RTP: by default we send to where the
// peer's packets come from once the first one arrives (NAT, SBCs).
NoLatch bool
// Record keeps the heard and sent audio for Recording().
Record bool
}
type NetStats ¶ added in v0.4.0
NetStats are traffic counters of all RTP sockets of the process.
func RTPNetStats ¶ added in v0.4.0
func RTPNetStats() NetStats
RTPNetStats returns the RTP traffic of the process so far, including packets that were not RTP (RTCP, STUN) on the media sockets.
type Quality ¶ added in v0.4.0
type Quality struct {
// Score is the similarity of the heard audio to the reference, 0..1:
// the correlation of their telephone-band spectrograms after alignment.
// It ignores the level; drop-outs, noise, distortion and wrong audio
// lower it.
Score float64
// Offset is where the reference starts in the recording.
Offset time.Duration
// Compared is the length of the reference that was compared: shorter
// than the reference when the recording ends early.
Compared time.Duration
// Gaps is the reference speech during which nothing was heard.
Gaps time.Duration
// ClippedStart is the part of the first word that was lost: gaps from
// the start of the reference speech until audio is first heard.
ClippedStart time.Duration
// Gain is the level of the heard audio relative to the reference, dB.
Gain float64
}
Quality compares what a call leg heard with the reference audio that should have arrived.
type Recording ¶ added in v0.4.0
type Recording struct {
Heard []int16 // received audio, what the subscriber hears
Sent []int16 // our audio, what the subscriber says
}
Recording is a copy of what a call leg heard and sent.
type Remote ¶
type Remote struct {
Addr *net.UDPAddr // nil or unspecified IP means hold
Codecs []Codec // supported codecs in the peer's order
DTMFPT int // telephone-event payload type, -1 if not offered
Dir Direction
}
Remote is what we learnt from the peer's SDP.
type Scheduler ¶
type Scheduler struct {
// contains filtered or unexported fields
}
Scheduler paces all sending streams from a few goroutines instead of one ticker per stream: with thousands of calls, per-stream tickers make the generator itself produce jitter. Streams are spread over shards; each shard ticks every 20 ms and sends one packet per stream.
func NewScheduler ¶
NewScheduler starts n shards; n <= 0 means GOMAXPROCS.
type Stats ¶
type Stats struct {
Codec string
PacketsSent uint64
PacketsReceived uint64
PacketsExpected uint64
PacketsLost uint64
Jitter time.Duration
Heard time.Duration // time of received audio above HeardLevel
DTMF string // RFC 4733 digits received
}
Stats summarise one stream. Loss and jitter follow RFC 3550.
type Stream ¶
type Stream struct {
// contains filtered or unexported fields
}
func New ¶
New opens the RTP socket and starts receiving right away, so early media and the first packets after 200 OK are counted.
func (*Stream) ApplyAnswer ¶
ApplyAnswer takes the peer's answer to our offer.
func (*Stream) Recording ¶ added in v0.4.0
Recording returns a copy of the recorded audio so far; ok is false when the stream was created without Record.
func (*Stream) SendDTMF ¶
SendDTMF queues RFC 4733 events; each digit lasts dur (default 100 ms) followed by a 60 ms pause. It returns once queued.
func (*Stream) SetDirection ¶
SetDirection changes what we send/receive, e.g. sendonly for hold.
func (*Stream) Start ¶
func (s *Stream) Start()
Start begins sending (when our direction allows it).
func (*Stream) Update ¶
Update applies an in-dialog offer (re-INVITE, e.g. hold) and returns our answer, keeping the negotiated codec.
func (*Stream) WaitDigits ¶
WaitDigits waits until the received digits contain want.