// VibEdit is a small video cutter: it splits clips out of source videos and // joins them back together using ffmpeg. The UI is a local web page served by // this program and opened in an Edge/Chrome app window. package main import ( "flag" "fmt" "log" "net" "net/http" "os" "os/signal" "syscall" "time" ) const appName = "VibEdit" var version = "1.0.0" func main() { addr := flag.String("addr", "127.0.0.1:0", "address to listen on") noBrowser := flag.Bool("no-browser", false, "do not open the editor window automatically") defaultBrowser := flag.Bool("default-browser", false, "open in the default web browser instead of an Edge/Chrome app window") ffmpegPath := flag.String("ffmpeg", "", "path to ffmpeg (default: next to this program, then PATH)") ffprobePath := flag.String("ffprobe", "", "path to ffprobe (default: next to this program, then PATH)") keepAlive := flag.Bool("keep-alive", false, "keep running after the editor window is closed") flag.Parse() log.SetFlags(log.Ltime) fmt.Printf("%s %s - simple ffmpeg video cutter\n\n", appName, version) app := newApp(*ffmpegPath, *ffprobePath, *keepAlive) if !app.tools.OK() { fmt.Println("WARNING: ffmpeg/ffprobe not found.") fmt.Println(" Put ffmpeg" + exeSuffix + " and ffprobe" + exeSuffix + " in the same folder as this program") fmt.Println(" (or on your PATH). Windows builds: https://www.gyan.dev/ffmpeg/builds/") fmt.Println() } else { fmt.Printf("ffmpeg: %s\nffprobe: %s\n\n", app.tools.FFmpeg, app.tools.FFprobe) } ln, err := net.Listen("tcp", *addr) if err != nil { fatal("Could not start the local web server: %v", err) } tcp := ln.Addr().(*net.TCPAddr) host := tcp.IP.String() if tcp.IP.IsUnspecified() { host = "127.0.0.1" } hostPort := net.JoinHostPort(host, fmt.Sprint(tcp.Port)) app.configureHost(tcp) url := fmt.Sprintf("http://%s/?t=%s", hostPort, app.token) fmt.Println("Editor address (open this if no window appears):") fmt.Println(" " + url) fmt.Println() fmt.Println("Close the editor window or this console to quit.") fmt.Println() if !*noBrowser { go func() { if err := openBrowser(url, *defaultBrowser); err != nil { log.Printf("could not open a browser: %v", err) } }() } sig := make(chan os.Signal, 1) signal.Notify(sig, os.Interrupt, syscall.SIGTERM) go func() { <-sig app.requestQuit("interrupted") }() srv := &http.Server{Handler: app, ReadHeaderTimeout: 10 * time.Second} go func() { <-app.quit srv.Close() }() if err := srv.Serve(ln); err != nil && err != http.ErrServerClosed { fatal("Web server stopped: %v", err) } app.shutdown() } func fatal(format string, args ...any) { fmt.Fprintf(os.Stderr, "\nERROR: "+format+"\n", args...) waitBeforeExit() os.Exit(1) }