Documentation
¶
Overview ¶
Package watermarks manages the on-disk library of uploadable watermark images (logos, channel bugs). Each asset is stored as two files in a flat directory:
<dir>/<id>.<ext> ← image bytes <dir>/<id>.json ← domain.WatermarkAsset metadata sidecar
The sidecar layout means we don't need a separate database for asset metadata — `os.ReadDir` rebuilds the registry after every restart and the cache stays consistent without coordination with the storage layer.
Resolution flow at transcode time:
Stream.Watermark.AssetID
│
▼ watermarks.Service.ResolvePath
/<dir>/<id>.png
│
▼ coordinator copies into TranscoderConfig.Watermark.ImagePath
ffmpeg -i ... -vf "...,movie=<absolute path>,..."
Index ¶
- Variables
- type Service
- func (s *Service) Delete(id domain.WatermarkAssetID) error
- func (s *Service) Dir() string
- func (s *Service) Get(id domain.WatermarkAssetID) (*domain.WatermarkAsset, error)
- func (s *Service) List() []*domain.WatermarkAsset
- func (s *Service) ResolvePath(id domain.WatermarkAssetID) (string, error)
- func (s *Service) Save(displayName, originalFilename string, body io.Reader) (*domain.WatermarkAsset, error)
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotFound is returned by Get / Delete when the asset is unknown. ErrNotFound = errors.New("watermarks: asset not found") // ErrInvalidContent is returned when the uploaded bytes don't sniff // as an image MIME type the FFmpeg overlay path supports. ErrInvalidContent = errors.New("watermarks: not an image") // ErrTooLarge is returned by the handler when the upload exceeds // MaxWatermarkAssetBytes — defined here so the handler can wrap it. ErrTooLarge = errors.New("watermarks: upload too large") )
Errors returned by the service. Mapped to HTTP status codes by the REST handler — see internal/api/handler/watermark.go.
Functions ¶
This section is empty.
Types ¶
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the public facade. Constructed via DI from config.WatermarksConfig. Safe for concurrent use; an internal RWMutex protects the metadata map.
func New ¶
New is the samber/do constructor. Creates the assets directory if missing and seeds the in-memory cache from any sidecars already on disk so a restart picks up where the previous instance left off.
func (*Service) Delete ¶
func (s *Service) Delete(id domain.WatermarkAssetID) error
Delete removes both the image and metadata sidecar. Idempotent on the "already gone" case so repeat calls return ErrNotFound exactly once and no-op afterwards. Caller is responsible for ensuring the asset isn't referenced by an active stream — there is no foreign-key check here.
func (*Service) Dir ¶
Dir returns the on-disk root of the assets library. Exposed so the configuration UI can show operators where uploads land.
func (*Service) Get ¶
func (s *Service) Get(id domain.WatermarkAssetID) (*domain.WatermarkAsset, error)
Get returns the metadata for a single asset.
func (*Service) List ¶
func (s *Service) List() []*domain.WatermarkAsset
List returns a snapshot of every known asset, sorted by upload time (newest first) so dashboards default to "what did I just upload".
func (*Service) ResolvePath ¶
func (s *Service) ResolvePath(id domain.WatermarkAssetID) (string, error)
ResolvePath returns the absolute filesystem path to the image bytes for the given asset id. Used by the coordinator to translate Stream.Watermark.AssetID into TranscoderConfig.Watermark.ImagePath before the transcoder consumes the config.
func (*Service) Save ¶
func (s *Service) Save(displayName, originalFilename string, body io.Reader) (*domain.WatermarkAsset, error)
Save uploads new image bytes under the given display name. ContentType is sniffed via http.DetectContentType from the first 512 bytes; the returned asset's FileName preserves the operator's original filename for download responses.
Atomic on success: temp file written then renamed; sidecar metadata written last so a half-uploaded asset is invisible to subsequent calls.