Add native support for Windows (#4491)

* Add support for Windows

* Fixes for Windows

* Update unit tests

* Fix ffreport setting

* Add test script equivalents

* Fix fontconfig error in test stream

* Fix thumbnail generator

* Fix lint warnings

* Fix warnings in test stream script

* Implement cross-platform ocTestStream

* Migrate to cross-platform script

* Revert ocTestStream.sh

* Add missing EOL

* Alternative test scripts for non-linux environments

---------

Co-authored-by: Gabe Kangas <gabek@real-ity.com>
This commit is contained in:
Nicholas Kwan
2025-10-13 15:55:13 -07:00
committed by GitHub
co-authored by Gabe Kangas
parent f30b80d473
commit fd89c6e8f2
13 changed files with 590 additions and 169 deletions
+17 -17
View File
@@ -13,6 +13,7 @@ import (
"path"
"path/filepath"
"regexp"
"runtime"
"strings"
"time"
@@ -38,7 +39,7 @@ func DoesFileExists(name string) bool {
// GetRelativePathFromAbsolutePath gets the relative path from the provided absolute path.
func GetRelativePathFromAbsolutePath(path string) string {
pathComponents := strings.Split(path, "/")
pathComponents := strings.Split(path, string(os.PathSeparator))
variant := pathComponents[len(pathComponents)-2]
file := pathComponents[len(pathComponents)-1]
@@ -47,7 +48,7 @@ func GetRelativePathFromAbsolutePath(path string) string {
// GetIndexFromFilePath is a utility that will return the index/key/variant name in a full path.
func GetIndexFromFilePath(path string) string {
pathComponents := strings.Split(path, "/")
pathComponents := strings.Split(path, string(os.PathSeparator))
variant := pathComponents[len(pathComponents)-2]
return variant
@@ -259,22 +260,18 @@ func ValidatedFfmpegPath(ffmpegPath string) string {
log.Warnln(ffmpegPath, "is an invalid path to ffmpeg will try to use a copy in your path, if possible")
}
// First look to see if ffmpeg is in the current working directory
localCopy := "./ffmpeg"
hasLocalCopyError := VerifyFFMpegPath(localCopy)
if hasLocalCopyError == nil {
// No error, so all is good. Use the local copy.
return localCopy
}
cmd := exec.Command("which", "ffmpeg")
out, err := cmd.CombinedOutput()
if err != nil {
// Look for ffmpeg in the system path or in the current working directory.
ffmpegPath, err := exec.LookPath("ffmpeg")
if ffmpegPath == "" || (err != nil && !errors.Is(err, exec.ErrDot)) || VerifyFFMpegPath(ffmpegPath) != nil {
log.Fatalln("Unable to locate ffmpeg. Either install it globally on your system or put the ffmpeg binary in the same directory as Owncast. The binary must be named ffmpeg.")
}
path := strings.TrimSpace(string(out))
return path
// Resolve to an absolute path.
absPath, err := filepath.Abs(ffmpegPath)
if err != nil {
return ffmpegPath
}
return absPath
}
// VerifyFFMpegPath verifies that the path exists, is a file, and is executable.
@@ -293,9 +290,12 @@ func VerifyFFMpegPath(path string) error {
return errors.New("ffmpeg path can not be a folder")
}
mode := stat.Mode()
mode := stat.Mode().Perm()
// source: https://stackoverflow.com/a/60128480
if mode&0o111 == 0 {
// On Windows, Perm() omits the executable bit, only check on Unix-like systems.
// https://github.com/golang/go/issues/41809
if runtime.GOOS != "windows" && mode&0o111 == 0 {
return errors.New("ffmpeg path is not executable")
}