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:
Gabe Kangas
2020-10-02 00:12:47 -07:00
committed by GitHub
parent 236f25b772
commit f4fdc6c951
7 changed files with 176 additions and 0 deletions

View File

@@ -21,6 +21,7 @@ var (
_storage models.ChunkStorageProvider
_cleanupTimer *time.Timer
_yp *yp.YP
_broadcaster *models.Broadcaster
)
//Start starts up the core processing

View File

@@ -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
View 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"
}

View File

@@ -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
}