Compare commits

...
Author SHA1 Message Date
LogalDeveloper 764e41f2b7 Fixed thumbnail generator using wrong init segment filename for multi-variant streams.
Automated API tests / test (push) Failing after 6s
Browser Tests / cypress-run (push) Failing after 5s
Lint / Go linter (push) Failing after 4s
HLS tests / tests (push) Failing after 5s
Go Tests / test (push) Has been cancelled
Go Tests / test-bsds (map[name:freebsd version:12.2]) (push) Has been cancelled
Go Tests / test-bsds (map[name:openbsd version:6.8]) (push) Has been cancelled
2026-04-03 15:49:45 -04:00
LogalDeveloper 84cd880753 Fixed offline master playlist not being processed by the storage provider.
Automated API tests / test (push) Failing after 6s
Browser Tests / cypress-run (push) Failing after 5s
Lint / Go linter (push) Failing after 4s
HLS tests / tests (push) Failing after 5s
Go Tests / test (push) Has been cancelled
Go Tests / test-bsds (map[name:freebsd version:12.2]) (push) Has been cancelled
Go Tests / test-bsds (map[name:openbsd version:6.8]) (push) Has been cancelled
2026-04-03 14:22:25 -04:00
LogalDeveloper 20c52a51ae Replaced per-request map allocations with a switch statement in cache duration function.
Automated API tests / test (push) Failing after 5s
Browser Tests / cypress-run (push) Failing after 4s
Lint / Go linter (push) Failing after 3s
HLS tests / tests (push) Failing after 5s
Go Tests / test (push) Has been cancelled
Go Tests / test-bsds (map[name:freebsd version:12.2]) (push) Has been cancelled
Go Tests / test-bsds (map[name:openbsd version:6.8]) (push) Has been cancelled
2026-04-03 13:39:52 -04:00
LogalDeveloper 6b93ac0d78 Fixed segment cleanup deleting init.mp4 and reduced its cache duration to 20 seconds.
Automated API tests / test (push) Failing after 5s
Browser Tests / cypress-run (push) Failing after 5s
Lint / Go linter (push) Failing after 4s
HLS tests / tests (push) Failing after 5s
Go Tests / test (push) Has been cancelled
Go Tests / test-bsds (map[name:freebsd version:12.2]) (push) Has been cancelled
Go Tests / test-bsds (map[name:openbsd version:6.8]) (push) Has been cancelled
2026-04-03 09:52:15 -04:00
LogalDeveloper e0673b084b Fixed linter errors in offline state and cache duration functions. 2026-04-02 09:21:55 -04:00
7 changed files with 39 additions and 16 deletions
+7 -1
View File
@@ -129,7 +129,6 @@ func transitionToOfflineVideoStreamContent() {
if err != nil { if err != nil {
log.Errorln("unable to create master playlist:", err) log.Errorln("unable to create master playlist:", err)
} else { } else {
defer masterFile.Close()
_, _ = masterFile.WriteString("#EXTM3U\n") _, _ = masterFile.WriteString("#EXTM3U\n")
_, _ = masterFile.WriteString("#EXT-X-VERSION:7\n") _, _ = masterFile.WriteString("#EXT-X-VERSION:7\n")
_, _ = masterFile.WriteString("#EXT-X-INDEPENDENT-SEGMENTS\n") _, _ = masterFile.WriteString("#EXT-X-INDEPENDENT-SEGMENTS\n")
@@ -137,6 +136,13 @@ func transitionToOfflineVideoStreamContent() {
_, _ = fmt.Fprintf(masterFile, "#EXT-X-STREAM-INF:BANDWIDTH=0\n") _, _ = fmt.Fprintf(masterFile, "#EXT-X-STREAM-INF:BANDWIDTH=0\n")
_, _ = fmt.Fprintf(masterFile, "%d/stream.m3u8\n", index) _, _ = fmt.Fprintf(masterFile, "%d/stream.m3u8\n", index)
} }
if err := masterFile.Close(); err != nil {
log.Errorln("unable to close master playlist:", err)
}
// Notify the storage provider so it can rewrite variant URLs
// to absolute paths for S3 or remote serving endpoints.
_storage.MasterPlaylistWritten(masterPlaylistPath)
} }
// Copy the logo to be the thumbnail // Copy the logo to be the thumbnail
+6 -2
View File
@@ -112,7 +112,9 @@ func saveOfflineFMP4ToDisk() (initPath string, segmentPath string, err error) {
return "", "", fmt.Errorf("unable to write offline init segment to disk: %s", err) return "", "", fmt.Errorf("unable to write offline init segment to disk: %s", err)
} }
initTmp.Close() if err := initTmp.Close(); err != nil {
return "", "", fmt.Errorf("unable to close offline init segment: %s", err)
}
initPath, _ = filepath.Abs(initTmp.Name()) initPath, _ = filepath.Abs(initTmp.Name())
segData := static.GetOfflineMediaSegment() segData := static.GetOfflineMediaSegment()
@@ -125,7 +127,9 @@ func saveOfflineFMP4ToDisk() (initPath string, segmentPath string, err error) {
return "", "", fmt.Errorf("unable to write offline media segment to disk: %s", err) return "", "", fmt.Errorf("unable to write offline media segment to disk: %s", err)
} }
segTmp.Close() if err := segTmp.Close(); err != nil {
return "", "", fmt.Errorf("unable to close offline media segment: %s", err)
}
segmentPath, _ = filepath.Abs(segTmp.Name()) segmentPath, _ = filepath.Abs(segTmp.Name())
return initPath, segmentPath, nil return initPath, segmentPath, nil
+1 -1
View File
@@ -82,7 +82,7 @@ func getAllFilesRecursive(baseDirectory string) (map[string][]os.FileInfo, error
directory = info.Name() directory = info.Name()
} }
if filepath.Ext(info.Name()) == ".m4s" || filepath.Ext(info.Name()) == ".mp4" { if filepath.Ext(info.Name()) == ".m4s" {
files[directory] = append(files[directory], info) files[directory] = append(files[directory], info)
} }
+1 -1
View File
@@ -317,7 +317,7 @@ func (s *S3Storage) retrieveAllVideoSegments() ([]s3object, error) {
err := s.s3Client.ListObjectsPages(allObjectsListRequest, err := s.s3Client.ListObjectsPages(allObjectsListRequest,
func(page *s3.ListObjectsOutput, lastPage bool) bool { func(page *s3.ListObjectsOutput, lastPage bool) bool {
for _, item := range page.Contents { for _, item := range page.Contents {
if strings.HasSuffix(*item.Key, ".m4s") || strings.HasSuffix(*item.Key, ".mp4") { if strings.HasSuffix(*item.Key, ".m4s") {
allObjects = append(allObjects, s3object{ allObjects = append(allObjects, s3object{
key: *item.Key, key: *item.Key,
lastModified: *item.LastModified, lastModified: *item.LastModified,
+12 -1
View File
@@ -89,8 +89,19 @@ func fireThumbnailGenerator(segmentPath string, variantIndex int) error {
return nil return nil
} }
configRepository := configrepository.Get() configRepository := configrepository.Get()
initSegment := path.Join(framePath, "init.mp4") // With multiple variants ffmpeg names init segments init_0.mp4, init_1.mp4, etc.
// With a single variant it uses init.mp4.
initSegment := path.Join(framePath, fmt.Sprintf("init_%d.mp4", variantIndex))
if !utils.DoesFileExists(initSegment) {
initSegment = path.Join(framePath, "init.mp4")
}
mostRecentFile := path.Join(framePath, names[0]) mostRecentFile := path.Join(framePath, names[0])
// The segment may have been cleaned up between ReadDir and now.
if !utils.DoesFileExists(mostRecentFile) {
return nil
}
// fMP4 segments require the init segment to be readable by ffmpeg // fMP4 segments require the init segment to be readable by ffmpeg
inputArg := fmt.Sprintf("concat:%s|%s", initSegment, mostRecentFile) inputArg := fmt.Sprintf("concat:%s|%s", initSegment, mostRecentFile)
ffmpegPath := utils.ValidatedFfmpegPath(configRepository.GetFfMpegPath()) ffmpegPath := utils.ValidatedFfmpegPath(configRepository.GetFfMpegPath())
BIN
View File
Binary file not shown.
+12 -10
View File
@@ -215,23 +215,25 @@ func GetCacheDurationSecondsForPath(filePath string) int {
defaultDaysCached := 30 defaultDaysCached := 30
if filename == "thumbnail.jpg" || filename == "preview.gif" { if filename == "thumbnail.jpg" || filename == "preview.gif" || filename == "init.mp4" {
// Thumbnails & preview gif re-generate during live // Thumbnails & preview gif re-generate during live
return 20 return 20
} else if fileExtension == ".js" || fileExtension == ".css" { }
// Cache javascript & CSS
return 60 * 60 * 24 * defaultDaysCached if filename == "/" || fileExtension == "" {
} else if fileExtension == ".m4s" || fileExtension == ".mp4" || fileExtension == ".woff2" { return 0
}
switch fileExtension {
case ".m3u8", ".html":
return 0
case ".m4s", ".mp4", ".woff2":
// Cache video segments as long as you want. They can't change. // Cache video segments as long as you want. They can't change.
// This matters most for local hosting of segments for recordings // This matters most for local hosting of segments for recordings
// and not for live or 3rd party storage. // and not for live or 3rd party storage.
return 31557600 return 31557600
} else if fileExtension == ".m3u8" { case ".js", ".css", ".jpg", ".png", ".gif", ".svg":
return 0
} else if fileExtension == ".jpg" || fileExtension == ".png" || fileExtension == ".gif" || fileExtension == ".svg" {
return 60 * 60 * 24 * defaultDaysCached return 60 * 60 * 24 * defaultDaysCached
} else if fileExtension == ".html" || filename == "/" || fileExtension == "" {
return 0
} }
// Default cache length in seconds // Default cache length in seconds