diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..b6f92bf
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,7 @@
+kill.sh
+build.sh
+launch.sh
+go/
+www/
+logs/
+low-latency-preview
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..6e2e020
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,9 @@
+FROM golang:1.11.10
+WORKDIR $GOPATH/src/app
+COPY . .
+RUN mkdir -p www logs
+RUN go get -d -v ./...
+RUN go install -v ./...
+EXPOSE 8080
+CMD ["app", "'./www'"]
+
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index beb5f01..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2018 codingtmd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/buildEncoderAndServerUbuntu.sh b/build.sh
old mode 100755
new mode 100644
similarity index 58%
rename from buildEncoderAndServerUbuntu.sh
rename to build.sh
index db72d6f..4b9832c
--- a/buildEncoderAndServerUbuntu.sh
+++ b/build.sh
@@ -1,15 +1,7 @@
-#!/bin/bash
-
-# install go repo
-
sudo add-apt-repository -y ppa:longsleep/golang-backports
-
# update the OS
-
sudo apt-get -y update
-
sudo apt-get -y upgrade
-
sudo apt-get -y install git
rm -r -f *zip*
@@ -19,15 +11,6 @@ rm -r -f *tar*
wget -O- https://dl.google.com/go/go1.11.1.linux-amd64.tar.gz | tar xz
go/bin/go get -d -v .
-
-go/bin/go build
-
-go/bin/go get -d -v .
-
go/bin/go build
mkdir -p www logs
-
-mkdir -p ffmpeg
-wget -O- "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz" | tar xJ -C ffmpeg --strip-components 1
-
diff --git a/buildEncoderAndServerMacOS.sh b/buildEncoderAndServerMacOS.sh
deleted file mode 100755
index 2577117..0000000
--- a/buildEncoderAndServerMacOS.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-
-cd utils
-
-curl -O https://cdn.theunarchiver.com/downloads/unarMac.zip
-
-unzip unarMac.zip
-
-cd ..
-
-rm -r -f ffmpeg/
-
-mkdir ffmpeg
-
-cd ffmpeg
-
-# NOTE: This link will need to be updated whenever ffmpeg creates a new binary release
-wget https://evermeet.cx/ffmpeg/ffmpeg-4.3.1.7z
-
-../utils/unar ffmpeg-4.3.1.7z
-
-rm ffmpeg-4.3.1.7z
-
-cd ..
-
-rm -r -f *zip*
-
-rm -r -f *tar*
-
-wget https://golang.org/dl/go1.15.7.darwin-amd64.tar.gz
-
-tar xvzf go1.15.7.darwin-amd64.tar.gz
-
-rm go1.15.7.darwin-amd64.tar.gz
-
-go/bin/go mod init github.com/streamlinevideo/low-latency-preview
-
-go/bin/go get -d -v .
-
-go/bin/go build
-
-rm -r -f www/
-
-mkdir -p www logs
-
-rm -r -f low-latency-preview-master
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..3ec4ff8
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,12 @@
+module streamline
+
+go 1.15
+
+require (
+ github.com/gorilla/mux v1.8.0
+ github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect
+ github.com/juju/loggo v0.0.0-20200526014432-9ce3a2e09b5e
+ github.com/lunixbochs/vtclean v1.0.0 // indirect
+ github.com/mattn/go-colorable v0.1.8 // indirect
+ github.com/rs/cors v1.7.0
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..2ebb6f2
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,16 @@
+github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
+github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
+github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
+github.com/juju/loggo v0.0.0-20200526014432-9ce3a2e09b5e h1:FdDd7bdI6cjq5vaoYlK1mfQYfF9sF2VZw8VEZMsl5t8=
+github.com/juju/loggo v0.0.0-20200526014432-9ce3a2e09b5e/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
+github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
+github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
+github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
+github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
+github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/handlers/dashplayhandle.go b/handlers/dashplayhandle.go
index c64791d..2b7ec93 100644
--- a/handlers/dashplayhandle.go
+++ b/handlers/dashplayhandle.go
@@ -5,7 +5,7 @@ import (
"net/url"
"path"
- "github.com/streamlinevideo/low-latency-preview/utils"
+ "streamline/utils"
)
type DashPlayHandler struct {
@@ -25,10 +25,10 @@ func (l *DashPlayHandler) servePlayer(w http.ResponseWriter, req *http.Request)
if req.URL.EscapedPath() == "/" {
curFileURL = "/localhost/manifest.mpd"
} else {
- curFileURL = req.URL.EscapedPath()[len("/ldashplay"):]
+ curFileURL = req.URL.EscapedPath()[len("/dashplay"):]
}
- curFilePath := path.Join("ldash", curFileURL)
+ curFilePath := path.Join("dash", curFileURL)
base, _ := url.Parse("http://" + req.Host)
relativeUrl, _ := url.Parse(curFilePath)
manifestUrl := base.ResolveReference(relativeUrl).String()
@@ -613,7 +613,7 @@ func (l *DashPlayHandler) servePlayer(w http.ResponseWriter, req *http.Request)
diff --git a/handlers/filedeletehandler.go b/handlers/filedeletehandlerdash.go
similarity index 72%
rename from handlers/filedeletehandler.go
rename to handlers/filedeletehandlerdash.go
index 6957b06..955734e 100644
--- a/handlers/filedeletehandler.go
+++ b/handlers/filedeletehandlerdash.go
@@ -6,15 +6,15 @@ import (
"path"
"time"
- "github.com/streamlinevideo/low-latency-preview/utils"
+ "streamline/utils"
)
// UploadHandler handles for http delete
-type FileDeleteHandler struct {
+type FileDashDeleteHandler struct {
BaseDir string
}
-func (d *FileDeleteHandler) isFileUploadingDone(file string) bool {
+func (d *FileDashDeleteHandler) isFileUploadingDone(file string) bool {
symlink := file + ".symlink"
if _, err := os.Stat(symlink); err == nil {
// exist, then segment uploading is not finished yet
@@ -24,14 +24,14 @@ func (d *FileDeleteHandler) isFileUploadingDone(file string) bool {
return true
}
-func (d *FileDeleteHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+func (d *FileDashDeleteHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
utils.GetUploadLogger().Infof("Received upload request\n")
- curFileURL := req.URL.EscapedPath()[len("/ldash"):]
+ curFileURL := req.URL.EscapedPath()[len("/dash"):]
curFilePath := path.Join(d.BaseDir, curFileURL)
d.serveHTTPImpl(curFilePath, w, req)
}
-func (d *FileDeleteHandler) serveHTTPImpl(curFilePath string, w http.ResponseWriter, req *http.Request) {
+func (d *FileDashDeleteHandler) serveHTTPImpl(curFilePath string, w http.ResponseWriter, req *http.Request) {
// check file existing
if _, err := os.Stat(curFilePath); err != nil {
utils.GetDeleteLogger().Debugf("file %s not exists \n", curFilePath)
diff --git a/handlers/filedeletehandlerhls.go b/handlers/filedeletehandlerhls.go
new file mode 100644
index 0000000..cd26d04
--- /dev/null
+++ b/handlers/filedeletehandlerhls.go
@@ -0,0 +1,52 @@
+package handlers
+
+import (
+ "net/http"
+ "os"
+ "path"
+ "time"
+
+ "streamline/utils"
+)
+
+// UploadHandler handles for http delete
+type FileHLSDeleteHandler struct {
+ BaseDir string
+}
+
+func (d *FileHLSDeleteHandler) isFileUploadingDone(file string) bool {
+ symlink := file + ".symlink"
+ if _, err := os.Stat(symlink); err == nil {
+ // exist, then segment uploading is not finished yet
+ return false
+ }
+ // not exist
+ return true
+}
+
+func (d *FileHLSDeleteHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ utils.GetUploadLogger().Infof("Received upload request\n")
+ curFileURL := req.URL.EscapedPath()[len("/hls"):]
+ curFilePath := path.Join(d.BaseDir, curFileURL)
+ d.serveHTTPImpl(curFilePath, w, req)
+}
+
+func (d *FileHLSDeleteHandler) serveHTTPImpl(curFilePath string, w http.ResponseWriter, req *http.Request) {
+ // check file existing
+ if _, err := os.Stat(curFilePath); err != nil {
+ utils.GetDeleteLogger().Debugf("file %s not exists \n", curFilePath)
+ return
+ }
+
+ is_chunk_uploading_done := d.isFileUploadingDone(curFilePath)
+ if !is_chunk_uploading_done { // chunk uploading is not done yet
+ return
+ }
+
+ if err := os.Remove(curFilePath); err != nil {
+ utils.GetDeleteLogger().Errorf("Failed to delete file %s with %v \n", curFilePath, err)
+ return
+ }
+
+ utils.GetDeleteLogger().Debugf("file %s was deleted exists @ %v \n", curFilePath, time.Now().Format(time.RFC3339))
+}
diff --git a/handlers/filedownloadhandler.go b/handlers/filedownloadhandlerdash.go
similarity index 84%
rename from handlers/filedownloadhandler.go
rename to handlers/filedownloadhandlerdash.go
index a877919..14a4a6d 100644
--- a/handlers/filedownloadhandler.go
+++ b/handlers/filedownloadhandlerdash.go
@@ -8,24 +8,24 @@ import (
"strings"
"time"
- "github.com/streamlinevideo/low-latency-preview/utils"
+ "streamline/utils"
)
-type FileDownloadHandler struct {
+type FileDashDownloadHandler struct {
StartTime time.Time
BaseDir string
}
-func (l *FileDownloadHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+func (l *FileDashDownloadHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
utils.GetDownloadLogger().Infof("Received download request\n")
l.serveDownload(w, req)
}
-func (l *FileDownloadHandler) getSourcePath(req *http.Request) string {
+func (l *FileDashDownloadHandler) getSourcePath(req *http.Request) string {
return l.BaseDir
}
-func (l *FileDownloadHandler) isFileUploadingDone(file string) bool {
+func (l *FileDashDownloadHandler) isFileUploadingDone(file string) bool {
symlink := file + ".symlink"
if _, err := os.Stat(symlink); err == nil {
// exist, then segment uploading is not finished yet
@@ -35,8 +35,8 @@ func (l *FileDownloadHandler) isFileUploadingDone(file string) bool {
return true
}
-func (l *FileDownloadHandler) serveDownload(w http.ResponseWriter, req *http.Request) {
- curFileURL := req.URL.EscapedPath()[len("/ldash"):]
+func (l *FileDashDownloadHandler) serveDownload(w http.ResponseWriter, req *http.Request) {
+ curFileURL := req.URL.EscapedPath()[len("/dash"):]
curFilePath := path.Join(l.getSourcePath(req), curFileURL)
file, err := os.Open(curFilePath) // For read access.
if err != nil {
diff --git a/handlers/filedownloadhandlerhls.go b/handlers/filedownloadhandlerhls.go
new file mode 100644
index 0000000..fb85306
--- /dev/null
+++ b/handlers/filedownloadhandlerhls.go
@@ -0,0 +1,105 @@
+package handlers
+
+import (
+ "io"
+ "net/http"
+ "os"
+ "path"
+ "strings"
+ "time"
+
+ "streamline/utils"
+)
+
+type FileHLSDownloadHandler struct {
+ StartTime time.Time
+ BaseDir string
+}
+
+func (l *FileHLSDownloadHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ utils.GetDownloadLogger().Infof("Received download request\n")
+ l.serveDownload(w, req)
+}
+
+func (l *FileHLSDownloadHandler) getSourcePath(req *http.Request) string {
+ return l.BaseDir
+}
+
+func (l *FileHLSDownloadHandler) isFileUploadingDone(file string) bool {
+ symlink := file + ".symlink"
+ if _, err := os.Stat(symlink); err == nil {
+ // exist, then segment uploading is not finished yet
+ return false
+ }
+ // not exist
+ return true
+}
+
+func (l *FileHLSDownloadHandler) serveDownload(w http.ResponseWriter, req *http.Request) {
+ curFileURL := req.URL.EscapedPath()[len("/lhls"):]
+ curFilePath := path.Join(l.getSourcePath(req), curFileURL)
+ file, err := os.Open(curFilePath) // For read access.
+ if err != nil {
+ utils.GetDownloadLogger().Errorf("Failed to open file: %v \n", err)
+ http.NotFound(w, req)
+ return
+ }
+ defer file.Close()
+
+ utils.GetDownloadLogger().Debugf("file %s was requested @ %v \n", curFileURL, time.Now().Format(time.RFC3339))
+
+ w.Header().Set("Access-Control-Allow-Origin", "*")
+ w.Header().Set("Transfer-Encoding", "chunked")
+ w.Header().Set("Connection", "Keep-Alive")
+
+ if strings.HasSuffix(curFilePath, ".m3u8") {
+ w.Header().Set("Content-Type", "application/x-mpegURL")
+ } else if strings.HasSuffix(curFilePath, ".mp4") || strings.HasSuffix(curFilePath, ".fmp4") {
+ w.Header().Set("Content-Type", "video/MP4")
+ } else {
+ w.Header().Set("Content-Type", "video/MP2T")
+ }
+
+ w.WriteHeader(http.StatusOK)
+
+ bufferSize := 20480
+ buffer := make([]byte, bufferSize)
+ var read_err error
+ bytesread := 0
+ for {
+ // start chunk transfer
+ for {
+ bytesread, read_err = file.Read(buffer)
+ if read_err != nil {
+ if read_err != io.EOF { // print out if read error
+ utils.GetDownloadLogger().Errorf("Failed to read file: %v \n", err)
+ panic(read_err)
+ }
+ }
+
+ if bytesread > 0 {
+ utils.GetDownloadLogger().Debugf("%s read %d bytes \n", curFileURL, bytesread)
+ _, errpr := w.Write(buffer[:bytesread])
+ if errpr != nil {
+ panic(errpr)
+ }
+ }
+
+ if bytesread != bufferSize {
+ break
+ }
+ }
+
+ if read_err != nil {
+ is_chunk_uploading_done := l.isFileUploadingDone(curFilePath)
+ if read_err == io.EOF && is_chunk_uploading_done {
+ // if read to end and uploading is done, time to close the downloading too
+ break
+ }
+ utils.GetDownloadLogger().Debugf("Read to end, but uploading is not finished yet: %v \n", err)
+ }
+ time.Sleep(50 * time.Millisecond)
+ }
+ utils.GetDownloadLogger().Debugf("file %s was downloaded @ %v \n", curFileURL, time.Now().Format(time.RFC3339))
+
+}
diff --git a/handlers/fileuploadhandler.go b/handlers/fileuploadhandlerdash.go
similarity index 85%
rename from handlers/fileuploadhandler.go
rename to handlers/fileuploadhandlerdash.go
index b29829f..fc1d847 100644
--- a/handlers/fileuploadhandler.go
+++ b/handlers/fileuploadhandlerdash.go
@@ -8,18 +8,18 @@ import (
"path"
"time"
- "github.com/streamlinevideo/low-latency-preview/utils"
+ "streamline/utils"
"github.com/gorilla/mux"
)
// UploadHandler handles for http upload
-type FileUploadHandler struct {
+type FileDashUploadHandler struct {
BaseDir string
}
-func (u *FileUploadHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+func (u *FileDashUploadHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
utils.GetUploadLogger().Infof("Received upload request\n")
- curFileURL := req.URL.EscapedPath()[len("/ldash"):]
+ curFileURL := req.URL.EscapedPath()[len("/dash"):]
vars := mux.Vars(req)
folder := vars["folder"]
curFolderPath := path.Join(u.BaseDir, folder)
@@ -27,7 +27,7 @@ func (u *FileUploadHandler) ServeHTTP(w http.ResponseWriter, req *http.Request)
u.serveHTTPImpl(curFolderPath, curFilePath, w, req)
}
-func (u *FileUploadHandler) serveHTTPImpl(curFolderPath string, curFilePath string, w http.ResponseWriter, req *http.Request) {
+func (u *FileDashUploadHandler) serveHTTPImpl(curFolderPath string, curFilePath string, w http.ResponseWriter, req *http.Request) {
if _, err := os.Stat(curFolderPath); os.IsNotExist(err) {
err := os.MkdirAll(curFolderPath, os.ModePerm)
if err != nil {
diff --git a/handlers/fileuploadhandlerhls.go b/handlers/fileuploadhandlerhls.go
new file mode 100644
index 0000000..8c097b2
--- /dev/null
+++ b/handlers/fileuploadhandlerhls.go
@@ -0,0 +1,75 @@
+package handlers
+
+import (
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "path"
+ "time"
+
+ "streamline/utils"
+ "github.com/gorilla/mux"
+)
+
+// UploadHandler handles for http upload
+type FileHLSUploadHandler struct {
+ BaseDir string
+}
+
+func (u *FileHLSUploadHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ utils.GetUploadLogger().Infof("Received upload request\n")
+ curFileURL := req.URL.EscapedPath()[len("/hls"):]
+ vars := mux.Vars(req)
+ folder := vars["folder"]
+ curFolderPath := path.Join(u.BaseDir, folder)
+ curFilePath := path.Join(u.BaseDir, curFileURL)
+ u.serveHTTPImpl(curFolderPath, curFilePath, w, req)
+}
+
+func (u *FileHLSUploadHandler) serveHTTPImpl(curFolderPath string, curFilePath string, w http.ResponseWriter, req *http.Request) {
+ if _, err := os.Stat(curFolderPath); os.IsNotExist(err) {
+ err := os.MkdirAll(curFolderPath, os.ModePerm)
+ if err != nil {
+ utils.GetUploadLogger().Infof("fail to create file %v", err)
+ }
+ }
+
+ // rewrite, mostly for manifest file
+ if _, err := os.Stat(curFilePath); err == nil {
+ utils.GetUploadLogger().Debugf("rewrite file %s @ %v \n", curFilePath, time.Now().Format(time.RFC3339))
+ data, _ := ioutil.ReadAll(req.Body)
+ err = ioutil.WriteFile(curFilePath, data, 0644)
+ if err != nil {
+ utils.GetUploadLogger().Errorf("fail to create file %v \n", err)
+ }
+ return
+ }
+
+ // create, mostly for segment
+ // for segment, we will allow partial downloading during the uploading to save the time for player(this is what low latency meaning)
+ // So here uses Symlink as a signal to tell download handler whether the uploading is finished or not.
+ symlink := curFilePath + ".symlink"
+ os.Symlink(curFilePath, symlink)
+ utils.GetUploadLogger().Debugf("create symlink %s @ %v \n", symlink, time.Now().Format(time.RFC3339))
+
+
+ f, rerr := os.Create(curFilePath)
+ if rerr != nil {
+ utils.GetUploadLogger().Errorf("fail to create file %s : %v\n", curFilePath, rerr)
+ return
+ }
+
+ utils.GetUploadLogger().Debugf("create file %s @ %v \n", curFilePath, time.Now().Format(time.RFC3339))
+ defer f.Close()
+
+ _, rerr = io.Copy(f, req.Body)
+ if rerr != nil {
+ utils.GetUploadLogger().Errorf("fail to create file %v \n", rerr)
+ }
+
+ // remove symlink once the uploading is done
+ os.Remove(symlink)
+ utils.GetUploadLogger().Debugf("remove symlink %s @ %v \n", symlink, time.Now().Format(time.RFC3339))
+
+}
diff --git a/killAll.sh b/killAll.sh
deleted file mode 100755
index 91e73d9..0000000
--- a/killAll.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-pkill main
-pkill ffmpeg
-
-echo All processes have been killed ☠
diff --git a/launchEncoderTestPattern.sh b/launchEncoderTestPattern.sh
deleted file mode 100755
index 259d29b..0000000
--- a/launchEncoderTestPattern.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/bash
-
-if [ -z "$1" ]; then
- TARGETSERVER="127.0.0.1"
- echo "Target Server not specified, assuming ${TARGETSERVER}..."
-else
- TARGETSERVER="$1"
-fi
-
-if [ -z "$2" ]; then
- STREAMID="1234"
- echo "Target Path not specified, assuming ${STREAMID}..."
-else
- STREAMID="$2"
-fi
-
-echo Oh 💩 here we go!
-echo View your stream at http://${TARGETSERVER}:8080/ldashplay/${STREAMID}/manifest.mpd
-
-# Encoding settings for x264 (CPU based encoder)
-
-x264enc='libx264 -tune zerolatency -profile:v high -preset veryfast -bf 0 -refs 3 -sc_threshold 0'
-
-ffmpeg/ffmpeg \
- -hide_banner \
- -re \
- -f lavfi \
- -i "testsrc2=size=1920x1080:rate=30" \
- -pix_fmt yuv420p \
- -map 0:v \
- -c:v ${x264enc} \
- -g 150 \
- -keyint_min 150 \
- -b:v 4000k \
- -vf "fps=30,drawtext=fontfile=utils/OpenSans-Bold.ttf:box=1:fontcolor=black:boxcolor=white:fontsize=100':x=40:y=400:textfile=utils/text.txt" \
- -method PUT \
- -seg_duration 5 \
- -streaming 1 \
- -http_persistent 1 \
- -utc_timing_url "https://time.akamai.com/?iso" \
- -index_correction 1 \
- -use_timeline 0 \
- -media_seg_name 'chunk-stream-$RepresentationID$-$Number%05d$.m4s' \
- -init_seg_name 'init-stream1-$RepresentationID$.m4s' \
- -window_size 5 \
- -extra_window_size 10 \
- -remove_at_exit 1 \
- -adaptation_sets "id=0,streams=v id=1,streams=a" \
- -f dash \
- http://${TARGETSERVER}:8080/ldash/${STREAMID}/manifest.mpd >/dev/null 2>logs/encode.log &
diff --git a/launchEncoderWebCam.sh b/launchEncoderWebCam.sh
deleted file mode 100755
index 5119a88..0000000
--- a/launchEncoderWebCam.sh
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/bin/bash
-
-if [ -z "$1" ]; then
- TARGETSERVER="127.0.0.1"
- echo "Target Server not specified, assuming ${TARGETSERVER}..."
-else
- TARGETSERVER="$1"
-fi
-
-if [ -z "$2" ]; then
- STREAMID="1234"
- echo "Target Path not specified, assuming ${STREAMID}..."
-else
- STREAMID="$2"
-fi
-
-echo Oh 💩 here we go!
-echo View your stream at http://${TARGETSERVER}:8080/ldashplay/${STREAMID}/manifest.mpd
-
-input='-f lavfi -i testsrc2=size=1920x1080:rate=30 -pix_fmt yuv420p'
-
-if [ "$(uname)" == "Darwin" ]; then
- # Use Apple Mac hardware encoder
- echo Using hardware encoder
- x264enc='h264_videotoolbox -profile:v main'
-
- #using Apple hardware webcam
- input='-f avfoundation -video_size 2048x1536 -framerate 20 -i 1'
-else
- # Encoding settings for x264 (CPU based encoder)
- echo Using software encoder
- x264enc='libx264 -tune zerolatency -profile:v high -preset veryfast -bf 0 -refs 3 -sc_threshold 0'
-fi
-
-ffmpeg/ffmpeg \
- -hide_banner \
- -re \
- ${input} \
- -map 0:v \
- -c:v ${x264enc} \
- -g 150 \
- -keyint_min 150 \
- -b:v 4000k \
- -vf "fps=30,drawtext=fontfile=utils/OpenSans-Bold.ttf:box=1:fontcolor=black:boxcolor=white:fontsize=100':x=40:y=500:textfile=utils/text.txt" \
- -method PUT \
- -seg_duration 5 \
- -streaming 1 \
- -http_persistent 1 \
- -utc_timing_url "https://time.akamai.com/?iso" \
- -index_correction 1 \
- -use_timeline 0 \
- -media_seg_name 'chunk-stream-$RepresentationID$-$Number%05d$.m4s' \
- -init_seg_name 'init-stream1-$RepresentationID$.m4s' \
- -window_size 5 \
- -extra_window_size 10 \
- -remove_at_exit 1 \
- -adaptation_sets "id=0,streams=v id=1,streams=a" \
- -f dash \
- http://${TARGETSERVER}:8080/ldash/${STREAMID}/manifest.mpd
-
diff --git a/launchServer.sh b/launchServer.sh
deleted file mode 100755
index 76b39fa..0000000
--- a/launchServer.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-go/bin/go run main.go "./www" 2>logs/server.log &
diff --git a/main.go b/main.go
index 4d06d41..058d0a6 100644
--- a/main.go
+++ b/main.go
@@ -7,8 +7,8 @@ import (
"path/filepath"
"time"
- "github.com/streamlinevideo/low-latency-preview/handlers"
- "github.com/streamlinevideo/low-latency-preview/utils"
+ "streamline/handlers"
+ "streamline/utils"
"github.com/gorilla/mux"
"github.com/rs/cors"
)
@@ -31,12 +31,12 @@ func main() {
// clean the segment folder
utils.RemoveContents(args[0])
- file_downloadHandler := &handlers.FileDownloadHandler{
+ file_dashdownloadHandler := &handlers.FileDashDownloadHandler{
StartTime: time.Now(),
BaseDir: filePath,
}
- file_uploadHandler := &handlers.FileUploadHandler{
+ file_dashuploadHandler := &handlers.FileDashUploadHandler{
BaseDir: filePath,
}
@@ -44,16 +44,32 @@ func main() {
BaseDir: filePath,
}
- file_deleteHandler := &handlers.FileDeleteHandler{
+ file_dashdeleteHandler := &handlers.FileDashDeleteHandler{
+ BaseDir: filePath,
+ }
+
+ file_hlsdownloadHandler := &handlers.FileHLSDownloadHandler{
+ StartTime: time.Now(),
+ BaseDir: filePath,
+ }
+
+ file_hlsuploadHandler := &handlers.FileHLSUploadHandler{
+ BaseDir: filePath,
+ }
+
+ file_hlsdeleteHandler := &handlers.FileHLSDeleteHandler{
BaseDir: filePath,
}
r := mux.NewRouter()
- r.Handle("/ldash/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", file_uploadHandler).Methods("PUT", "POST")
- r.Handle("/ldash/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", file_downloadHandler).Methods("GET")
- r.Handle("/ldash/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", file_deleteHandler).Methods("DELETE")
- r.Handle("/ldashplay/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", dash_playHandler)
+ r.Handle("/dash/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", file_dashuploadHandler).Methods("PUT", "POST")
+ r.Handle("/dash/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", file_dashdownloadHandler).Methods("GET")
+ r.Handle("/dash/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", file_dashdeleteHandler).Methods("DELETE")
+ r.Handle("/dashplay/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", dash_playHandler)
+ r.Handle("/hls/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", file_hlsuploadHandler).Methods("PUT", "POST")
+ r.Handle("/hls/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", file_hlsdownloadHandler).Methods("GET")
+ r.Handle("/hls/{folder}/{name:[a-zA-Z0-9/_-]+}.{name:[a-zA-Z0-9/_-]+}", file_hlsdeleteHandler).Methods("DELETE")
r.Handle("/", dash_playHandler)
// KJSL: Adding CORS
diff --git a/streamline.exe b/streamline.exe
new file mode 100644
index 0000000..1233187
Binary files /dev/null and b/streamline.exe differ
diff --git a/utils/OpenSans-Bold.ttf b/utils/OpenSans-Bold.ttf
deleted file mode 100644
index fd79d43..0000000
Binary files a/utils/OpenSans-Bold.ttf and /dev/null differ
diff --git a/utils/text.txt b/utils/text.txt
deleted file mode 100644
index 25d34da..0000000
--- a/utils/text.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Encoder time
-%{localtime:%M}:%{localtime:%S }:%{eif:1M*t-1K*trunc(t*1K):d}