Switch dashboard to watcher-based multi-disk view, fix transcoding FPS display
- dashboard.html: remove standalone "Mounted Disk" input panel; show all disks from GET /api/disks (watcher), auto-refresh every 5s - detect.go: use avg_frame_rate when r_frame_rate is unrealistic (>120 fps or 0), fixes MJPEG/mjpeg showing 90000fps - transcoder.go: parse fps= from ffmpeg progress output and expose in Progress struct - copier.go: update task message with real-time encoding fps (@ 45.3 fps), clear speed_bps/eta during transcoding to avoid showing stale copy speed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,8 +21,13 @@ type Options struct {
|
||||
SourceInfo VideoInfo
|
||||
}
|
||||
|
||||
// Transcode запускает ffmpeg. progress вызывается с 0..1 по мере работы.
|
||||
func Transcode(ctx context.Context, opts Options, progress func(float64)) error {
|
||||
type Progress struct {
|
||||
Pct float64 // 0..1
|
||||
EncodeFPS float64 // текущая скорость кодирования, кадр/с
|
||||
}
|
||||
|
||||
// Transcode запускает ffmpeg. progress вызывается при каждом обновлении прогресса.
|
||||
func Transcode(ctx context.Context, opts Options, progress func(Progress)) error {
|
||||
if err := os.MkdirAll(filepath.Dir(opts.Output), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -42,20 +47,29 @@ func Transcode(ctx context.Context, opts Options, progress func(float64)) error
|
||||
}
|
||||
|
||||
// Парсим прогресс из stdout (-progress pipe:1)
|
||||
if opts.SourceInfo.DurationSec > 0 && progress != nil {
|
||||
if progress != nil {
|
||||
var cur Progress
|
||||
scanner := bufio.NewScanner(stdout)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "out_time_us=") {
|
||||
switch {
|
||||
case strings.HasPrefix(line, "out_time_us="):
|
||||
val := strings.TrimPrefix(line, "out_time_us=")
|
||||
if us, err := strconv.ParseInt(val, 10, 64); err == nil && us > 0 {
|
||||
if us, err := strconv.ParseInt(val, 10, 64); err == nil && us > 0 && opts.SourceInfo.DurationSec > 0 {
|
||||
sec := float64(us) / 1e6
|
||||
pct := sec / opts.SourceInfo.DurationSec
|
||||
if pct > 1 {
|
||||
pct = 1
|
||||
}
|
||||
progress(pct)
|
||||
cur.Pct = pct
|
||||
}
|
||||
case strings.HasPrefix(line, "fps="):
|
||||
val := strings.TrimPrefix(line, "fps=")
|
||||
if fps, err := strconv.ParseFloat(strings.TrimSpace(val), 64); err == nil && fps > 0 {
|
||||
cur.EncodeFPS = fps
|
||||
}
|
||||
case line == "progress=continue" || line == "progress=end":
|
||||
progress(cur)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user