mirror of
https://github.com/bluenviron/mediamtx.git
synced 2025-12-20 02:00:05 -08:00
Add keepalive API endpoints that allow streams to be kept active
without real viewers. Keepalives act as synthetic readers that
trigger on-demand publishers and prevent streams from closing when
all real viewers disconnect.
Features:
- POST /v3/paths/keepalive/add/{name} - create keepalive for path
- DELETE /v3/paths/keepalive/remove/{id} - remove keepalive by ID
- GET /v3/paths/keepalive/list - list all active keepalives
- GET /v3/paths/keepalive/get/{id} - get keepalive details
Implementation details:
- Keepalives implement defs.Reader interface
- Full authentication and authorization support
- Ownership tracking - only creator can remove keepalive
- Automatic cleanup when paths are removed
- UUID-based identification
- Asynchronous stream initialization to prevent deadlocks
63 lines
1.5 KiB
Go
63 lines
1.5 KiB
Go
package core
|
|
|
|
import (
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/bluenviron/mediamtx/internal/defs"
|
|
"github.com/bluenviron/mediamtx/internal/logger"
|
|
)
|
|
|
|
// keepalive is a synthetic reader that keeps a stream alive
|
|
// without being an actual viewer.
|
|
type keepalive struct {
|
|
id uuid.UUID
|
|
pathName string
|
|
created time.Time
|
|
creatorUser string // username that created this keepalive
|
|
creatorIP net.IP // IP address that created this keepalive
|
|
onClose func() // callback to remove from path when closed
|
|
}
|
|
|
|
func newKeepalive(pathName string, user string, ip net.IP) *keepalive {
|
|
return &keepalive{
|
|
id: uuid.New(),
|
|
pathName: pathName,
|
|
created: time.Now(),
|
|
creatorUser: user,
|
|
creatorIP: ip,
|
|
}
|
|
}
|
|
|
|
// Close implements defs.Reader.
|
|
// This is called when the keepalive is explicitly closed via the API.
|
|
func (k *keepalive) Close() {
|
|
if k.onClose != nil {
|
|
k.onClose()
|
|
}
|
|
}
|
|
|
|
// APIReaderDescribe implements defs.Reader.
|
|
func (k *keepalive) APIReaderDescribe() defs.APIPathSourceOrReader {
|
|
return defs.APIPathSourceOrReader{
|
|
Type: "keepalive",
|
|
ID: k.id.String(),
|
|
}
|
|
}
|
|
|
|
// Log implements logger.Writer.
|
|
func (k *keepalive) Log(level logger.Level, format string, args ...interface{}) {
|
|
// no-op, keepalives don't need logging
|
|
}
|
|
|
|
func (k *keepalive) apiDescribe() *defs.APIKeepalive {
|
|
return &defs.APIKeepalive{
|
|
ID: k.id,
|
|
Created: k.created,
|
|
Path: k.pathName,
|
|
CreatorUser: k.creatorUser,
|
|
CreatorIP: k.creatorIP.String(),
|
|
}
|
|
}
|