Files
ffmpeg-gui/internal/ffmpeg/progress.go
T

86 lines
1.9 KiB
Go
Raw Normal View History

2026-07-29 02:17:57 +08:00
package ffmpeg
import (
"regexp"
"strconv"
"strings"
)
// Progress holds real-time encoding progress from ffmpeg stderr.
type Progress struct {
Frame int64 `json:"frame"`
FPS float64 `json:"fps"`
Q float64 `json:"q"`
Size string `json:"size"`
Time string `json:"time"`
Bitrate string `json:"bitrate"`
Speed string `json:"speed"`
Eta string `json:"eta"`
Percent float64 `json:"percent"`
}
var progressRe = regexp.MustCompile(
`frame=\s*(\d+)\s+fps=\s*([\d.]+)\s+q=\s*([\d.-]+)\s+(?:size=\s*(\S+)\s+)?time=\s*([\d:.]+)\s+bitrate=\s*(\S+)\s+speed=\s*(\S+)`,
)
func parseProgressLine(line string) (Progress, bool) {
m := progressRe.FindStringSubmatch(line)
if m == nil {
return Progress{}, false
}
frame, _ := strconv.ParseInt(m[1], 10, 64)
fps, _ := strconv.ParseFloat(m[2], 64)
q, _ := strconv.ParseFloat(m[3], 64)
return Progress{
Frame: frame,
FPS: fps,
Q: q,
Size: m[4],
Time: m[5],
Bitrate: m[6],
Speed: m[7],
}, true
}
// parseSpeedMultiplier converts "1.5x" → 1.5.
func parseSpeedMultiplier(s string) float64 {
s = strings.TrimSuffix(s, "x")
v, _ := strconv.ParseFloat(s, 64)
return v
}
// formatSeconds converts seconds to "MM:SS" or "HH:MM:SS".
func formatSeconds(secs float64) string {
if secs < 0 {
secs = 0
}
h := int(secs) / 3600
m := (int(secs) % 3600) / 60
s := int(secs) % 60
if h > 0 {
return strconv.Itoa(h) + ":" + pad2(m) + ":" + pad2(s)
}
return pad2(m) + ":" + pad2(s)
}
func pad2(n int) string {
if n < 10 {
return "0" + strconv.Itoa(n)
}
return strconv.Itoa(n)
}
// parseTimeSeconds converts "HH:MM:SS.mm" to seconds.
func parseTimeSeconds(t string) float64 {
parts := strings.Split(t, ":")
if len(parts) != 3 {
return 0
}
h, _ := strconv.ParseFloat(parts[0], 64)
m, _ := strconv.ParseFloat(parts[1], 64)
s, _ := strconv.ParseFloat(parts[2], 64)
return h*3600 + m*60 + s
}