From a266633a9a833c9957735a8658ef3539c6948726 Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Sat, 18 Jul 2020 15:37:17 -0700 Subject: [PATCH 1/5] Force LiveUI/seek bar during live to show. Closes #11. --- webroot/js/utils.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webroot/js/utils.js b/webroot/js/utils.js index 103700cee..5b8fb716b 100644 --- a/webroot/js/utils.js +++ b/webroot/js/utils.js @@ -32,6 +32,9 @@ const VIDEO_SRC = { const VIDEO_OPTIONS = { autoplay: false, liveui: true, // try this + liveTracker: { + trackingThreshold: 0, + }, sources: [VIDEO_SRC], }; From 2855027f2236eacc6bb4abd6ce71b17435d0bb7b Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Sat, 18 Jul 2020 17:27:04 -0700 Subject: [PATCH 2/5] Use endpoint for chat history instead of websocket (#67) * Change placeholder when chat is disabled * Use the /chat endpoint for bulk chat history population instead of websocket. For #47 * Force LiveUI/seek bar during live to show. Closes #11. * Change pulling chat history into app.js * Force new messages to have visability = true --- core/chat/client.go | 1 + core/chat/server.go | 7 ------- webroot/js/app.js | 32 ++++++++++++++++++++++++++------ webroot/js/message.js | 1 + 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/core/chat/client.go b/core/chat/client.go index 7436336fb..2c5553047 100644 --- a/core/chat/client.go +++ b/core/chat/client.go @@ -111,6 +111,7 @@ func (c *Client) listenRead() { msg.ID = id msg.MessageType = "CHAT" msg.Timestamp = time.Now() + msg.Visible = true if err := websocket.JSON.Receive(c.ws, &msg); err == io.EOF { c.doneCh <- true diff --git a/core/chat/server.go b/core/chat/server.go index 62e9f4bf6..2d3c20afc 100644 --- a/core/chat/server.go +++ b/core/chat/server.go @@ -56,12 +56,6 @@ func (s *server) err(err error) { s.errCh <- err } -func (s *server) sendPastMessages(c *Client) { - for _, msg := range s.Messages { - c.Write(msg) - } -} - func (s *server) sendAll(msg models.ChatMessage) { for _, c := range s.Clients { c.Write(msg) @@ -104,7 +98,6 @@ func (s *server) Listen() { s.Clients[c.id] = c s.listener.ClientAdded(c.id) - s.sendPastMessages(c) // remove a client case c := <-s.delCh: diff --git a/webroot/js/app.js b/webroot/js/app.js index 04b97512b..531fa8ed7 100644 --- a/webroot/js/app.js +++ b/webroot/js/app.js @@ -86,6 +86,8 @@ class Owncast { onError: this.handlePlayerError, }); this.player.init(); + + this.getChatHistory(); }; setConfigData(data) { @@ -132,17 +134,21 @@ class Owncast { return; } const message = new Message(model); - const existing = this.vueApp.messages.filter(function (item) { - return item.id === message.id; - }) - if (existing.length === 0 || !existing) { - this.vueApp.messages = [...this.vueApp.messages, message]; - } + this.addMessage(message); }; this.websocket = ws; this.messagingInterface.setWebsocket(this.websocket); }; + addMessage(message) { + const existing = this.vueApp.messages.filter(function (item) { + return item.id === message.id; + }) + if (existing.length === 0 || !existing) { + this.vueApp.messages = [...this.vueApp.messages, message]; + } + } + // fetch /config data getConfig() { fetch(URL_CONFIG) @@ -276,4 +282,18 @@ class Owncast { this.handleOfflineMode(); // stop timers? }; + + async getChatHistory() { + const url = "/chat"; + const response = await fetch(url); + const data = await response.json(); + const messages = data.map(function (message) { + return new Message(message); + }) + this.setChatHistory(messages); + } + + setChatHistory(messages) { + this.vueApp.messages = messages; + } }; diff --git a/webroot/js/message.js b/webroot/js/message.js index 698deb685..bc74a50f7 100644 --- a/webroot/js/message.js +++ b/webroot/js/message.js @@ -81,6 +81,7 @@ class MessagingInterface { } else { this.tagAppContainer.classList.add('desktop'); } + } setWebsocket(socket) { From fff911010cdb7a831c42267c79ca178e9ac5f7fe Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Fri, 17 Jul 2020 18:27:00 -0700 Subject: [PATCH 3/5] Centralize default values into an instance of config. For #64 --- config/config.go | 57 +++++++++++++++++------------------- config/defaults.go | 40 +++++++++++++++++++++++++ doc/config-example-full.yaml | 3 +- 3 files changed, 69 insertions(+), 31 deletions(-) create mode 100644 config/defaults.go diff --git a/config/config.go b/config/config.go index af3747e21..d619d5e3a 100644 --- a/config/config.go +++ b/config/config.go @@ -3,8 +3,6 @@ package config import ( "errors" "io/ioutil" - "os/exec" - "strings" "github.com/gabek/owncast/utils" log "github.com/sirupsen/logrus" @@ -13,6 +11,7 @@ import ( //Config contains a reference to the configuration var Config *config +var _default config type config struct { ChatDatabaseFilePath string `yaml:"chatDatabaseFile"` @@ -137,32 +136,12 @@ func (c *config) verifySettings() error { return nil } -func (c *config) GetFFMpegPath() string { - if c.FFMpegPath != "" { - return c.FFMpegPath - } - - cmd := exec.Command("which", "ffmpeg") - out, err := cmd.CombinedOutput() - if err != nil { - log.Panicln("Unable to determine path to ffmpeg. Please specify it in the config file.") - } - - path := strings.TrimSpace(string(out)) - - // Memoize it for future access - c.FFMpegPath = path - - return path -} - func (c *config) GetVideoSegmentSecondsLength() int { if c.VideoSettings.ChunkLengthInSeconds != 0 { return c.VideoSettings.ChunkLengthInSeconds } - // Default - return 4 + return _default.GetVideoSegmentSecondsLength() } func (c *config) GetPublicHLSSavePath() string { @@ -170,7 +149,7 @@ func (c *config) GetPublicHLSSavePath() string { return c.PublicHLSPath } - return "webroot/hls" + return _default.PublicHLSPath } func (c *config) GetPrivateHLSSavePath() string { @@ -178,7 +157,7 @@ func (c *config) GetPrivateHLSSavePath() string { return c.PrivateHLSPath } - return "hls" + return _default.PrivateHLSPath } func (c *config) GetPublicWebServerPort() int { @@ -186,8 +165,7 @@ func (c *config) GetPublicWebServerPort() int { return c.WebServerPort } - // Default web server port - return 8080 + return _default.WebServerPort } func (c *config) GetMaxNumberOfReferencedSegmentsInPlaylist() int { @@ -195,7 +173,7 @@ func (c *config) GetMaxNumberOfReferencedSegmentsInPlaylist() int { return c.Files.MaxNumberInPlaylist } - return 20 + return _default.GetMaxNumberOfReferencedSegmentsInPlaylist() } func (c *config) GetOfflineContentPath() string { @@ -204,12 +182,29 @@ func (c *config) GetOfflineContentPath() string { } // This is relative to the webroot, not the project root. - return "static/offline.m4v" + return _default.VideoSettings.OfflineContent +} + +func (c *config) GetFFMpegPath() string { + if c.FFMpegPath != "" { + return c.FFMpegPath + } + + return _default.FFMpegPath +} + +func (c *config) GetVideoStreamQualities() []StreamQuality { + if len(c.VideoSettings.StreamQualities) > 0 { + return c.VideoSettings.StreamQualities + } + + return _default.VideoSettings.StreamQualities } //Load tries to load the configuration file func Load(filePath string, versionInfo string) error { Config = new(config) + _default = getDefaults() if err := Config.load(filePath); err != nil { return err @@ -220,8 +215,10 @@ func Load(filePath string, versionInfo string) error { // Defaults // This is relative to the webroot, not the project root. + // Has to be set here instead of pulled from a getter + // since it's serialized to JSON. if Config.InstanceDetails.ExtraInfoFile == "" { - Config.InstanceDetails.ExtraInfoFile = "/static/content.md" + Config.InstanceDetails.ExtraInfoFile = _default.InstanceDetails.ExtraInfoFile } return Config.verifySettings() diff --git a/config/defaults.go b/config/defaults.go new file mode 100644 index 000000000..ded829273 --- /dev/null +++ b/config/defaults.go @@ -0,0 +1,40 @@ +package config + +import ( + "log" + "os/exec" + "strings" +) + +func getDefaults() config { + defaults := config{} + defaults.WebServerPort = 8080 + defaults.FFMpegPath = getDefaultFFMpegPath() + defaults.VideoSettings.ChunkLengthInSeconds = 4 + defaults.Files.MaxNumberInPlaylist = 5 + defaults.PublicHLSPath = "webroot/hls" + defaults.PrivateHLSPath = "hls" + defaults.VideoSettings.OfflineContent = "static/offline.m4v" + defaults.InstanceDetails.ExtraInfoFile = "/static/content.md" + + defaultQuality := StreamQuality{ + IsAudioPassthrough: true, + VideoBitrate: 1200, + EncoderPreset: "veryfast", + } + defaults.VideoSettings.StreamQualities = []StreamQuality{defaultQuality} + + return defaults +} + +func getDefaultFFMpegPath() string { + cmd := exec.Command("which", "ffmpeg") + out, err := cmd.CombinedOutput() + if err != nil { + log.Panicln("Unable to determine path to ffmpeg. Please specify it in the config file.") + } + + path := strings.TrimSpace(string(out)) + + return path +} diff --git a/doc/config-example-full.yaml b/doc/config-example-full.yaml index ac7bca6dc..9edcaf821 100644 --- a/doc/config-example-full.yaml +++ b/doc/config-example-full.yaml @@ -55,7 +55,8 @@ videoSettings: audioPassthrough: true # The slower the preset the higher quality the video is. # Select a preset from https://trac.ffmpeg.org/wiki/Encode/H.264 - encoderPreset: superfast + # "superfast" and "ultrafast" are generally not recommended since they look bad. + encoderPreset: veryfast - medium: videoBitrate: 800 From fbfea8e38c85336741fa27e50d1afa0a73ddfa43 Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Sat, 18 Jul 2020 17:46:18 -0700 Subject: [PATCH 4/5] Throw and error if a stream key is not set in the config --- config/config.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/config.go b/config/config.go index d619d5e3a..d5b2ca144 100644 --- a/config/config.go +++ b/config/config.go @@ -115,6 +115,10 @@ func (c *config) load(filePath string) error { } func (c *config) verifySettings() error { + if c.VideoSettings.StreamingKey == "" { + return errors.New("No stream key set. Please set one in your config file.") + } + if c.S3.Enabled && c.IPFS.Enabled { return errors.New("s3 and IPFS support cannot be enabled at the same time; choose one") } From edec533eefdae3095d8564fb89b712432c0425d4 Mon Sep 17 00:00:00 2001 From: Matt Steele Date: Sun, 19 Jul 2020 12:26:05 -0500 Subject: [PATCH 5/5] Set Content-Type on status endpoint (#70) --- controllers/status.go | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/status.go b/controllers/status.go index b372651a5..78e62f1dc 100644 --- a/controllers/status.go +++ b/controllers/status.go @@ -13,6 +13,7 @@ func GetStatus(w http.ResponseWriter, r *http.Request) { middleware.EnableCors(&w) status := core.GetStatus() + w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(status) }