Buffer RTSP performance
This commit is contained in:
@@ -127,7 +127,7 @@ var Content = /** @class */ (function () {
|
|||||||
var cell = new Cell();
|
var cell = new Cell();
|
||||||
cell.child = true;
|
cell.child = true;
|
||||||
cell.childType = "P";
|
cell.childType = "P";
|
||||||
if (SERVER["settings"]["buffer"] == true) {
|
if (SERVER["settings"]["buffer"] != "-") {
|
||||||
cell.value = data[key]["tuner"];
|
cell.value = data[key]["tuner"];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
186
src/buffer.go
186
src/buffer.go
@@ -473,6 +473,7 @@ func killClientConnection(streamID int, playlistID string, force bool) {
|
|||||||
if clients.Connection <= 0 {
|
if clients.Connection <= 0 {
|
||||||
BufferClients.Delete(playlistID + stream.MD5)
|
BufferClients.Delete(playlistID + stream.MD5)
|
||||||
delete(playlist.Streams, streamID)
|
delete(playlist.Streams, streamID)
|
||||||
|
delete(playlist.Clients, streamID)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1344,9 +1345,11 @@ func bufferWithFfmpeg(streamID int, playlistID string) {
|
|||||||
var playlist = p.(Playlist)
|
var playlist = p.(Playlist)
|
||||||
var debug, path, options, bufferType string
|
var debug, path, options, bufferType string
|
||||||
var tmpSegment = 1
|
var tmpSegment = 1
|
||||||
var fileSize = 0
|
var bufferSize = Settings.BufferSize * 1024
|
||||||
var stream = playlist.Streams[streamID]
|
var stream = playlist.Streams[streamID]
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
var fileSize = 0
|
||||||
|
var streamStatus = make(chan bool)
|
||||||
|
|
||||||
var tmpFolder = playlist.Streams[streamID].Folder
|
var tmpFolder = playlist.Streams[streamID].Folder
|
||||||
var url = playlist.Streams[streamID].URL
|
var url = playlist.Streams[streamID].URL
|
||||||
@@ -1392,25 +1395,13 @@ func bufferWithFfmpeg(streamID int, playlistID string) {
|
|||||||
|
|
||||||
showInfo("Streaming URL:" + stream.URL)
|
showInfo("Streaming URL:" + stream.URL)
|
||||||
|
|
||||||
// Größe des Buffers
|
|
||||||
buffer := make([]byte, 1024*Settings.BufferSize*2)
|
|
||||||
var tmpFileSize = 1024 * Settings.BufferSize * 1
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("Buffer Size:%d KB [SERVER CONNECTION]", len(buffer)/1024)
|
|
||||||
showDebug(debug, 3)
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("Buffer Size:%d KB [CLIENT CONNECTION]", tmpFileSize/1024)
|
|
||||||
showDebug(debug, 3)
|
|
||||||
|
|
||||||
var tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)
|
var tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)
|
||||||
|
|
||||||
bufferFile, err := os.Create(tmpFile)
|
f, err := os.Create(tmpFile)
|
||||||
|
f.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
addErrorToStream(err)
|
addErrorToStream(err)
|
||||||
bufferFile.Close()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var args = strings.Replace(options, "[URL]", url, -1)
|
var args = strings.Replace(options, "[URL]", url, -1)
|
||||||
@@ -1447,130 +1438,147 @@ func bufferWithFfmpeg(streamID int, playlistID string) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
||||||
// Log Daten vom Prozess im Dubug Mode 2 anzeigen.
|
// Log Daten vom Prozess im Dubug Mode 1 anzeigen.
|
||||||
scanner := bufio.NewScanner(logOut)
|
scanner := bufio.NewScanner(logOut)
|
||||||
scanner.Split(bufio.ScanLines)
|
scanner.Split(bufio.ScanLines)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
|
|
||||||
debug = fmt.Sprintf("%s:%s", bufferType, strings.TrimSpace(scanner.Text()))
|
debug = fmt.Sprintf("%s:%s", bufferType, strings.TrimSpace(scanner.Text()))
|
||||||
showDebug(debug, 1)
|
|
||||||
|
select {
|
||||||
|
case <-streamStatus:
|
||||||
|
showDebug(debug, 1)
|
||||||
|
default:
|
||||||
|
showInfo(debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Duration(10) * time.Millisecond)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
scanner := bufio.NewScanner(stdOut)
|
f, err = os.OpenFile(tmpFile, os.O_APPEND|os.O_WRONLY, 0600)
|
||||||
scanner.Split(bufio.ScanBytes)
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
for scanner.Scan() {
|
buffer := make([]byte, 1024*4)
|
||||||
|
|
||||||
if len(buf.Bytes()) == 0 && stream.Status == false {
|
reader := bufio.NewReader(stdOut)
|
||||||
showInfo("Streaming Status:Receive data from " + bufferType)
|
|
||||||
}
|
|
||||||
|
|
||||||
b := scanner.Bytes()
|
t := make(chan int)
|
||||||
|
|
||||||
for _, i := range b {
|
go func() {
|
||||||
buf.WriteByte(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fileSize = fileSize + len(b)
|
var timeout = 0
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Duration(100) * time.Millisecond)
|
||||||
|
timeout++
|
||||||
|
|
||||||
if clientConnection(stream) == false {
|
select {
|
||||||
|
case <-t:
|
||||||
cmd.Process.Kill()
|
return
|
||||||
bufferFile.Close()
|
default:
|
||||||
|
t <- timeout
|
||||||
err = os.RemoveAll(stream.Folder)
|
|
||||||
if err != nil {
|
|
||||||
ShowError(err, 4005)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Wait()
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileSize >= tmpFileSize/2 {
|
}()
|
||||||
|
|
||||||
if stream.Status == false {
|
for {
|
||||||
showInfo("Streaming Status:Buffering data from " + bufferType)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := bufferFile.Write(buf.Bytes()); err != nil {
|
|
||||||
|
|
||||||
|
select {
|
||||||
|
case timeout := <-t:
|
||||||
|
if timeout >= 20 && tmpSegment == 1 {
|
||||||
cmd.Process.Kill()
|
cmd.Process.Kill()
|
||||||
ShowError(err, 0)
|
err = errors.New("Timout")
|
||||||
|
ShowError(err, 4006)
|
||||||
addErrorToStream(err)
|
addErrorToStream(err)
|
||||||
cmd.Wait()
|
cmd.Wait()
|
||||||
|
f.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
debug = fmt.Sprintf("Buffer Status:Done (%s)", tmpFile)
|
default:
|
||||||
showDebug(debug, 2)
|
|
||||||
|
|
||||||
bufferFile.Close()
|
}
|
||||||
|
|
||||||
|
if fileSize == 0 && stream.Status == false {
|
||||||
|
showInfo("Streaming Status:Receive data from " + bufferType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if clientConnection(stream) == false {
|
||||||
|
cmd.Process.Kill()
|
||||||
|
f.Close()
|
||||||
|
cmd.Wait()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := reader.Read(buffer)
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
fileSize = fileSize + len(buffer[:n])
|
||||||
|
|
||||||
|
if _, err := f.Write(buffer[:n]); err != nil {
|
||||||
|
cmd.Process.Kill()
|
||||||
|
ShowError(err, 0)
|
||||||
|
addErrorToStream(err)
|
||||||
|
cmd.Wait()
|
||||||
|
f.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if fileSize >= bufferSize/2 {
|
||||||
|
|
||||||
|
if tmpSegment == 1 && stream.Status == false {
|
||||||
|
close(t)
|
||||||
|
close(streamStatus)
|
||||||
|
showInfo(fmt.Sprintf("Streaming Status:Buffering data from %s", bufferType))
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Close()
|
||||||
|
tmpSegment++
|
||||||
|
|
||||||
stream.Status = true
|
stream.Status = true
|
||||||
playlist.Streams[streamID] = stream
|
playlist.Streams[streamID] = stream
|
||||||
BufferInformation.Store(playlistID, playlist)
|
BufferInformation.Store(playlistID, playlist)
|
||||||
|
|
||||||
tmpSegment++
|
|
||||||
|
|
||||||
tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)
|
tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)
|
||||||
|
|
||||||
if clientConnection(stream) == false {
|
|
||||||
|
|
||||||
cmd.Process.Kill()
|
|
||||||
bufferFile.Close()
|
|
||||||
|
|
||||||
err = os.RemoveAll(stream.Folder)
|
|
||||||
if err != nil {
|
|
||||||
ShowError(err, 4005)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Wait()
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bufferFile, err = os.Create(tmpFile)
|
|
||||||
if err != nil {
|
|
||||||
|
|
||||||
addErrorToStream(err)
|
|
||||||
cmd.Process.Kill()
|
|
||||||
cmd.Wait()
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.Reset()
|
|
||||||
|
|
||||||
fileSize = 0
|
fileSize = 0
|
||||||
|
|
||||||
/*
|
var errCreate, errOpen error
|
||||||
if n == 0 {
|
f, errCreate = os.Create(tmpFile)
|
||||||
bufferFile.Close()
|
f, errOpen = os.OpenFile(tmpFile, os.O_APPEND|os.O_WRONLY, 0600)
|
||||||
run.Process.Kill()
|
if errCreate != nil || errOpen != nil {
|
||||||
break
|
cmd.Process.Kill()
|
||||||
}
|
ShowError(err, 0)
|
||||||
*/
|
addErrorToStream(err)
|
||||||
|
cmd.Wait()
|
||||||
|
f.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//cmd.Process.Kill()
|
cmd.Process.Kill()
|
||||||
cmd.Wait()
|
cmd.Wait()
|
||||||
|
|
||||||
err = errors.New(bufferType + " error")
|
err = errors.New(bufferType + " error")
|
||||||
addErrorToStream(err)
|
addErrorToStream(err)
|
||||||
ShowError(err, 1204)
|
ShowError(err, 1204)
|
||||||
|
|
||||||
time.Sleep(time.Duration(1000) * time.Millisecond)
|
time.Sleep(time.Duration(500) * time.Millisecond)
|
||||||
clientConnection(stream)
|
clientConnection(stream)
|
||||||
|
|
||||||
//os.Exit(0)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func Init() (err error) {
|
|||||||
|
|
||||||
// FFmpeg Default Einstellungen
|
// FFmpeg Default Einstellungen
|
||||||
System.FFmpeg.DefaultOptions = "-hide_banner -loglevel panic -i [URL] -c copy -f mpegts pipe:1"
|
System.FFmpeg.DefaultOptions = "-hide_banner -loglevel panic -i [URL] -c copy -f mpegts pipe:1"
|
||||||
System.VLC.DefaultOptions = "[URL] --sout #std{mux=ts,access=file,dst=-}"
|
System.VLC.DefaultOptions = "-I dummy [URL] --sout #std{mux=ts,access=file,dst=-}"
|
||||||
|
|
||||||
// Default Logeinträge, wird später von denen aus der settings.json überschrieben. Muss gemacht werden, damit die ersten Einträge auch im Log (webUI aangezeigt werden)
|
// Default Logeinträge, wird später von denen aus der settings.json überschrieben. Muss gemacht werden, damit die ersten Einträge auch im Log (webUI aangezeigt werden)
|
||||||
Settings.LogEntriesRAM = 500
|
Settings.LogEntriesRAM = 500
|
||||||
|
|||||||
@@ -355,6 +355,8 @@ func getErrMsg(errCode int) (errMsg string) {
|
|||||||
errMsg = fmt.Sprintf("This error message comes from the provider")
|
errMsg = fmt.Sprintf("This error message comes from the provider")
|
||||||
case 4005:
|
case 4005:
|
||||||
errMsg = fmt.Sprintf("Temporary buffer files could not be deleted")
|
errMsg = fmt.Sprintf("Temporary buffer files could not be deleted")
|
||||||
|
case 4006:
|
||||||
|
errMsg = fmt.Sprintf("Server connection timeout")
|
||||||
|
|
||||||
// Buffer (M3U8)
|
// Buffer (M3U8)
|
||||||
case 4050:
|
case 4050:
|
||||||
|
|||||||
@@ -130,7 +130,13 @@ func searchFileInOS(file string) (path string) {
|
|||||||
|
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
path = strings.Trim(string(out), "\r\n")
|
|
||||||
|
var slice = strings.Split(strings.Replace(string(out), "\r\n", "\n", -1), "\n")
|
||||||
|
|
||||||
|
if len(slice) > 0 {
|
||||||
|
path = strings.Trim(slice[0], "\r\n")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
73
src/webUI.go
73
src/webUI.go
File diff suppressed because one or more lines are too long
@@ -147,7 +147,7 @@ class Content {
|
|||||||
var cell:Cell = new Cell()
|
var cell:Cell = new Cell()
|
||||||
cell.child = true
|
cell.child = true
|
||||||
cell.childType = "P"
|
cell.childType = "P"
|
||||||
if (SERVER["settings"]["buffer"] == true) {
|
if (SERVER["settings"]["buffer"] != "-") {
|
||||||
cell.value = data[key]["tuner"]
|
cell.value = data[key]["tuner"]
|
||||||
} else {
|
} else {
|
||||||
cell.value = "-"
|
cell.value = "-"
|
||||||
|
|||||||
4
xteve.go
4
xteve.go
@@ -35,11 +35,11 @@ var GitHub = GitHubStruct{Branch: "master", User: "xteve-project", Repo: "xTeVe-
|
|||||||
Update: Automatic updates from the GitHub repository [true|false]
|
Update: Automatic updates from the GitHub repository [true|false]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Name : Programname
|
// Name : Programmname
|
||||||
const Name = "xTeVe"
|
const Name = "xTeVe"
|
||||||
|
|
||||||
// Version : Version, die Build Nummer wird in der main func geparst.
|
// Version : Version, die Build Nummer wird in der main func geparst.
|
||||||
const Version = "2.0.3.0036"
|
const Version = "2.0.3.0041"
|
||||||
|
|
||||||
// DBVersion : Datanbank Version
|
// DBVersion : Datanbank Version
|
||||||
const DBVersion = "2.1.0"
|
const DBVersion = "2.1.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user