Sintec.VideoDownloader 1.0.0

dotnet add package Sintec.VideoDownloader --version 1.0.0
                    
NuGet\Install-Package Sintec.VideoDownloader -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Sintec.VideoDownloader" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Sintec.VideoDownloader" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Sintec.VideoDownloader" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Sintec.VideoDownloader --version 1.0.0
                    
#r "nuget: Sintec.VideoDownloader, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Sintec.VideoDownloader@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Sintec.VideoDownloader&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Sintec.VideoDownloader&version=1.0.0
                    
Install as a Cake Tool

Sintec.VideoDownloader

A .NET library for downloading videos from various platforms with authentication support for paid/subscription sites.

Features

  • Download videos using yt-dlp
  • Automatic site detection for paid platforms (VHX, Patreon, Udemy, Teachable, Skillshare)
  • Cookie-based authentication for subscription sites
  • Session management with automatic reuse
  • Real-time progress callbacks
  • Extensible provider architecture

Prerequisites

  • .NET 9.0 or later
  • yt-dlp - Must be installed and either:
    • In your system PATH, or
    • Located in a custom directory specified via ToolsDirectory option
  • ffmpeg (optional) - Required for merging video/audio streams

Installation

dotnet add package Sintec.VideoDownloader

Quick Start

Setup with Dependency Injection

using Sintec.VideoDownloader.DependencyInjection;

services.AddVideoDownloader(options =>
{
    // Optional: specify tools directory if not in PATH
    // options.ToolsDirectory = "/path/to/tools";

    // Optional: specify download location (default: system temp)
    options.DownloadsDirectory = "/path/to/downloads";
});

Download a Public Video

var downloader = serviceProvider.GetRequiredService<IVideoDownloader>();
var result = await downloader.DownloadAsync("https://youtube.com/watch?v=...");

if (result.Success)
{
    Console.WriteLine($"Downloaded: {result.FilePath}");
}

Download from a Paid Site with Authentication

var result = await downloader.DownloadWithAuthAsync(
    "https://mysite.vhx.tv/videos/lesson-1",
    "user@example.com",
    "password"
);

API Reference

Configuration

VideoDownloaderOptions
Property Type Default Description
ToolsDirectory string? null Directory where yt-dlp/ffmpeg are located. If not set, searches PATH.
DownloadsDirectory string System temp Directory where downloaded videos are saved
TempDirectory string? null Directory for temporary files (cookies). Defaults to system temp.

Interfaces

IVideoDownloader

Main interface for downloading videos.

public interface IVideoDownloader
{
    // Download from public URL (no authentication)
    Task<DownloadResult> DownloadAsync(string url, DownloadOptions? options = null);

    // Download with username/password authentication
    Task<DownloadResult> DownloadWithAuthAsync(string url, string username, string password, DownloadOptions? options = null);

    // Download using existing cookie file
    Task<DownloadResult> DownloadWithCookiesAsync(string url, string cookieFilePath, DownloadOptions? options = null);
}
ISiteDetectionService

Detects site type from URL patterns.

public interface ISiteDetectionService
{
    // Returns SiteInfo or null if not a recognized paid platform
    SiteInfo? DetectSite(string url);
}
ISiteAuthService

Coordinates authentication across different site types.

public interface ISiteAuthService
{
    // Authenticate to a site
    Task<AuthResult> AuthenticateAsync(string siteDomain, string siteType, string username, string password);

    // Check if valid session exists
    bool HasValidSession(string siteDomain, string siteType);

    // Get cookie file path for existing session
    string? GetCookieFilePath(string siteDomain, string siteType);

    // Clear all sessions (deletes cookie files)
    void ClearAllSessions();
}

Models

DownloadResult
public record DownloadResult(
    bool Success,
    string? FilePath = null,      // Full path to downloaded file
    string? FileName = null,      // Just the filename
    long? FileSizeBytes = null,   // File size in bytes
    string? Error = null          // Error message if failed
);
DownloadOptions
public record DownloadOptions
{
    // Custom yt-dlp output template
    string? OutputTemplate { get; init; }

    // Timestamp prefix for filename (e.g., "20240115_143022")
    string? FileTimestamp { get; init; }

    // Preferred video format (e.g., "bestvideo+bestaudio/best")
    string? Format { get; init; }

    // Output container format for merging (e.g., "mp4", "mkv")
    string? MergeOutputFormat { get; init; }

    // Progress callback
    Action<DownloadProgress>? OnProgress { get; init; }
}
DownloadProgress
public record DownloadProgress(
    int Percentage,              // 0-100
    string? Status,              // Status message (e.g., "Downloading", "Merging")
    long? DownloadedBytes = null,
    long? TotalBytes = null,
    double? Speed = null         // Bytes per second
);
SiteInfo
public record SiteInfo(
    string Domain,       // e.g., "mysite.vhx.tv"
    string SiteType,     // e.g., "VHX", "Patreon"
    bool RequiresAuth    // Whether authentication is needed
);
AuthResult
public record AuthResult(
    bool Success,
    string? Error = null
);

Usage Examples

Progress Tracking

var result = await downloader.DownloadAsync(url, new DownloadOptions
{
    OnProgress = progress =>
    {
        Console.Write($"\r{progress.Status} - {progress.Percentage}%");

        if (progress.Speed.HasValue)
        {
            var speedMb = progress.Speed.Value / 1024 / 1024;
            Console.Write($" ({speedMb:F1} MB/s)");
        }
    }
});

Check Site Type Before Download

var detection = serviceProvider.GetRequiredService<ISiteDetectionService>();
var siteInfo = detection.DetectSite(url);

if (siteInfo == null)
{
    // Public site - no auth needed
    await downloader.DownloadAsync(url);
}
else if (siteInfo.RequiresAuth)
{
    Console.WriteLine($"Site requires {siteInfo.SiteType} authentication");
    // Prompt for credentials...
    await downloader.DownloadWithAuthAsync(url, email, password);
}

Session Reuse

Sessions are automatically managed. Once authenticated, subsequent downloads to the same domain reuse the existing session:

var siteAuth = serviceProvider.GetRequiredService<ISiteAuthService>();
var detection = serviceProvider.GetRequiredService<ISiteDetectionService>();

var site = detection.DetectSite(url);

if (site != null && siteAuth.HasValidSession(site.Domain, site.SiteType))
{
    // Session exists - no need for credentials
    var cookiePath = siteAuth.GetCookieFilePath(site.Domain, site.SiteType);
    await downloader.DownloadWithCookiesAsync(url, cookiePath!);
}
else
{
    // Need to authenticate
    await downloader.DownloadWithAuthAsync(url, email, password);
}

Session Cleanup

Clear sessions on application exit to delete cookie files:

var siteAuth = serviceProvider.GetRequiredService<ISiteAuthService>();
siteAuth.ClearAllSessions();

Custom Format Selection

var result = await downloader.DownloadAsync(url, new DownloadOptions
{
    Format = "bestvideo[height<=1080]+bestaudio/best[height<=1080]",
    MergeOutputFormat = "mp4"
});

Supported Platforms

Platform Domain Pattern Auth Status
VHX/Vimeo OTT *.vhx.tv, embed.vhx.tv Implemented
Patreon *.patreon.com Stub (manual cookies)
Udemy *.udemy.com Stub (manual cookies)
Teachable *.teachable.com Detected only
Skillshare *.skillshare.com Detected only

VHX Authentication Flow

The VHX provider handles the complete authentication flow:

  1. GET /login - Extract CSRF token (authenticity_token)
  2. POST /login - Submit credentials with CSRF token
  3. Verify logged_in=1 cookie
  4. Write Netscape-format cookie file for yt-dlp
  5. Sessions expire after 24 hours

Error Handling

var result = await downloader.DownloadAsync(url);

if (!result.Success)
{
    Console.WriteLine($"Download failed: {result.Error}");
    // Common errors:
    // - "yt-dlp not found"
    // - "Invalid email or password"
    // - "Video unavailable"
    // - "Authentication required"
}

Architecture

Sintec.VideoDownloader/
├── DependencyInjection/
│   └── ServiceCollectionExtensions.cs  # AddVideoDownloader() extension
├── Download/
│   ├── IVideoDownloader.cs             # Main download interface
│   ├── VideoDownloader.cs              # yt-dlp wrapper implementation
│   ├── DownloadOptions.cs              # Download options + progress
│   └── DownloadResult.cs               # Download result model
├── SiteAuth/
│   ├── ISiteAuthProvider.cs            # Provider interface
│   ├── SiteAuthService.cs              # Auth coordinator
│   ├── SiteDetectionService.cs         # URL pattern matching
│   └── Providers/
│       ├── VhxAuthProvider.cs          # VHX CSRF login flow
│       └── PatreonAuthProvider.cs      # Patreon stub
└── Tools/
    └── ToolsManager.cs                 # yt-dlp/ffmpeg path resolution

License

MIT

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 129 1/17/2026