parent
ff20dd1137
commit
9d87143a95
@ -1,8 +1,5 @@ |
||||
GO_IS_STUPID_EXE=
|
||||
|
||||
ifeq '$(OS)' 'Windows_NT' |
||||
GO_IS_STUPID_EXE=.exe
|
||||
endif |
||||
|
||||
build: |
||||
go build .
|
||||
|
||||
install: build |
||||
sudo cp vidcrunch /usr/local/bin/
|
||||
|
||||
@ -1,128 +1,139 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"path/filepath" |
||||
"runtime" |
||||
"log" |
||||
"os" |
||||
"math/rand" |
||||
"strings" |
||||
"lcthw.dev/go/vidcrunch/config" |
||||
"github.com/modfy/fluent-ffmpeg" |
||||
"fmt" |
||||
"path/filepath" |
||||
"runtime" |
||||
"log" |
||||
"os" |
||||
"math/rand" |
||||
"net/http" |
||||
"strings" |
||||
"lcthw.dev/go/vidcrunch/config" |
||||
"github.com/modfy/fluent-ffmpeg" |
||||
) |
||||
|
||||
func ModFile(fname string, encoding config.VideoOpts) string { |
||||
cleaned := filepath.Clean(fname) |
||||
dir, file := filepath.Split(cleaned) |
||||
ext := filepath.Ext(file) |
||||
cleaned := filepath.Clean(fname) |
||||
dir, file := filepath.Split(cleaned) |
||||
ext := filepath.Ext(file) |
||||
|
||||
base, found := strings.CutSuffix(file, ext) |
||||
if !found { panic("no extension found?!") } |
||||
base, found := strings.CutSuffix(file, ext) |
||||
if !found { panic("no extension found?!") } |
||||
|
||||
dim := strings.Replace(encoding.Scale, ":", ".", 1) |
||||
renamed := fmt.Sprint(base, ".", dim, ".", encoding.Format) |
||||
return filepath.Join(dir, renamed) |
||||
dim := strings.Replace(encoding.Scale, ":", ".", 1) |
||||
renamed := fmt.Sprint(base, ".", dim, ".", encoding.Format) |
||||
return filepath.Join(dir, renamed) |
||||
} |
||||
|
||||
func Run(encoding config.VideoOpts, pass int, pid int, input string, output string) { |
||||
encode := fluentffmpeg.NewCommand("") |
||||
|
||||
extras := []string{ |
||||
"-pix_fmt", "yuv420p", |
||||
"-pass", fmt.Sprint(pass), |
||||
"-passlogfile", fmt.Sprintf("ffmpegpass-%x.log", pid), |
||||
} |
||||
|
||||
if encoding.Preset != "" { |
||||
extras = append(extras, "-preset", encoding.Preset) |
||||
} |
||||
|
||||
if encoding.Resize { |
||||
extras = append(extras, |
||||
"-vf", fmt.Sprintf("scale=%s:flags=lanczos", encoding.Scale), |
||||
"-aspect", encoding.Scale) |
||||
} |
||||
|
||||
if pass != encoding.Passes { |
||||
extras = append(extras, "-an") |
||||
} else { |
||||
encode.AudioCodec(encoding.AudioCodec) |
||||
extras = append(extras, |
||||
"-b:a", fmt.Sprint(encoding.AudioBitrate * 1024)) |
||||
} |
||||
|
||||
if encoding.Test > 0 { |
||||
encode.InputOptions( |
||||
"-ss", fmt.Sprintf("00:%d", encoding.TestStart)) |
||||
extras = append(extras, "-t", fmt.Sprint(encoding.Test)) |
||||
} |
||||
|
||||
encode.VideoCodec(encoding.VideoCodec). |
||||
VideoBitRate(encoding.VideoBitrate * 1024). |
||||
FrameRate(encoding.FPS). |
||||
ConstantRateFactor(encoding.CRF) |
||||
|
||||
extras = append(extras, encoding.Extras...) |
||||
encode.OutputOptions(extras...) |
||||
|
||||
cmd := encode.InputPath(input). |
||||
OutputFormat(encoding.Format). |
||||
OutputPath(output). |
||||
encode := fluentffmpeg.NewCommand("") |
||||
|
||||
extras := []string{ |
||||
"-pix_fmt", "yuv420p", |
||||
"-pass", fmt.Sprint(pass), |
||||
"-passlogfile", fmt.Sprintf("ffmpegpass-%x.log", pid), |
||||
} |
||||
|
||||
if encoding.Preset != "" { |
||||
extras = append(extras, "-preset", encoding.Preset) |
||||
} |
||||
|
||||
if encoding.Resize { |
||||
extras = append(extras, |
||||
"-vf", fmt.Sprintf("scale=%s:flags=lanczos", encoding.Scale), |
||||
"-aspect", encoding.Scale) |
||||
} |
||||
|
||||
if pass != encoding.Passes { |
||||
extras = append(extras, "-an") |
||||
} else { |
||||
encode.AudioCodec(encoding.AudioCodec) |
||||
extras = append(extras, |
||||
"-b:a", fmt.Sprint(encoding.AudioBitrate * 1024)) |
||||
} |
||||
|
||||
if encoding.Test > 0 { |
||||
encode.InputOptions("-ss", fmt.Sprintf("00:%d", encoding.TestStart)) |
||||
extras = append(extras, "-t", fmt.Sprint(encoding.Test)) |
||||
} |
||||
|
||||
encode.VideoCodec(encoding.VideoCodec). |
||||
VideoBitRate(encoding.VideoBitrate * 1024). |
||||
FrameRate(encoding.FPS). |
||||
ConstantRateFactor(encoding.CRF) |
||||
|
||||
extras = append(extras, encoding.Extras...) |
||||
encode.OutputOptions(extras...) |
||||
|
||||
cmd := encode.InputPath(input). |
||||
OutputFormat(encoding.Format). |
||||
OutputPath(output). |
||||
OutputLogs(os.Stdout). |
||||
Overwrite(true). |
||||
Build() |
||||
Build() |
||||
|
||||
fmt.Println(">", cmd.String()) |
||||
fmt.Println(">", cmd.String()) |
||||
|
||||
err := cmd.Run() |
||||
if err != nil { log.Fatalf("%v", err) } |
||||
err := cmd.Run() |
||||
if err != nil { log.Fatalf("%v", err) } |
||||
} |
||||
|
||||
func DevNull() string { |
||||
if runtime.GOOS == "windows" { |
||||
return "NUL" |
||||
} else { |
||||
return "/dev/null" |
||||
} |
||||
if runtime.GOOS == "windows" { |
||||
return "NUL" |
||||
} else { |
||||
return "/dev/null" |
||||
} |
||||
} |
||||
|
||||
func RenderFile(encoding config.VideoOpts, pid int, path string, target string) { |
||||
for i := 1; i < encoding.Passes; i++ { |
||||
Run(encoding, i, pid, path, DevNull()) |
||||
} |
||||
for i := 1; i < encoding.Passes; i++ { |
||||
Run(encoding, i, pid, path, DevNull()) |
||||
} |
||||
|
||||
Run(encoding, encoding.Passes, pid, path, target) |
||||
Run(encoding, encoding.Passes, pid, path, target) |
||||
} |
||||
|
||||
func RenderToDir(encoding config.VideoOpts, force bool) { |
||||
matches, err := filepath.Glob(encoding.Input) |
||||
if err != nil { log.Fatalf("%v", err) } |
||||
|
||||
for _, path := range matches { |
||||
base := filepath.Base(path) |
||||
target := filepath.Join(encoding.OutDir, base) |
||||
target = ModFile(target, encoding) |
||||
|
||||
_, err := os.Stat(target) |
||||
|
||||
if err != nil || force { |
||||
fmt.Println("--- PATH", path, "->", target) |
||||
RenderFile(encoding, rand.Int(), path, target) |
||||
} else { |
||||
fmt.Println("^^^ SKIP", path, "->", target) |
||||
} |
||||
} |
||||
matches, err := filepath.Glob(encoding.Input) |
||||
if err != nil { log.Fatalf("%v", err) } |
||||
|
||||
for _, path := range matches { |
||||
base := filepath.Base(path) |
||||
target := filepath.Join(encoding.OutDir, base) |
||||
target = ModFile(target, encoding) |
||||
|
||||
_, err := os.Stat(target) |
||||
|
||||
if err != nil || force { |
||||
fmt.Println("--- PATH", path, "->", target) |
||||
RenderFile(encoding, rand.Int(), path, target) |
||||
} else { |
||||
fmt.Println("^^^ SKIP", path, "->", target) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func main() { |
||||
settings := config.Load() |
||||
|
||||
for _, encoding := range settings.Encodings { |
||||
if encoding.OutDir != "" { |
||||
RenderToDir(encoding, settings.Force) |
||||
} else { |
||||
log.Fatal("config file needs either Output or OutDir") |
||||
} |
||||
} |
||||
settings := config.Load() |
||||
|
||||
if settings.Serve != "" { |
||||
dir_handler := http.FileServer(http.Dir(settings.Serve)) |
||||
|
||||
http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) { |
||||
fmt.Println(r.Method, r.URL) |
||||
dir_handler.ServeHTTP(w, r) |
||||
}) |
||||
|
||||
log.Fatal(http.ListenAndServe(settings.Port, nil)) |
||||
} else { |
||||
for _, encoding := range settings.Encodings { |
||||
if encoding.OutDir != "" { |
||||
RenderToDir(encoding, settings.Force) |
||||
} else { |
||||
log.Fatal("config file needs either Output or OutDir") |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
Loading…
Reference in new issue