Reviewed-on: https://git.example.com/jarianc/youtube-cli/pulls/14
This commit is contained in:
commit
6ae8f3befc
@ -825,9 +825,7 @@ class YouTubeCLI:
|
||||
else:
|
||||
logger.info("Using 1080p quality by default")
|
||||
|
||||
# Run command and let yt-dlp handle progress natively
|
||||
# Removed timeout to support long-running downloads in queue
|
||||
# Use a pipe to capture progress and support cancellation
|
||||
# Run command with progress bar
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
@ -836,12 +834,71 @@ class YouTubeCLI:
|
||||
text=True,
|
||||
)
|
||||
|
||||
try:
|
||||
stdout, _ = process.communicate(timeout=None) # No timeout
|
||||
result = subprocess.CompletedProcess(
|
||||
cmd, process.returncode, stdout, ""
|
||||
# Rich progress bar for downloads
|
||||
from rich.progress import (
|
||||
BarColumn,
|
||||
DownloadColumn,
|
||||
Progress,
|
||||
TextColumn,
|
||||
TimeRemainingColumn,
|
||||
TransferSpeedColumn,
|
||||
)
|
||||
except subprocess.TimeoutExpired:
|
||||
|
||||
progress = Progress(
|
||||
TextColumn("[bold blue]{task.description}"),
|
||||
BarColumn(bar_width=40),
|
||||
"[progress.percentage]{task.percentage:>3.1f}%",
|
||||
"•",
|
||||
DownloadColumn(),
|
||||
"•",
|
||||
TransferSpeedColumn(),
|
||||
"•",
|
||||
TimeRemainingColumn(),
|
||||
)
|
||||
|
||||
downloaded_bytes = 0
|
||||
total_bytes = 0
|
||||
download_task = None
|
||||
output_lines = []
|
||||
|
||||
try:
|
||||
with progress:
|
||||
for line in process.stdout:
|
||||
output_lines.append(line)
|
||||
|
||||
# Parse progress line: "[download] 5.0% of ~ 10.00MiB at 1.23MiB/s ETA 00:08"
|
||||
import re as re_mod
|
||||
|
||||
progress_match = re_mod.search(
|
||||
r"\[download\]\s+(\d+\.?\d*)%\s+of\s+[~]?\s*([\d.]+)\s*(B|KiB|MiB|GiB)",
|
||||
line,
|
||||
)
|
||||
if progress_match:
|
||||
pct = float(progress_match.group(1))
|
||||
size_str = progress_match.group(2)
|
||||
size_unit = progress_match.group(3)
|
||||
total_bytes = self._parse_size(size_str, size_unit)
|
||||
downloaded_bytes = int(total_bytes * pct / 100)
|
||||
|
||||
if download_task is None:
|
||||
download_task = progress.add_task(
|
||||
"Downloading...",
|
||||
total=total_bytes if total_bytes > 0 else None,
|
||||
)
|
||||
progress.update(
|
||||
download_task,
|
||||
completed=downloaded_bytes,
|
||||
total=total_bytes if total_bytes > 0 else None,
|
||||
)
|
||||
elif "[download]" in line and "[" not in line.split("[download]")[1].split()[0]:
|
||||
pass
|
||||
elif "[download] Deprecated commandline" in line:
|
||||
pass
|
||||
|
||||
result = subprocess.CompletedProcess(
|
||||
cmd, process.returncode, "".join(output_lines), ""
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
process.kill()
|
||||
logger.warning("Download cancelled by user")
|
||||
return False
|
||||
@ -855,7 +912,6 @@ class YouTubeCLI:
|
||||
|
||||
# Add video to archive for tracking
|
||||
try:
|
||||
# Extract video ID from URL for archive
|
||||
import re
|
||||
|
||||
video_id = None
|
||||
@ -880,8 +936,6 @@ class YouTubeCLI:
|
||||
if result.stdout:
|
||||
logger.error(f"Error details: {result.stdout}")
|
||||
|
||||
# Try to check if we have a different problem
|
||||
# Check for specific JavaScript challenge errors and recommend solutions
|
||||
if (
|
||||
"Solving JS challenges" in result.stdout
|
||||
or "challenge solving failed" in result.stdout
|
||||
@ -895,6 +949,11 @@ class YouTubeCLI:
|
||||
except Exception as e:
|
||||
logger.error(f"Error during download: {str(e)}")
|
||||
|
||||
def _parse_size(self, size_str: str, unit: str) -> int:
|
||||
"""Parse size string with unit to bytes."""
|
||||
multipliers = {"B": 1, "KiB": 1024, "MiB": 1024**2, "GiB": 1024**3}
|
||||
return int(float(size_str) * multipliers.get(unit, 1))
|
||||
|
||||
def download_playlist(
|
||||
self,
|
||||
url,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user