fix: correct interlace detection and reap idet child
The previous detector substring-matched "TFF"/"BFF" against idet's own label text, so it returned true on every source, and `cmd.Start()` was never paired with `Wait()`, leaving a zombie ffmpeg per file. Run idet bounded with `-frames:v 400 -an -sn -f null -` so it completes, use CombinedOutput so the child is reaped, and parse the "Multi frame detection" summary line — interlaced only when TFF+BFF > Progressive.
This commit is contained in:
@@ -6,12 +6,15 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"videnc-vibe/pkg/types"
|
||||
)
|
||||
|
||||
var idetSummaryRegex = regexp.MustCompile(`Multi frame detection:\s+TFF:\s*(\d+)\s+BFF:\s*(\d+)\s+Progressive:\s*(\d+)\s+Undetermined:\s*(\d+)`)
|
||||
|
||||
type Encoder struct {
|
||||
ffmpegPath string
|
||||
ffprobePath string
|
||||
@@ -122,20 +125,43 @@ func (e *Encoder) GetMediaInfo(path string) (width, height int, interlaced bool,
|
||||
}
|
||||
}
|
||||
|
||||
cmd = exec.Command(e.ffmpegPath, "-i", path, "-hide_banner", "-vf", "idet")
|
||||
stderr, _ := cmd.StderrPipe()
|
||||
cmd.Start()
|
||||
buf := make([]byte, 16384)
|
||||
n, _ := stderr.Read(buf)
|
||||
stderr.Close()
|
||||
outputStr := string(buf[:n])
|
||||
interlaced = strings.Contains(outputStr, "TFF") || strings.Contains(outputStr, "BFF")
|
||||
cmd = exec.Command(e.ffmpegPath,
|
||||
"-hide_banner",
|
||||
"-nostats",
|
||||
"-i", path,
|
||||
"-vf", "idet",
|
||||
"-frames:v", "400",
|
||||
"-an", "-sn",
|
||||
"-f", "null", "-",
|
||||
)
|
||||
idetOut, _ := cmd.CombinedOutput()
|
||||
interlaced = detectInterlaced(string(idetOut))
|
||||
|
||||
fmt.Printf("DEBUG interlaced: %v\n", interlaced)
|
||||
|
||||
return width, height, interlaced, nil
|
||||
}
|
||||
|
||||
// detectInterlaced parses ffmpeg idet's "Multi frame detection" summary line
|
||||
// and returns true when TFF+BFF clearly outnumber Progressive frames among
|
||||
// the decided frames. Undetermined frames are ignored. If the summary line
|
||||
// is missing, returns false (default to progressive).
|
||||
func detectInterlaced(idetOutput string) bool {
|
||||
m := idetSummaryRegex.FindStringSubmatch(idetOutput)
|
||||
if m == nil {
|
||||
return false
|
||||
}
|
||||
tff, _ := strconv.Atoi(m[1])
|
||||
bff, _ := strconv.Atoi(m[2])
|
||||
prog, _ := strconv.Atoi(m[3])
|
||||
interlaced := tff + bff
|
||||
decided := interlaced + prog
|
||||
if decided == 0 {
|
||||
return false
|
||||
}
|
||||
return interlaced > prog
|
||||
}
|
||||
|
||||
func (e *Encoder) calculateZscaleWidth(path string, originalHeight int) (string, int, error) {
|
||||
cmd := exec.Command(e.ffprobePath, "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=width,height,sample_aspect_ratio", "-print_format", "json", path)
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
||||
Reference in New Issue
Block a user