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