CheapHelpers.MediaProcessing
3.8.1
dotnet add package CheapHelpers.MediaProcessing --version 3.8.1
NuGet\Install-Package CheapHelpers.MediaProcessing -Version 3.8.1
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.
For projects that support PackageReference, copy this XML node into the project file to reference the package.
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 CheapHelpers.MediaProcessing --version 3.8.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: CheapHelpers.MediaProcessing, 3.8.1"
#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 CheapHelpers.MediaProcessing@3.8.1
#: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=CheapHelpers.MediaProcessing&version=3.8.1
#tool nuget:?package=CheapHelpers.MediaProcessing&version=3.8.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
CheapHelpers
A collection of production-ready C# utilities, extensions, and services for .NET 11.0 development. Simplify common development tasks with battle-tested helpers for Blazor, Entity Framework, networking, email, PDF generation, billing, reporting, and more.
Packages
| Package | Version | Description |
|---|---|---|
| CheapHelpers | Core utilities, extensions, threading, and scheduling | |
| CheapHelpers.Models | Shared entities, DTOs, enums, and UBL invoice models | |
| CheapHelpers.EF | Entity Framework repository pattern with Identity support | |
| CheapHelpers.Services | Email, PDF, billing, reporting, notifications, auth, and integrations | |
| CheapHelpers.Blazor | Blazor components, account module, auth endpoints, and Hybrid features | |
| CheapHelpers.Networking | Network scanning, mDNS discovery, and device detection | |
| CheapHelpers.MAUI | MAUI platform implementations (iOS APNS, Android FCM) | |
| CheapHelpers.MediaProcessing | FFmpeg integration, hardware detection (Windows/Linux) | |
| CheapHelpers.Avalonia.Bridge | Desktop notification bridge for Avalonia apps |
Installation
# Core utilities and extensions
dotnet add package CheapHelpers
# Entity Framework repository pattern
dotnet add package CheapHelpers.EF
# Business services (email, PDF, billing, reporting, notifications)
dotnet add package CheapHelpers.Services
# Blazor components, account module, and Hybrid features
dotnet add package CheapHelpers.Blazor
# Network scanning and device discovery
dotnet add package CheapHelpers.Networking
Quick Start
String Extensions
using CheapHelpers.Extensions;
"hello world".Capitalize(); // "Hello world"
"0474123456".ToInternationalPhoneNumber(); // "+32474123456"
"Very long text here".TrimWithEllipsis(10); // "Very long ..."
"my:invalid*file".SanitizeFileName(); // "my_invalid_file"
Email Service (3 providers)
using CheapHelpers.Services.Email;
// MailKit (SMTP), Microsoft Graph, or SendGrid
var emailService = new SendGridEmailService(
fromName: "MyApp",
fromAddress: "noreply@myapp.com",
apiKey: "SG.xxx",
inDev: false,
developers: ["dev@myapp.com"]);
await emailService.SendEmailAsync(
"user@example.com", "Welcome!", "Welcome!
",
attachments: [("invoice.pdf", pdfBytes)]);
Email Templates (Fluid/Liquid)
// Template data class
public class WelcomeEmailTemplateData : BaseEmailTemplateData
{
public override string Subject => $"Welcome, {UserName}!";
public string UserName { get; set; }
public string ActivationLink { get; set; }
}
// Render and send
var templateService = new EmailTemplateService(...);
var result = await templateService.RenderEmailAsync(new WelcomeEmailTemplateData
{
UserName = "John",
ActivationLink = "https://myapp.com/activate/abc123"
});
await emailService.SendEmailAsync("john@example.com", result.Subject, result.HtmlBody);
Notification System
// Register with multi-channel support
services.AddCheapNotifications(options =>
{
options.EnabledChannels = NotificationChannelFlags.InApp | NotificationChannelFlags.Email;
options.RealTimeProvider = "SignalR"; // Default. Use "RabbitMQ" for multi-server
});
// Blazor real-time (SignalR)
services.AddCheapNotificationsBlazor();
app.MapCheapNotificationsHub();
// Optional: RabbitMQ for cross-server delivery (SignalR stays client-facing)
services.AddCheapNotificationsRabbitMQConsumer("amqp://localhost");
API Key System
services.AddCheapApiKeys(options =>
{
options.KeyPrefix = "myapp_";
options.DefaultRateLimitPerMinute = 100;
});
// Generate — full key only returned once
var result = await apiKeyService.GenerateAsync(
userId, "Production API",
scopes: ["read", "write"],
prefixOverride: "VTQ_", // Per-call prefix override
expiresAt: DateTime.UtcNow.AddYears(1));
// result.FullKey = "VTQ_a7f3bc91..." (store immediately!)
// Validate
var validation = await apiKeyService.ValidateAsync(rawKey);
if (validation.IsValid)
Debug.WriteLine($"User: {validation.UserId}, Scopes: {string.Join(",", validation.Scopes)}");
Billing Service (Metered Usage)
services.AddCheapBilling(options =>
{
options.DefaultTaxRate = 21.00m; // Belgian VAT
options.InvoiceNumberPrefix = "INV";
});
// Record API usage (fire-and-forget safe)
await usageMeter.RecordUsageAsync(apiKeyId, "/api/data", "GET", 200, durationMs: 42);
// Generate invoice for a billing period
var invoice = await billingService.GenerateInvoiceAsync(
apiKeyId, billingPlanId,
new DateTime(2026, 3, 1), new DateTime(2026, 3, 31));
PEPPOL BIS 3.0 Invoicing
using CheapHelpers.Services.DataExchange.Ubl;
// Simple API — fluent builder, no UBL knowledge needed
var invoice = InvoiceBuilder.Create("INV-2026-000001")
.From("My Company", vatNumber: "BE0123456789")
.To("Acme Corp", vatNumber: "BE9876543210")
.DueIn(days: 30)
.AddLine("API calls - March 2026", quantity: 50000, unitPrice: 0.001m, vatPercent: 21)
.AddLine("Premium support", quantity: 1, unitPrice: 150.00m, vatPercent: 21)
.WithPayment(iban: "BE68539007547034", bic: "BBRUBEBB")
.Build();
// Tax totals, line totals, and monetary totals are calculated automatically
var invoiceService = new UblInvoiceService();
var xml = await invoiceService.CreateInvoiceXmlAsync(invoice);
// Credit notes work the same way
var creditNote = CreditNoteBuilder.Create("CN-2026-000001")
.CreditsInvoice("INV-2026-000001")
.WithReason("Overcharged API calls")
.From("My Company", vatNumber: "BE0123456789")
.To("Acme Corp", vatNumber: "BE9876543210")
.AddLine("API call correction", quantity: 10000, unitPrice: 0.001m, vatPercent: 21)
.Build();
// Advanced: use UblInvoice DTOs directly for full PEPPOL control
var advancedInvoice = new UblInvoice { /* full UBL model access */ };
Reporting Service
services.AddCheapReporting(options =>
{
options.StorageProvider = StorageProviderType.AzureBlob;
options.AzureBlobConnectionString = "...";
options.DefaultRetentionDays = 90;
});
// Generate PDF report
var result = await reportService.GenerateReportAsync(new ReportRequest
{
Name = "Monthly Sales",
Format = ReportFormat.Pdf,
Data = salesRecords,
Template = myPdfTemplate,
DistributeToEmails = ["manager@company.com"], // Auto-email after generation
RetentionDays = 30
});
// Download later
var (content, fileName, mimeType) = await reportService.DownloadReportAsync(result.ReportId);
Authentication (Multiple Providers)
// Plex SSO
services.AddPlexAuth(options => { options.AdminToken = "..."; });
app.MapPlexAuthEndpoints(); // /auth/plex-start, /auth/plex-callback, /auth/logout
// Google + Microsoft OAuth
services.AddGoogleAuth(options => { options.ClientId = "..."; options.ClientSecret = "..."; });
services.AddMicrosoftAuth(options => { options.ClientId = "..."; options.ClientSecret = "..."; });
// GitHub + Apple OAuth
services.AddGitHubAuth(options => { options.ClientId = "..."; });
services.AddAppleAuth(options => { options.TeamId = "..."; options.KeyId = "..."; });
// Optional: auto-provision CheapUser from external auth
services.AddExternalUserProvisioning();
Blazor Account Module
// Register services
services.AddCheapHelpersBlazor(options =>
{
options.UseEmailService();
options.AccountRouteOptions = new AccountRouteOptions
{
LoginRoute = "/auth/login",
};
});
// Consumer creates their own controller (one line):
[Route("Account/[action]")]
public class AccountController : CheapAccountController;
// Built-in pages: Login, Register, ForgotPassword, ResetPassword,
// ConfirmEmail, ConfirmEmailChange, SetPassword, ChangePassword,
// Authenticator (2FA), RecoveryCodes, PersonalData (GDPR), Lockout
// Account dashboard with extensible custom tabs
Entity Framework
// Generic context with Identity
services.AddCheapContext(options => options.UseSqlServer(connectionString))
.AddIdentity();
// Generic repository with pagination
public class ProductRepo(IDbContextFactory> factory)
: UserRepo(factory) where TUser : CheapUser { }
var users = await userRepo.GetAllUsersPaginatedAsync(pageIndex: 1, pageSize: 20);
var stats = await userRepo.GetUserStatisticsAsync();
Scheduling
using CheapHelpers.Scheduling;
scheduledTaskService.RegisterDailyTask("cleanup", new TimeOnly(2, 0), async ct =>
{
await notificationService.DeleteExpiredAsync(ct);
});
scheduledTaskService.RegisterMonthlyTask("billing", 1, new TimeOnly(3, 0), async ct =>
{
await billingService.RunBillingCycleAsync(ct);
});
Network Scanning
services.AddNetworkScanning()
.AddAllDetectors() // UPnP, mDNS, HTTP, SSH
.AddJsonStorage();
var scanner = serviceProvider.GetRequiredService();
scanner.DeviceDiscovered += (device) =>
Debug.WriteLine($"Found: {device.Name} ({device.IPv4Address})");
scanner.Start();
Project Structure
CheapHelpers/ Core utilities, extensions, scheduling, threading
CheapHelpers.Models/ Entities, DTOs, enums, UBL invoice models
CheapHelpers.EF/ Entity Framework, CheapContext, repositories
CheapHelpers.Services/
├── ApiKeys/ API key generation, validation, rate limiting
├── Auth/ IExternalAuthProvider, Plex SSO service
├── Billing/ Usage metering, invoice generation, billing cycles
├── DataExchange/
│ ├── Csv/ CSV import/export
│ ├── Excel/ Excel generation (ClosedXML)
│ ├── Json/ JSON file service
│ ├── Pdf/ PDF generation (iText) + optimization (iLovePDF)
│ ├── Ubl/ UBL Order/Invoice/CreditNote (UblSharp, PEPPOL BIS 3.0)
│ └── Xml/ XML serialization
├── Email/ MailKit, Microsoft Graph, SendGrid + Fluid templates
├── Geocoding/ Mapbox, Azure Maps, Google Maps, PTV Maps
├── Notifications/ Multi-channel (InApp, Email, SMS, Push) + RabbitMQ
├── Polling/ HTTP polling with exponential backoff
├── Reporting/ Report generation, storage, distribution, scheduling
└── Storage/ Azure Blob Storage
CheapHelpers.Blazor/
├── Components/ NotificationBell, CultureSelector
├── Extensions/ DI, Plex/OAuth/notification endpoint mapping
├── Helpers/ AuthenticatorHelper, AccountTabDefinition
├── Hybrid/ WebView bridge, push notifications, app bar
├── Middleware/ API key middleware
├── Pages/Account/ Full account module (login, register, 2FA, GDPR)
├── Services/ UserService, ExternalUserProvisioner, RabbitMQ consumer
└── Shared/ LoginDisplay, UploadFile, ImagePanel, Selectors
CheapHelpers.Networking/ Network scanner, mDNS discovery, device detectors
CheapHelpers.MediaProcessing/ FFmpeg integration, hardware detection (Win/Linux)
CheapHelpers.MAUI/ iOS APNS, Android FCM, status bar helpers
CheapHelpers.Avalonia.Bridge/ Desktop notification adapter
Key Dependencies
| Package | Used For |
|---|---|
| MailKit | SMTP email delivery |
| Microsoft.Graph | Microsoft Graph email |
| SendGrid | SendGrid email API |
| Fluid.Core | Liquid email templates |
| iText + iText.PdfOptimizer | PDF generation and optimization |
| ILove_PDF | Cloud PDF optimization |
| UblSharp | UBL 2.1 document generation (PEPPOL BIS 3.0) |
| RabbitMQ.Client | Cross-server notification transport |
| MudBlazor | Blazor UI components |
| ClosedXML | Excel file generation |
| Humanizer.Core | Relative timestamp formatting |
| FluentValidation | Form validation |
| Azure.Storage.Blobs | Report/file storage |
| Azure.Identity + Microsoft.Graph | Azure AD authentication |
| Microsoft.Azure.NotificationHubs | Push notification backend |
Requirements
- .NET 11.0 or later
- C# 15
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
git clone https://github.com/CheapNud/CheapHelpers.git
cd CheapHelpers
dotnet restore
dotnet build
License
This project is licensed under the MIT License - see the LICENSE.txt file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net11.0 is compatible. net11.0-windows7.0 is compatible. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net11.0
- CheapHelpers (>= 3.8.1)
- FFMpegCore (>= 5.4.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.11)
- Polly (>= 8.7.0)
- SharpCompress (>= 1.0.0)
-
net11.0-windows7.0
- CheapHelpers (>= 3.8.1)
- FFMpegCore (>= 5.4.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.11)
- Polly (>= 8.7.0)
- SharpCompress (>= 1.0.0)
- System.Management (>= 10.0.11)
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 |
|---|---|---|
| 3.8.1 | 116 | 9/3/2026 |
| 3.8.0 | 117 | 8/18/2026 |
| 3.7.0 | 123 | 7/23/2026 |
| 3.6.0 | 121 | 7/11/2026 |
| 3.5.1 | 138 | 5/9/2026 |
| 3.5.0 | 150 | 4/18/2026 |
| 3.4.3 | 137 | 3/30/2026 |
| 3.4.2 | 140 | 3/29/2026 |
| 3.4.0 | 142 | 3/29/2026 |
| 3.3.0 | 136 | 3/28/2026 |
| 3.2.0 | 134 | 3/21/2026 |
| 2.1.0 | 185 | 2/14/2026 |
| 2.0.1 | 250 | 1/24/2026 |
| 2.0.0 | 159 | 1/24/2026 |
| 1.3.0 | 160 | 1/18/2026 |
| 1.2.0 | 215 | 1/10/2026 |