Kuwait.Lis.PixCrypt
1.0.10
dotnet add package Kuwait.Lis.PixCrypt --version 1.0.10
NuGet\Install-Package Kuwait.Lis.PixCrypt -Version 1.0.10
<PackageReference Include="Kuwait.Lis.PixCrypt" Version="1.0.10" />
<PackageVersion Include="Kuwait.Lis.PixCrypt" Version="1.0.10" />
<PackageReference Include="Kuwait.Lis.PixCrypt" />
paket add Kuwait.Lis.PixCrypt --version 1.0.10
#r "nuget: Kuwait.Lis.PixCrypt, 1.0.10"
#:package Kuwait.Lis.PixCrypt@1.0.10
#addin nuget:?package=Kuwait.Lis.PixCrypt&version=1.0.10
#tool nuget:?package=Kuwait.Lis.PixCrypt&version=1.0.10
Kuwait.Lis.PixCrypt
A .NET library for media encryption and cloud storage operations for Kuwait LIS services.
Features
- Media Encryption/Decryption: AES encryption using
CryptoStreamfor memory-efficient streaming - Media Compression:
- Images: Quality-aware re-encoding (JPEG, PNG, WebP, GIF, BMP) with size guard — never returns a larger file than the original
- Videos: H.264/H.265 transcoding via FFmpeg (50–80% size reduction)
- Documents: GZip compression for PDF, DOC, XLS, etc.
- Auto FFmpeg Installation: Automatically downloads FFmpeg binaries on first use (thread-safe, one-time)
- Azure Blob Storage: Upload, download, and delete files from Azure using
BlockBlobClient - AWS S3 Storage: Upload, download, and delete files from AWS S3 with cached client instances
- Chunk Upload: Large file upload with chunking support (Azure & AWS) with automatic session expiry (2 hours)
- AWS S3 Multipart Upload: Native S3 multipart chunk upload without full-file buffering
- Dependency Injection: First-class DI support via
AddPixCrypt()extension - Typed Storage Options: Separate
AzureStorageOptionsandAwsStorageOptionsfor compile-time safety - Plug & Play: All credentials passed at runtime — no configuration files needed
Installation
dotnet add package Kuwait.Lis.PixCrypt
Dependency Injection Setup
Register all PixCrypt services in your DI container:
// Program.cs / Startup.cs
builder.Services.AddPixCrypt();
Then inject services directly:
public class MyService
{
private readonly MediaEncryptionService _encryption;
private readonly MediaCompressionService _compression;
public MyService(MediaEncryptionService encryption, MediaCompressionService compression)
{
_encryption = encryption;
_compression = compression;
}
}
Or use the static PixCryptHelper facade for quick usage without DI.
Usage
Media Compression
Image Compression
using Kuwait.Lis.PixCrypt.Helpers;
// Compress image (re-encodes at quality 80)
// Returns original bytes if re-encoded result is larger (e.g. already-compressed JPEG)
byte[] compressed = await PixCryptHelper.CompressBytesAsync(imageData, "photo.jpg", imageQuality: 80);
// Decompress (for GZip-compressed files only, not needed for images)
byte[] original = PixCryptHelper.DecompressBytes(compressed);
Video Compression (FFmpeg)
using Kuwait.Lis.PixCrypt.Helpers;
using Kuwait.Lis.PixCrypt.Models;
// Basic video compression (H.264, CRF 28, auto-download FFmpeg if needed)
byte[] compressed = await PixCryptHelper.CompressBytesAsync(videoData, "video.mp4");
// Advanced video compression with custom options
var videoOptions = new VideoCompressionOptions
{
Codec = VideoCodec.H265, // H264 or H265 (better compression)
Crf = 28, // Quality: 0 (best) – 51 (worst). Recommended: 23–30
Preset = EncodingPreset.Fast, // Speed vs compression trade-off
MaxResolution = new VideoResolution
{
Width = 1280,
Height = 720
},
AudioBitrateKbps = 128, // Audio quality (0 = strip audio)
FfmpegPath = "/app/ffmpeg-bins" // Optional: persistent FFmpeg location
};
byte[] compressed = await PixCryptHelper.CompressBytesAsync(
videoData,
"large-video.mp4",
videoOptions: videoOptions
);
FFmpeg Auto-Installation:
- FFmpeg binaries are automatically downloaded on first use (~70MB, one-time)
- Initialization is thread-safe — concurrent calls will not trigger duplicate downloads
- Default download location:
%TEMP%/ffmpeg/(may be cleared on server restart) - For production: set
FfmpegPathto a persistent directory to avoid re-downloading
Video Compression Results:
- Typical size reduction: 50–80% depending on CRF and codec
- H.265 provides ~30% better compression than H.264 but slower encoding
- CRF 28 = good balance of quality and size
- Higher CRF = smaller file, lower quality
Document Compression
// Compress PDF/DOC/XLS with GZip (lossless)
byte[] compressed = await PixCryptHelper.CompressBytesAsync(pdfData, "document.pdf");
// Decompress
byte[] original = PixCryptHelper.DecompressBytes(compressed);
Media Encryption
Encryption uses CryptoStream internally for efficient handling of large files:
using Kuwait.Lis.PixCrypt.Services;
using Kuwait.Lis.PixCrypt.Models;
var encryptionService = new MediaEncryptionService();
var options = new EncryptionOptions
{
Key = "your-base64-key",
IV = "your-base64-iv"
};
// Encrypt bytes
byte[] encrypted = encryptionService.Encrypt(imageData, options);
// Decrypt bytes
byte[] decrypted = encryptionService.Decrypt(encrypted, options);
// Encrypt from stream (memory-efficient for large files)
await using var fileStream = File.OpenRead("large-file.bin");
byte[] encrypted = await encryptionService.EncryptAsync(fileStream, options, cancellationToken);
Typed Storage Options
Use AzureStorageOptions or AwsStorageOptions for compile-time validation instead of the base StorageOptions:
// Azure — required properties enforced at compile time
var azureOptions = new AzureStorageOptions
{
AzureConnectionString = "your-connection-string",
AzureContainerName = "your-container"
};
// AWS — required properties enforced at compile time
var awsOptions = new AwsStorageOptions
{
AwsAccessKeyId = "your-access-key",
AwsSecretAccessKey = "your-secret-key",
AwsBucketName = "your-bucket",
AwsRegion = "us-east-1"
};
Azure Storage
using Kuwait.Lis.PixCrypt.Helpers;
using Kuwait.Lis.PixCrypt.Models;
// Upload with video compression
var result = await PixCryptHelper.UploadToAzureAsync(
filePath: "large-video.mp4",
connectionString: "your-connection-string",
containerName: "your-container",
compress: true,
videoOptions: new VideoCompressionOptions { Codec = VideoCodec.H265, Crf = 28 }
);
// Upload with encryption + compression
var result = await PixCryptHelper.UploadToAzureAsync(
filePath: "video.mp4",
connectionString: "your-connection-string",
containerName: "your-container",
encryptionKey: "your-key",
encryptionIV: "your-iv",
compress: true,
videoOptions: new VideoCompressionOptions { Crf = 30 }
);
// Download
string outputPath = await PixCryptHelper.DownloadFromAzureAsync(
fileName: "video.mp4",
destinationFolderPath: "/downloads",
connectionString: "your-connection-string",
containerName: "your-container"
);
// Download and decrypt
string outputPath = await PixCryptHelper.DownloadAndDecryptFromAzureAsync(
fileName: "video.mp4",
destinationFolderPath: "/downloads",
connectionString: "your-connection-string",
containerName: "your-container",
encryptionKey: "your-key",
encryptionIV: "your-iv"
);
// Delete
bool deleted = await PixCryptHelper.DeleteFromAzureAsync(
fileName: "video.mp4",
connectionString: "your-connection-string",
containerName: "your-container"
);
AWS S3 Storage
AWS S3 clients are cached per accessKeyId + region — no new client is created per call:
var result = await PixCryptHelper.UploadToAwsAsync(
filePath: "large-video.mp4",
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucketName: "your-bucket",
region: "us-east-1",
compress: true,
videoOptions: new VideoCompressionOptions
{
Codec = VideoCodec.H265,
Crf = 28,
MaxResolution = new VideoResolution { Width = 1920, Height = 1080 }
}
);
// Download
string outputPath = await PixCryptHelper.DownloadFromAwsAsync(
fileName: "large-video.mp4",
destinationFolderPath: "/downloads",
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucketName: "your-bucket",
region: "us-east-1"
);
// Delete
bool deleted = await PixCryptHelper.DeleteFromAwsAsync(
fileName: "large-video.mp4",
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucketName: "your-bucket",
region: "us-east-1"
);
Chunk Upload (Azure)
Sessions are automatically expired after 2 hours if not completed:
var result = await PixCryptHelper.ChunkUploadToAzureAsync(
filePath: "huge-video.mp4",
connectionString: "your-connection-string",
containerName: "your-container",
compress: true,
videoOptions: new VideoCompressionOptions
{
Codec = VideoCodec.H265,
Crf = 30,
Preset = EncodingPreset.Fast
},
chunkSizeBytes: 5 * 1024 * 1024 // 5MB chunks
);
AWS S3 Multipart Chunk Upload
Uses native S3 multipart upload — parts are uploaded directly to S3 without full-file reassembly in memory:
var result = await PixCryptHelper.ChunkUploadToAwsAsync(
filePath: "huge-video.mp4",
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucketName: "your-bucket",
region: "us-east-1",
compress: true,
videoOptions: new VideoCompressionOptions { Codec = VideoCodec.H265, Crf = 28 },
chunkSizeBytes: 5 * 1024 * 1024
);
Combined: Compress, Encrypt & Upload
// Full pipeline: compress video → encrypt → upload to S3
var result = await PixCryptHelper.UploadToAwsAsync(
filePath: "sensitive-video.mp4",
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucketName: "your-bucket",
region: "us-east-1",
encryptionKey: "your-encryption-key",
encryptionIV: "your-encryption-iv",
compress: true,
videoOptions: new VideoCompressionOptions
{
Codec = VideoCodec.H265,
Crf = 28,
MaxResolution = new VideoResolution { Width = 1280, Height = 720 },
AudioBitrateKbps = 128
}
);
Video Compression Configuration
VideoCompressionOptions Properties
| Property | Type | Default | Description |
|---|---|---|---|
FfmpegPath |
string? |
null |
Path to FFmpeg binaries. If null, auto-downloads to %TEMP%/ffmpeg/ |
Codec |
VideoCodec |
H264 |
H264 (wider support) or H265 (better compression) |
Crf |
int |
28 |
Quality: 0 (lossless) – 51 (worst). H264: 23–28, H265: 24–30 |
Preset |
EncodingPreset |
Medium |
Speed vs compression: Ultrafast, Fast, Medium, Slow, Veryslow |
MaxResolution |
VideoResolution? |
null |
Cap resolution (e.g., 1280x720). Null = keep original |
AudioBitrateKbps |
int |
128 |
Audio quality in kbps. Set to 0 to strip audio |
Recommended Settings by Use Case
High Quality (minimal compression):
new VideoCompressionOptions { Codec = VideoCodec.H265, Crf = 23, Preset = EncodingPreset.Slow }
Balanced (recommended for most cases):
new VideoCompressionOptions { Codec = VideoCodec.H265, Crf = 28, Preset = EncodingPreset.Medium }
Maximum Compression (smaller files, lower quality):
new VideoCompressionOptions { Codec = VideoCodec.H265, Crf = 32, Preset = EncodingPreset.Fast }
Mobile/Web Optimized:
new VideoCompressionOptions
{
Codec = VideoCodec.H264, // Better browser support
Crf = 28,
MaxResolution = new VideoResolution { Width = 1280, Height = 720 },
AudioBitrateKbps = 96
}
FFmpeg Installation
Automatic (Recommended)
No action needed — FFmpeg binaries are automatically downloaded on first video compression (~70MB, one-time). The initialization is protected by a SemaphoreSlim so concurrent requests will not trigger duplicate downloads.
Manual Installation (Optional)
Linux:
apt-get install ffmpeg
Windows:
- Download from ffmpeg.org
- Set
FfmpegPathinVideoCompressionOptionsto the directory containing the binaries
Docker:
RUN apt-get update && apt-get install -y ffmpeg
Production Recommendation
Set a persistent FfmpegPath to avoid re-downloading on every app restart:
var videoOptions = new VideoCompressionOptions
{
FfmpegPath = "/app/ffmpeg-bins", // Persistent across restarts
Codec = VideoCodec.H265,
Crf = 28
};
Build and Package
# Build
dotnet build --configuration Release
# Pack
dotnet pack --configuration Release --output ./packages
# Push to NuGet (optional)
dotnet nuget push ./packages/Kuwait.Lis.PixCrypt.1.0.0.nupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json
Dependencies
- .NET 10.0
- Azure.Storage.Blobs (12.24.0)
- AWSSDK.S3 (3.7.408)
- SixLabors.ImageSharp (3.1.12)
- Xabe.FFmpeg (6.0.2)
- Xabe.FFmpeg.Downloader (6.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (10.0.0)
Performance Considerations
- Image compression: Returns original bytes if re-encoded result is larger — no unnecessary overhead
- Encryption: Uses
CryptoStreamfor streaming — avoids doubling memory usage on large files - AWS S3 client: Cached per
accessKeyId + region— eliminates connection pool exhaustion under load - Video compression: CPU-intensive, async (time depends on video length and preset)
- 1-minute 1080p video: ~10–30 seconds with
Mediumpreset - Use
FastorUltrafastpreset for faster encoding (larger output files)
- 1-minute 1080p video: ~10–30 seconds with
- Large videos (>100MB): Use chunk upload to avoid memory pressure
- FFmpeg download: ~70MB, happens once per server lifetime (or per restart if using
%TEMP%) - Chunk sessions: Automatically purged after 2 hours to prevent memory leaks from abandoned uploads
License
MIT License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- AWSSDK.S3 (>= 3.7.408)
- Azure.Storage.Blobs (>= 12.24.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- SixLabors.ImageSharp (>= 3.1.12)
- Xabe.FFmpeg (>= 6.0.2)
- Xabe.FFmpeg.Downloader (>= 6.0.2)
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 |
|---|