diff --git a/chunkStorage.go b/chunkStorage.go
index ddb86ce9c..16ba6dbdb 100644
--- a/chunkStorage.go
+++ b/chunkStorage.go
@@ -2,6 +2,6 @@ package main
type ChunkStorage interface {
Setup(config Config)
- Save(filePath string) string
+ Save(filePath string, retryCount int) string
GenerateRemotePlaylist(playlist string, variant Variant) string
}
diff --git a/client.go b/client.go
index 89f20c881..5f3bd4700 100644
--- a/client.go
+++ b/client.go
@@ -4,6 +4,7 @@ import (
"fmt"
"io"
+ log "github.com/sirupsen/logrus"
"golang.org/x/net/websocket"
)
@@ -24,11 +25,11 @@ type Client struct {
func NewClient(ws *websocket.Conn, server *Server) *Client {
if ws == nil {
- panic("ws cannot be nil")
+ log.Panicln("ws cannot be nil")
}
if server == nil {
- panic("server cannot be nil")
+ log.Panicln("server cannot be nil")
}
ch := make(chan *ChatMessage, channelBufSize)
diff --git a/config.go b/config.go
index 5d2a63b10..d77701772 100644
--- a/config.go
+++ b/config.go
@@ -3,9 +3,6 @@ package main
import (
"fmt"
"io/ioutil"
- "os"
- "path"
- "strconv"
log "github.com/sirupsen/logrus"
@@ -69,7 +66,7 @@ func getConfig() Config {
var config Config
err = yaml.Unmarshal(yamlFile, &config)
if err != nil {
- panic(err)
+ log.Panicln(err)
}
// fmt.Printf("%+v\n", config)
@@ -79,37 +76,37 @@ func getConfig() Config {
func checkConfig(config Config) {
if config.S3.Enabled && config.IPFS.Enabled {
- panic("S3 and IPFS support cannot be enabled at the same time. Choose one.")
+ log.Panicln("S3 and IPFS support cannot be enabled at the same time. Choose one.")
}
if config.S3.Enabled {
if config.S3.AccessKey == "" || config.S3.Secret == "" {
- panic("S3 support requires an access key and secret.")
+ log.Panicln("S3 support requires an access key and secret.")
}
if config.S3.Region == "" || config.S3.Endpoint == "" {
- panic("S3 support requires a region and endpoint.")
+ log.Panicln("S3 support requires a region and endpoint.")
}
if config.S3.Bucket == "" {
- panic("S3 support requires a bucket created for storing public video segments.")
+ log.Panicln("S3 support requires a bucket created for storing public video segments.")
}
}
- if !fileExists(config.PrivateHLSPath) {
- os.MkdirAll(path.Join(config.PrivateHLSPath, strconv.Itoa(0)), 0777)
- }
+ // if !fileExists(config.PrivateHLSPath) {
+ // os.MkdirAll(path.Join(config.PrivateHLSPath, strconv.Itoa(0)), 0777)
+ // }
- if !fileExists(config.PublicHLSPath) {
- os.MkdirAll(path.Join(config.PublicHLSPath, strconv.Itoa(0)), 0777)
- }
+ // if !fileExists(config.PublicHLSPath) {
+ // os.MkdirAll(path.Join(config.PublicHLSPath, strconv.Itoa(0)), 0777)
+ // }
if !fileExists(config.FFMpegPath) {
- panic(fmt.Sprintf("ffmpeg does not exist at %s.", config.FFMpegPath))
+ log.Panicln(fmt.Sprintf("ffmpeg does not exist at %s.", config.FFMpegPath))
}
if config.VideoSettings.EncoderPreset == "" {
- panic("A video encoder preset is required to be set in the config file.")
+ log.Panicln("A video encoder preset is required to be set in the config file.")
}
}
diff --git a/ipfsStorage.go b/ipfsStorage.go
index 6208dc26e..fe4aa55f4 100644
--- a/ipfsStorage.go
+++ b/ipfsStorage.go
@@ -52,12 +52,12 @@ func (s *IPFSStorage) Setup(config Config) {
s.createIPFSDirectory("./hls")
}
-func (s *IPFSStorage) Save(filePath string) string {
+func (s *IPFSStorage) Save(filePath string, retryCount int) string {
someFile, err := getUnixfsNode(filePath)
defer someFile.Close()
if err != nil {
- panic(fmt.Errorf("Could not get File: %s", err))
+ log.Panicln(fmt.Errorf("Could not get File: %s", err))
}
opts := []options.UnixfsAddOption{
@@ -70,7 +70,7 @@ func (s *IPFSStorage) Save(filePath string) string {
cidFile, err := (*s.ipfs).Unixfs().Add(s.ctx, someFile, opts...)
if err != nil {
- panic(fmt.Errorf("Could not add File: %s", err))
+ log.Panicln(fmt.Errorf("Could not add File: %s", err))
}
// fmt.Printf("Added file to IPFS with CID %s\n", cidFile.String())
diff --git a/main.go b/main.go
index e485c6353..915e55cd3 100644
--- a/main.go
+++ b/main.go
@@ -37,18 +37,19 @@ func main() {
usingExternalStorage = true
}
+ resetDirectories(configuration)
+
if usingExternalStorage {
storage.Setup(configuration)
go monitorVideoContent(configuration.PrivateHLSPath, configuration, storage)
}
- resetDirectories(configuration)
go startRTMPService()
- startChatServer()
+ startWebServer()
}
-func startChatServer() {
+func startWebServer() {
// log.SetFlags(log.Lshortfile)
// websocket server
@@ -63,6 +64,7 @@ func startChatServer() {
if path.Ext(r.URL.Path) == ".m3u8" {
clientID := getClientIDFromRequest(r)
stats.SetClientActive(clientID)
+ disableCache(&w)
}
})
@@ -77,6 +79,11 @@ func enableCors(w *http.ResponseWriter) {
(*w).Header().Set("Access-Control-Allow-Origin", "*")
}
+func disableCache(w *http.ResponseWriter) {
+ (*w).Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
+ (*w).Header().Set("Expires", "0")
+}
+
func getStatus(w http.ResponseWriter, r *http.Request) {
enableCors(&w)
diff --git a/playlistMonitor.go b/playlistMonitor.go
index 5cd68d767..71c865dc4 100644
--- a/playlistMonitor.go
+++ b/playlistMonitor.go
@@ -108,7 +108,7 @@ func monitorVideoContent(pathToMonitor string, configuration Config, storage Chu
newObjectPathChannel := make(chan string, 1)
go func() {
- newObjectPath := storage.Save(path.Join(configuration.PrivateHLSPath, segment.RelativeUploadPath))
+ newObjectPath := storage.Save(path.Join(configuration.PrivateHLSPath, segment.RelativeUploadPath), 0)
newObjectPathChannel <- newObjectPath
}()
newObjectPath := <-newObjectPathChannel
diff --git a/s3Storage.go b/s3Storage.go
index e9b0e0d5d..b3f9b16ed 100644
--- a/s3Storage.go
+++ b/s3Storage.go
@@ -36,14 +36,14 @@ func (s *S3Storage) Setup(configuration Config) {
s.sess = s.connectAWS()
}
-func (s *S3Storage) Save(filePath string) string {
+func (s *S3Storage) Save(filePath string, retryCount int) string {
// fmt.Println("Saving", filePath)
file, err := os.Open(filePath)
defer file.Close()
if err != nil {
- log.Fatal(err)
+ log.Errorln(err)
}
uploader := s3manager.NewUploader(s.sess)
@@ -55,7 +55,11 @@ func (s *S3Storage) Save(filePath string) string {
})
if err != nil {
- panic(err)
+ log.Errorln(err)
+ if retryCount < 4 {
+ log.Println("Retrying...")
+ s.Save(filePath, retryCount+1)
+ }
}
// fmt.Println("Uploaded", filePath, "to", response.Location)
@@ -88,7 +92,7 @@ func (s S3Storage) connectAWS() *session.Session {
creds := credentials.NewStaticCredentials(s.s3AccessKey, s.s3Secret, "")
_, err := creds.Get()
if err != nil {
- panic(err)
+ log.Panicln(err)
}
sess, err := session.NewSession(
@@ -101,7 +105,7 @@ func (s S3Storage) connectAWS() *session.Session {
)
if err != nil {
- panic(err)
+ log.Panicln(err)
}
return sess
}
diff --git a/scripts/build.sh b/scripts/build.sh
index dea287fa6..631a62ab0 100755
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -9,6 +9,11 @@ ARCH=(amd64 amd64)
# Version
VERSION=$1
+
+if [[ -z "${VERSION}" ]]; then
+ echo "Version must be specified when running build"
+fi
+
[[ -z "${VERSION}" ]] && VERSION='unknownver' || VERSION="${VERSION}"
GIT_COMMIT=$(git rev-list -1 HEAD)
@@ -33,7 +38,10 @@ build() {
mkdir -p dist/${NAME}/config
+ # Default files
cp config/config-example.yaml dist/${NAME}/config/config.yaml
+ cp webroot/static/content-example.md dist/${NAME}/webroot/static/content.md
+
cp -R webroot/ dist/${NAME}/webroot/
cp -R doc/ dist/${NAME}/doc/
cp README.md dist/${NAME}
diff --git a/stats.go b/stats.go
index bc8fb9d21..4d12a70d1 100644
--- a/stats.go
+++ b/stats.go
@@ -145,7 +145,7 @@ func getSavedStats() *Stats {
var stats Stats
err = json.Unmarshal(jsonFile, &stats)
if err != nil {
- panic(err)
+ log.Panicln(err)
}
return &stats
diff --git a/webroot/index.html b/webroot/index.html
index d63ddb149..a1e2f75e4 100644
--- a/webroot/index.html
+++ b/webroot/index.html
@@ -8,9 +8,9 @@
-
+
-
+
diff --git a/webroot/js/app.js b/webroot/js/app.js
index 5319617f6..e36f07de5 100644
--- a/webroot/js/app.js
+++ b/webroot/js/app.js
@@ -47,13 +47,10 @@ async function setupApp() {
const response = await fetch(pageContentFile);
const descriptionMarkdown = await response.text()
const descriptionHTML = new showdown.Converter().makeHtml(descriptionMarkdown);
- console.log(descriptionHTML)
app.description = descriptionHTML;
- // Object.assign(this, configData);
return this;
} catch (error) {
console.log(error);
- // No config file present. That's ok. It's not required.
}
}
diff --git a/webroot/static/content-example.md b/webroot/static/content-example.md
new file mode 100644
index 000000000..6b8f2888b
--- /dev/null
+++ b/webroot/static/content-example.md
@@ -0,0 +1,4 @@
+# Stream description and content can go here.
+
+1. Edit `content.md` in markdown.
+1. And it'll go here.
\ No newline at end of file