Skip to content

Instantly share code, notes, and snippets.

@jeffmylife
Created July 11, 2025 17:22
Show Gist options
  • Save jeffmylife/8f255c85ea95368dd80f451ad5ba45b7 to your computer and use it in GitHub Desktop.
Save jeffmylife/8f255c85ea95368dd80f451ad5ba45b7 to your computer and use it in GitHub Desktop.
Download a clip from youtube to an mp4 with a command line tool
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = ["yt-dlp", "ffmpeg", "typer", "rich"]
# ///
import subprocess
from typing import Optional
import typer
from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn
console = Console()
app = typer.Typer(help="Download YouTube clips via yt-dlp with exact time ranges.")
@app.command()
def clip(
url: str = typer.Option(..., "--url", "-u", help="YouTube video or clip URL"),
start: str = typer.Option(..., "--start", "-s", help="Start time (mm:ss or hh:mm:ss)"),
end: str = typer.Option(..., "--end", "-e", help="End time (mm:ss or hh:mm:ss)"),
fmt: str = typer.Option("137+140", "--format", "-f", help="yt-dlp format to download (video+audio)"),
output: Optional[str] = typer.Option(None, "--output", "-o", help="Output filename (default: autogenerated)")
):
"""
Download a YouTube clip from URL between START and END timestamps.
"""
section = f"*{start}-{end}"
cmd = [
"yt-dlp",
"-f", fmt,
"--download-sections", section,
"--force-keyframes-at-cuts",
"--merge-output-format", "mp4",
url,
]
if output:
cmd.extend(["-o", output])
console.print(f"[bold green]▶ Running:[/] {' '.join(cmd)}")
with Progress(SpinnerColumn(), TextColumn("{task.description}"), transient=True) as progress:
task = progress.add_task("Downloading...", start=False)
progress.start_task(task)
result = subprocess.run(cmd)
if result.returncode != 0:
console.print(f"[bold red]✖ Failed with exit code[/] {result.returncode}")
raise typer.Exit(result.returncode)
console.print("[bold blue]✅ Clip downloaded successfully![/]")
if __name__ == "__main__":
app()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment