replace progress percentage with actual file size

This commit is contained in:
2026-03-04 23:58:11 -05:00
parent 3cac63ba82
commit 481c8d9bb6
4 changed files with 93 additions and 68 deletions

View File

@@ -4,6 +4,8 @@ import (
"context"
"encoding/json"
"os"
"path/filepath"
"sync"
"time"
"github.com/lrstanley/go-ytdlp"
@@ -95,42 +97,80 @@ func GetFormats(url string) (*FormatOptions, error) {
return formatOpts, nil
}
func dirSize(path string) int {
var total int64
filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if err == nil && !info.IsDir() {
total += info.Size()
}
return nil
})
return int(total)
}
func DownloadVideo(out_dir, temp_dir, url string, opts DownloadOptions, progressChan chan<- ProgressUpdate) {
defer close(progressChan)
var mu sync.Mutex
currentPhase := "downloading"
currentFilename := ""
// Poll the temp directory for actual bytes-on-disk progress.
// The yt-dlp progress callback only tracks phase/filename since
// DownloadedBytes from the callback is unreliable for DASH streams.
var wg sync.WaitGroup
wg.Add(1)
stopPoll := make(chan struct{})
go func() {
defer wg.Done()
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-stopPoll:
return
case <-ticker.C:
mu.Lock()
phase := currentPhase
filename := currentFilename
mu.Unlock()
progressChan <- ProgressUpdate{
Phase: phase,
DownloadedBytes: dirSize(temp_dir),
Filename: filename,
}
}
}
}()
defer func() {
close(stopPoll)
wg.Wait()
close(progressChan)
}()
homePath := "home:" + out_dir
tempPath := "temp:" + temp_dir
var lastPhase string
dl := ytdlp.New().
SetExecutable(ytdlpBinary).
Paths(homePath).
Paths(tempPath).
RecodeVideo("mp4").
ProgressFunc(100*time.Millisecond, func(prog ytdlp.ProgressUpdate) {
// Detect phase transition -- differentiate "downloading" as the main download
// and "post processing" when the file name changes, preventing it from appearing "reset"
if prog.Status == ytdlp.ProgressStatusFinished ||
prog.Status == ytdlp.ProgressStatusStarting ||
prog.Status == ytdlp.ProgressStatusError {
return
}
phase := "downloading"
if prog.Status == ytdlp.ProgressStatusDownloading && prog.Percent() == 0.0 {
// If we already had progress, it's likely post-processing
if lastPhase == "downloading" {
phase = "post-processing"
}
} else if prog.Status != ytdlp.ProgressStatusDownloading {
if prog.Status == ytdlp.ProgressStatusPostProcessing {
phase = "post-processing"
}
lastPhase = phase
progressChan <- ProgressUpdate{
Status: prog.Status,
Percent: prog.PercentString(),
PercentFloat: prog.Percent(),
ETA: prog.ETA(),
Filename: prog.Filename,
Phase: phase,
}
mu.Lock()
currentPhase = phase
currentFilename = prog.Filename
mu.Unlock()
}).
Output("%(title)s.%(ext)s")