[BREAKING] Can do a single video to a dash directory, but need to make it work on many videos.

master
Zed A. Shaw 4 weeks ago
parent 78f750a3e8
commit 5d58dae41f
  1. 2
      .gitignore
  2. 1
      config/settings.go
  3. 5
      go.mod
  4. 2
      go.sum
  5. 90
      main.go

2
.gitignore vendored

@ -30,3 +30,5 @@ public
*.mp4 *.mp4
ffmpeg* ffmpeg*
renders renders
vidcrunch
vidcrunch.exe

@ -23,6 +23,7 @@ type VideoOpts struct {
Tune string Tune string
Input string Input string
OutDir string OutDir string
FakeResult string
Test int Test int
TestStart int TestStart int
Passes int Passes int

@ -2,7 +2,10 @@ module lcthw.dev/go/vidcrunch
go 1.24.2 go 1.24.2
require github.com/modfy/fluent-ffmpeg v0.1.0 require (
github.com/modfy/fluent-ffmpeg v0.1.0
github.com/zencoder/go-dash v0.0.0-20201006100653-2f93b14912b2
)
require ( require (
github.com/fatih/structs v1.1.0 // indirect github.com/fatih/structs v1.1.0 // indirect

@ -4,3 +4,5 @@ github.com/modfy/fluent-ffmpeg v0.1.0 h1:9T191rhSK6KfoDo9Y/+0Tph3khrudvLQEEi05O+
github.com/modfy/fluent-ffmpeg v0.1.0/go.mod h1:GauXGqGYAmYFupCWG8n1eyuLZMKmLxGTGvszYkJ0Oyo= github.com/modfy/fluent-ffmpeg v0.1.0/go.mod h1:GauXGqGYAmYFupCWG8n1eyuLZMKmLxGTGvszYkJ0Oyo=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/zencoder/go-dash v0.0.0-20201006100653-2f93b14912b2 h1:0iAY2pL6yYhNYpdc1DbFq0p7ocyu5MlgKmkealhz3nk=
github.com/zencoder/go-dash v0.0.0-20201006100653-2f93b14912b2/go.mod h1:c8Gxxfmh0jmZ6G+ISlpa315WBVkzd8mEhu6gN9mn5Qg=

@ -11,8 +11,20 @@ import (
"strings" "strings"
"lcthw.dev/go/vidcrunch/config" "lcthw.dev/go/vidcrunch/config"
"github.com/modfy/fluent-ffmpeg" "github.com/modfy/fluent-ffmpeg"
"strconv"
"os/exec"
"slices"
"iter"
) )
func AudioOnly(encoding config.VideoOpts) bool {
return encoding.Scale == "" && encoding.VideoCodec == "none"
}
func VideoOnly(encoding config.VideoOpts) bool {
return encoding.AudioCodec == "none"
}
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)
@ -21,7 +33,7 @@ func ModFile(fname string, encoding config.VideoOpts) string {
base, found := strings.CutSuffix(file, ext) base, found := strings.CutSuffix(file, ext)
if !found { panic("no extension found?!") } if !found { panic("no extension found?!") }
if encoding.Scale == "" && encoding.VideoCodec == "none" { if AudioOnly(encoding) {
renamed := fmt.Sprint(base, ".audio.", encoding.Format) renamed := fmt.Sprint(base, ".audio.", encoding.Format)
return filepath.Join(dir, renamed) return filepath.Join(dir, renamed)
} else { } else {
@ -54,7 +66,7 @@ func Run(encoding config.VideoOpts, pass int, pid int, input string, output stri
"-aspect", encoding.Scale) "-aspect", encoding.Scale)
} }
if pass != encoding.Passes || encoding.AudioCodec == "none" { if pass != encoding.Passes || VideoOnly(encoding) {
extras = append(extras, "-an") extras = append(extras, "-an")
} else { } else {
encode.AudioCodec(encoding.AudioCodec) encode.AudioCodec(encoding.AudioCodec)
@ -114,13 +126,69 @@ func RenderFile(encoding config.VideoOpts, pid int, path string, target string)
Run(encoding, encoding.Passes, pid, path, target) Run(encoding, encoding.Passes, pid, path, target)
} }
func RenderToDir(encoding config.VideoOpts, force bool) { func StrSeq(up_to int) iter.Seq[string] {
return func (yield func(x string) bool) {
for i := range up_to {
if !yield(strconv.Itoa(i)) { return }
}
}
}
func SaveMPD(settings config.Settings) {
args := make([]string, 0, 10)
var the_audio string
// force it to overwrite
args = append(args, "-y")
for _, encoding := range settings.Encodings {
if VideoOnly(encoding) {
args = append(args, "-f", "webm_dash_manifest", "-i", encoding.FakeResult)
} else if AudioOnly(encoding) {
the_audio = encoding.FakeResult
}
}
args = append(args, "-f", "webm_dash_manifest", "-i", the_audio)
// create map for each
args = append(args, "-c", "copy")
for i := 0; i < len(settings.Encodings); i++ {
args = append(args, "-map", strconv.Itoa(i))
}
// generate adaptation sets, separating the audio
// id=0 is videos, id=1 is audio
args = append(args, "-f", "webm_dash_manifest", "-adaptation_sets")
da_ints := slices.Collect(StrSeq(len(settings.Encodings) - 1))
video_set := strings.Join(da_ints, ",")
adapt_set := fmt.Sprintf("id=0,streams=%s id=1,streams=%d",
video_set, len(settings.Encodings) - 1)
args = append(args, adapt_set)
args = append(args, filepath.Join(settings.Encodings[0].OutDir, "manifest.mpd"))
fmt.Println("\n\n\n\nARGS", args)
ffmpeg := exec.Command("ffmpeg", args...)
out, err := ffmpeg.CombinedOutput()
os.Stdout.Write(out)
log.Fatal(err)
}
func RenderToDir(encoding config.VideoOpts, force bool) string {
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) }
target := ""
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)
@ -132,6 +200,10 @@ func RenderToDir(encoding config.VideoOpts, force bool) {
fmt.Println("^^^ SKIP", path, "->", target) fmt.Println("^^^ SKIP", path, "->", target)
} }
} }
if target == "" { log.Fatal("fuck!") }
return target
} }
func main() { func main() {
@ -147,12 +219,18 @@ func main() {
log.Fatal(http.ListenAndServe(settings.Port, nil)) log.Fatal(http.ListenAndServe(settings.Port, nil))
} else { } else {
for _, encoding := range settings.Encodings { for i := 0; i < len(settings.Encodings); i++ {
fmt.Println("LOOP", i)
encoding := &settings.Encodings[i];
if encoding.OutDir != "" { if encoding.OutDir != "" {
RenderToDir(encoding, settings.Force) encoding.FakeResult = RenderToDir(*encoding, settings.Force)
fmt.Println("ENCODING result", encoding.FakeResult, "len=", len(settings.Encodings))
} else { } else {
log.Fatal("config file needs either Output or OutDir") log.Fatal("config file needs either Output or OutDir")
} }
} }
SaveMPD(settings)
} }
} }

Loading…
Cancel
Save