fix: progress stuck at 0%, container not respected, audio display, Spotify DRM fallback
- Remove --no-progress from yt-dlp args that suppressed all progress output - Add --merge-output-format when FormatString is set (container was ignored for combined formats) - Improve formatLabelForDisplay for audio-only formats missing bitrate (show ID+extension) - Detect DRM errors (Spotify) and fall back to YouTube Music search via ytsearch1:
This commit is contained in:
@@ -220,6 +220,9 @@ func (c *Client) StartDownload(job *domain.DownloadJob, downloadDir string) (<-c
|
||||
// Use explicit format string if set (video+audio combination)
|
||||
if job.FormatString != "" {
|
||||
args = append(args, "-f", job.FormatString)
|
||||
if job.Container != "" {
|
||||
args = append(args, "--merge-output-format", job.Container)
|
||||
}
|
||||
} else {
|
||||
// Build format string for merge
|
||||
switch job.MediaType {
|
||||
@@ -243,8 +246,8 @@ func (c *Client) StartDownload(job *domain.DownloadJob, downloadDir string) (<-c
|
||||
outputPath := filepath.Join(downloadDir, job.ID+"_%(id)s.%(ext)s")
|
||||
args = append(args, "--output", outputPath)
|
||||
|
||||
// Progress reporting
|
||||
args = append(args, "--newline", "--no-progress")
|
||||
// Progress reporting (--newline for line-based, no --no-progress so we get actual output)
|
||||
args = append(args, "--newline")
|
||||
|
||||
// Language selection if specified
|
||||
if job.Language != "" {
|
||||
@@ -337,6 +340,40 @@ func CancelDownload(job *domain.DownloadJob) {
|
||||
}
|
||||
}
|
||||
|
||||
// ytdlpSearchResult holds a single flat search result from yt-dlp.
|
||||
type ytdlpSearchResult struct {
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// SearchYoutube searches YouTube via yt-dlp ytsearch and returns the first result URL and title.
|
||||
func (c *Client) SearchYoutube(query string) (url, title string, err error) {
|
||||
args := []string{
|
||||
"--flat-playlist", "-J", "--no-download",
|
||||
"--no-warnings",
|
||||
"ytsearch1:" + query,
|
||||
}
|
||||
if c.cookiesFile != "" {
|
||||
args = append(args, "--cookies", c.cookiesFile)
|
||||
}
|
||||
|
||||
out, err := c.run(args)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("youtube search failed: %w", err)
|
||||
}
|
||||
|
||||
var info struct {
|
||||
Entries []ytdlpSearchResult `json:"entries"`
|
||||
}
|
||||
if err := json.Unmarshal(out, &info); err != nil {
|
||||
return "", "", fmt.Errorf("parse search result: %w", err)
|
||||
}
|
||||
if len(info.Entries) == 0 {
|
||||
return "", "", fmt.Errorf("no results found")
|
||||
}
|
||||
return info.Entries[0].URL, info.Entries[0].Title, nil
|
||||
}
|
||||
|
||||
func (c *Client) run(args []string) ([]byte, error) {
|
||||
cmd := exec.Command(c.binaryPath, args...)
|
||||
var stderr bytes.Buffer
|
||||
|
||||
Reference in New Issue
Block a user