Documentation
¶
Overview ¶
Package broadcast streams completed trunked-radio calls to external call aggregators — Broadcastify Calls, RdioScanner, OpenMHz — and to live Icecast/ShoutCast audio servers.
The Manager subscribes to events.KindCallComplete (published by the recorder once a call's WAV is flushed to disk), resolves which backends want the call, encodes the audio to MP3 once, and dispatches it to each backend with bounded exponential-backoff retry. A call is skipped entirely when its talkgroup is flagged Stream=false or when it is shorter than the configured minimum duration.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Backend ¶
type Backend interface {
// Name is a short stable identifier used in logs and stats.
Name() string
// Accepts reports whether this backend wants calls from the named
// trunking system. An unfiltered backend accepts every system.
Accepts(systemName string) bool
// Send delivers the call. A non-nil error triggers a retry.
Send(ctx context.Context, c *Call) error
}
Backend is one outbound streaming destination. Implementations must be safe for concurrent Send calls — the Manager runs several upload workers. Send should treat a retry as a fresh attempt; the Manager handles backoff between attempts.
func NewBroadcastify ¶
func NewBroadcastify(cfg BroadcastifyConfig, hc *http.Client) (Backend, error)
NewBroadcastify builds a Broadcastify Calls backend.
func NewIcecast ¶
func NewIcecast(cfg IcecastConfig, log *slog.Logger) (Backend, error)
NewIcecast builds a live Icecast/ShoutCast streaming backend and starts its background source connection.
func NewOpenMHz ¶
func NewOpenMHz(cfg OpenMHzConfig, hc *http.Client) (Backend, error)
NewOpenMHz builds an OpenMHz upload backend.
func NewRdioScanner ¶
func NewRdioScanner(cfg RdioScannerConfig, hc *http.Client) (Backend, error)
NewRdioScanner builds an RdioScanner call-upload backend.
type BroadcastifyConfig ¶
type BroadcastifyConfig struct {
// Name is an optional label used in logs; defaults to
// "broadcastify".
Name string
// APIKey is the Broadcastify Calls API key for the system.
APIKey string
// SystemID is the numeric Broadcastify Calls system ID.
SystemID int
// Systems restricts the feed to these trunking-system names.
// Empty streams every system.
Systems []string
// Endpoint overrides the upload API URL (tests). Empty uses the
// production endpoint.
Endpoint string
}
BroadcastifyConfig configures one Broadcastify Calls feed.
type Call ¶
type Call struct {
System string
Protocol string
Talkgroup uint32
TalkgroupLabel string
Source uint32
FrequencyHz uint32
Encrypted bool
// AlgorithmID / KeyID surface the P25 encryption parameters when
// the in-call signalling has revealed them. Zero on clear calls
// and on encrypted calls whose Encryption Sync never arrived
// before the call ended. Aggregators that accept the fields can
// thread them into their API payload; aggregators that don't will
// just ignore them.
AlgorithmID uint8
KeyID uint16
Emergency bool
PatchedGroups []uint32
StartedAt time.Time
EndedAt time.Time
AudioPath string // .wav on disk written by the recorder
SampleRate int
// contains filtered or unexported fields
}
Call is a completed call queued for outbound streaming. It carries the call metadata plus a lazy MP3 accessor — the WAV on AudioPath is encoded to MP3 at most once regardless of how many backends consume it.
type IcecastConfig ¶
type IcecastConfig struct {
// Name is an optional log label; defaults to "icecast".
Name string
// Host and Port address the Icecast server.
Host string
Port int
// Mount is the mountpoint path (e.g. "/gophertrunk"). A leading
// slash is added when missing.
Mount string
// Username is the source username; defaults to "source".
Username string
// Password is the source password.
Password string
// StreamName is advertised to listeners via the Ice-Name header.
StreamName string
// SampleRate is the PCM rate used to synthesise inter-call
// silence; defaults to 8000.
SampleRate int
// Systems restricts the feed to these trunking-system names.
// Empty streams every system.
Systems []string
}
IcecastConfig configures one live Icecast/ShoutCast feed.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager fans completed calls out to the configured backends.
func NewManager ¶
NewManager validates opts and returns a Manager that has already subscribed to the bus (so calls completed before Run starts are not lost). The caller must invoke Run and, on shutdown, Close.
func (*Manager) Close ¶
Close releases the bus subscription, waits for Run to drain, then stops the upload workers. Safe to call multiple times.
func (*Manager) Run ¶
Run drains KindCallComplete events until ctx is cancelled or the bus subscription closes.
type NormalizeConfig ¶ added in v0.4.0
type NormalizeConfig struct {
Enabled bool
Params loudness.NormalizeParams
}
NormalizeConfig configures optional loudness normalization of the distributed MP3 copy. When Enabled, the WAV on disk is left untouched and the gain is applied in memory before MP3 encoding. Params are assumed to already carry defaults (see loudness.NormalizeParams).
type OpenMHzConfig ¶
type OpenMHzConfig struct {
// Name is an optional log label; defaults to "openmhz".
Name string
// APIKey is the OpenMHz system API key.
APIKey string
// ShortName is the OpenMHz system short name (the path segment in
// the upload URL).
ShortName string
// Systems restricts the feed to these trunking-system names.
// Empty streams every system.
Systems []string
// Endpoint overrides the API base URL (tests). Empty uses the
// production endpoint.
Endpoint string
}
OpenMHzConfig configures one OpenMHz upload feed.
type Options ¶
type Options struct {
Bus *events.Bus
Log *slog.Logger
// Backends is the set of outbound destinations. A Manager with no
// backends is valid but inert.
Backends []Backend
// MinDuration drops calls shorter than this from every backend.
// Zero streams calls of any length.
MinDuration time.Duration
// Workers is the number of concurrent upload goroutines. Default 2.
Workers int
// MaxRetries is the per-backend retry budget on a failed Send.
// Default 3.
MaxRetries int
// RetryBase is the first backoff delay; it doubles per attempt.
// Default 2s.
RetryBase time.Duration
// Normalize, when Enabled, loudness-normalizes the distributed MP3
// copy in memory (the on-disk WAV is left pristine). Off by default.
Normalize NormalizeConfig
}
Options configure a Manager.
type RdioScannerConfig ¶
type RdioScannerConfig struct {
// Name is an optional log label; defaults to "rdioscanner".
Name string
// URL is the RdioScanner base URL (e.g. "https://scanner.example").
// The "/api/call-upload" path is appended automatically.
URL string
// APIKey is the RdioScanner system API key.
APIKey string
// SystemID is the numeric RdioScanner system ID.
SystemID int
// Systems restricts the feed to these trunking-system names.
// Empty streams every system.
Systems []string
}
RdioScannerConfig configures one RdioScanner call-upload feed.