Sintec.VideoDownloader
1.0.0
dotnet add package Sintec.VideoDownloader --version 1.0.0
NuGet\Install-Package Sintec.VideoDownloader -Version 1.0.0
<PackageReference Include="Sintec.VideoDownloader" Version="1.0.0" />
<PackageVersion Include="Sintec.VideoDownloader" Version="1.0.0" />
<PackageReference Include="Sintec.VideoDownloader" />
paket add Sintec.VideoDownloader --version 1.0.0
#r "nuget: Sintec.VideoDownloader, 1.0.0"
#:package Sintec.VideoDownloader@1.0.0
#addin nuget:?package=Sintec.VideoDownloader&version=1.0.0
#tool nuget:?package=Sintec.VideoDownloader&version=1.0.0
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
ToolsDirectoryoption
- 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:
- GET
/login- Extract CSRF token (authenticity_token) - POST
/login- Submit credentials with CSRF token - Verify
logged_in=1cookie - Write Netscape-format cookie file for yt-dlp
- 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 | Versions 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. |
-
net9.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Options (>= 9.0.0)
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 |