Current broadcaster details admin api (#206)
* Add support for ending the inbound stream. Closes #191 * Add a simple success response to API requests * Store inbound broadcast details for admin purposes * Add /api/admin/broadcaster endpoint * Reset broadcaster on disconnect * Move controller to admin directory
This commit is contained in:
@@ -21,6 +21,7 @@ var (
|
||||
_storage models.ChunkStorageProvider
|
||||
_cleanupTimer *time.Timer
|
||||
_yp *yp.YP
|
||||
_broadcaster *models.Broadcaster
|
||||
)
|
||||
|
||||
//Start starts up the core processing
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/gabek/owncast/config"
|
||||
"github.com/gabek/owncast/core"
|
||||
"github.com/gabek/owncast/core/ffmpeg"
|
||||
"github.com/gabek/owncast/models"
|
||||
"github.com/gabek/owncast/utils"
|
||||
"github.com/nareix/joy5/format/rtmp"
|
||||
)
|
||||
@@ -62,10 +63,36 @@ func Start() {
|
||||
}
|
||||
}
|
||||
|
||||
func setCurrentBroadcasterInfo(t flvio.Tag, remoteAddr string) {
|
||||
data, err := getInboundDetailsFromMetadata(t.DebugFields())
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
|
||||
broadcaster := models.Broadcaster{
|
||||
RemoteAddr: remoteAddr,
|
||||
Time: time.Now(),
|
||||
StreamDetails: models.InboundStreamDetails{
|
||||
Width: data.Width,
|
||||
Height: data.Height,
|
||||
VideoBitrate: int(data.VideoBitrate),
|
||||
VideoCodec: getVideoCodec(data.VideoCodec),
|
||||
VideoFramerate: data.VideoFramerate,
|
||||
AudioBitrate: int(data.AudioBitrate),
|
||||
AudioCodec: getAudioCodec(data.AudioCodec),
|
||||
Encoder: data.Encoder,
|
||||
},
|
||||
}
|
||||
|
||||
core.SetBroadcaster(broadcaster)
|
||||
}
|
||||
|
||||
func HandleConn(c *rtmp.Conn, nc net.Conn) {
|
||||
c.LogTagEvent = func(isRead bool, t flvio.Tag) {
|
||||
if t.Type == flvio.TAG_AMF0 {
|
||||
log.Tracef("%+v\n", t.DebugFields())
|
||||
setCurrentBroadcasterInfo(t, nc.RemoteAddr().String())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
64
core/rtmp/utils.go
Normal file
64
core/rtmp/utils.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package rtmp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/gabek/owncast/models"
|
||||
"github.com/nareix/joy5/format/flv/flvio"
|
||||
)
|
||||
|
||||
func getInboundDetailsFromMetadata(metadata []interface{}) (models.RTMPStreamMetadata, error) {
|
||||
metadataComponentsString := fmt.Sprintf("%+v", metadata)
|
||||
re := regexp.MustCompile(`\{(.*?)\}`)
|
||||
submatchall := re.FindAllString(metadataComponentsString, 1)
|
||||
|
||||
if len(submatchall) == 0 {
|
||||
return models.RTMPStreamMetadata{}, errors.New("unable to parse inbound metadata")
|
||||
}
|
||||
|
||||
metadataJSONString := submatchall[0]
|
||||
var details models.RTMPStreamMetadata
|
||||
json.Unmarshal([]byte(metadataJSONString), &details)
|
||||
return details, nil
|
||||
}
|
||||
|
||||
func getAudioCodec(codec interface{}) string {
|
||||
var codecID float64
|
||||
if assertedCodecID, ok := codec.(float64); ok {
|
||||
codecID = assertedCodecID
|
||||
} else {
|
||||
return codec.(string)
|
||||
}
|
||||
|
||||
switch codecID {
|
||||
case flvio.SOUND_MP3:
|
||||
return "MP3"
|
||||
case flvio.SOUND_AAC:
|
||||
return "AAC"
|
||||
case flvio.SOUND_SPEEX:
|
||||
return "Speex"
|
||||
}
|
||||
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
func getVideoCodec(codec interface{}) string {
|
||||
var codecID float64
|
||||
if assertedCodecID, ok := codec.(float64); ok {
|
||||
codecID = assertedCodecID
|
||||
} else {
|
||||
return codec.(string)
|
||||
}
|
||||
|
||||
switch codecID {
|
||||
case flvio.VIDEO_H264:
|
||||
return "H.264"
|
||||
case flvio.VIDEO_H265:
|
||||
return "H.265"
|
||||
}
|
||||
|
||||
return "Unknown"
|
||||
}
|
||||
@@ -49,6 +49,7 @@ func SetStreamAsConnected() {
|
||||
func SetStreamAsDisconnected() {
|
||||
_stats.StreamConnected = false
|
||||
_stats.LastDisconnectTime = utils.NullTime{time.Now(), true}
|
||||
_broadcaster = nil
|
||||
|
||||
if _yp != nil {
|
||||
_yp.Stop()
|
||||
@@ -57,3 +58,12 @@ func SetStreamAsDisconnected() {
|
||||
ffmpeg.ShowStreamOfflineState()
|
||||
startCleanupTimer()
|
||||
}
|
||||
|
||||
// SetBroadcaster will store the current inbound broadcasting details
|
||||
func SetBroadcaster(broadcaster models.Broadcaster) {
|
||||
_broadcaster = &broadcaster
|
||||
}
|
||||
|
||||
func GetBroadcaster() *models.Broadcaster {
|
||||
return _broadcaster
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user