Last active
September 15, 2025 20:25
-
-
Save emilwojcik93/868fbc801667e65e334679fec62b6879 to your computer and use it in GitHub Desktop.
Revisions
-
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 528 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,528 @@ # VideoCompressor - PowerShell Video Compression Tool # Optimized for cloud storage platforms (OneDrive, YouTube, SharePoint, etc.) function Test-FFmpegInstallation { <# .SYNOPSIS Checks if FFmpeg is available and installs it if not found #> # Check if ffmpeg is available in PATH $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue $ffprobeAvailable = Get-Command ffprobe -ErrorAction SilentlyContinue # If not found in PATH, check winget packages directory if (-not $ffmpegAvailable -or -not $ffprobeAvailable) { Write-Host "FFmpeg not found in PATH. Checking winget packages..." -ForegroundColor Yellow $wingetPath = "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" if (Test-Path $wingetPath) { # Look for FFmpeg packages $ffmpegDirs = @( "Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe", "BtbN.FFmpeg*", "*FFmpeg*" ) foreach ($pattern in $ffmpegDirs) { $packageDirs = Get-ChildItem -Path $wingetPath -Directory -Name $pattern -ErrorAction SilentlyContinue foreach ($packageDir in $packageDirs) { $fullPackagePath = Join-Path $wingetPath $packageDir # Look for bin directories recursively $binDirs = Get-ChildItem -Path $fullPackagePath -Recurse -Directory -Name "bin" -ErrorAction SilentlyContinue foreach ($binDir in $binDirs) { $binPath = Join-Path $fullPackagePath $binDir $ffmpegExe = Join-Path $binPath "ffmpeg.exe" $ffprobeExe = Join-Path $binPath "ffprobe.exe" if ((Test-Path $ffmpegExe) -and (Test-Path $ffprobeExe)) { Write-Host "Found FFmpeg installation at: $binPath" -ForegroundColor Green # Add to current session PATH if ($env:PATH -notlike "*$binPath*") { $env:PATH += ";$binPath" Write-Host "Added to current session PATH: $binPath" -ForegroundColor Green } # Ask user if they want to add to permanent PATH $addToPermanentPath = Read-Host "Add FFmpeg to permanent system PATH? (y/n)" if ($addToPermanentPath -eq 'y' -or $addToPermanentPath -eq 'Y') { try { # Get current user PATH $userPath = [System.Environment]::GetEnvironmentVariable("PATH", "User") if ($userPath -notlike "*$binPath*") { $newUserPath = "$userPath;$binPath" [System.Environment]::SetEnvironmentVariable("PATH", $newUserPath, "User") Write-Host "Added to permanent user PATH. Restart PowerShell for changes to take effect." -ForegroundColor Green } else { Write-Host "FFmpeg is already in permanent PATH." -ForegroundColor Yellow } } catch { Write-Host "Failed to update permanent PATH: $($_.Exception.Message)" -ForegroundColor Red } } # Verify the commands are now available $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue $ffprobeAvailable = Get-Command ffprobe -ErrorAction SilentlyContinue if ($ffmpegAvailable -and $ffprobeAvailable) { Write-Host "FFmpeg is now available!" -ForegroundColor Green return $true } } } } } } } if (-not $ffmpegAvailable -or -not $ffprobeAvailable) { Write-Host "FFmpeg is not recognized as an internal or external command." -ForegroundColor Red Write-Host "FFmpeg is required for video compression." -ForegroundColor Yellow Write-Host "" Write-Host "Available installation options via winget:" -ForegroundColor Cyan Write-Host "1. Gyan.FFmpeg (MSVC build - Best Windows compatibility)" -ForegroundColor Green Write-Host "2. BtbN.FFmpeg.GPL (MinGW build - Latest features)" -ForegroundColor Yellow Write-Host "" $install = Read-Host "Do you want to install FFmpeg now? (y/n)" if ($install -eq 'y' -or $install -eq 'Y') { Write-Host "Installing FFmpeg (Gyan.FFmpeg)..." -ForegroundColor Yellow try { winget install Gyan.FFmpeg --accept-package-agreements --accept-source-agreements # Refresh PATH in current session $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") # Verify installation Start-Sleep -Seconds 3 $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue if (-not $ffmpegAvailable) { Write-Host "Primary installation failed. Trying alternative package (BtbN.FFmpeg.GPL)..." -ForegroundColor Yellow winget install BtbN.FFmpeg.GPL --accept-package-agreements --accept-source-agreements # Refresh PATH again $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") Start-Sleep -Seconds 3 $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue } if ($ffmpegAvailable) { Write-Host "FFmpeg installed successfully!" -ForegroundColor Green Write-Host "You may need to restart PowerShell for PATH changes to take effect." -ForegroundColor Yellow return $true } else { Write-Host "FFmpeg installation failed. Please install manually or restart PowerShell." -ForegroundColor Red Write-Host "Manual installation: Download from https://ffmpeg.org/download.html" -ForegroundColor Yellow return $false } } catch { Write-Host "Error installing FFmpeg: $($_.Exception.Message)" -ForegroundColor Red Write-Host "Please try installing manually:" -ForegroundColor Yellow Write-Host " winget install Gyan.FFmpeg" -ForegroundColor Cyan Write-Host " or: winget install BtbN.FFmpeg.GPL" -ForegroundColor Cyan return $false } } else { Write-Host "FFmpeg installation cancelled. Cannot proceed without FFmpeg." -ForegroundColor Red return $false } } return $true } function Get-VideoProperties { <# .SYNOPSIS Uses ffprobe to analyze video properties for optimal compression #> param( [Parameter(Mandatory = $true)] [string]$VideoPath ) try { # Get video information using ffprobe $probeOutput = ffprobe -v quiet -print_format json -show_streams -show_format "$VideoPath" | ConvertFrom-Json $videoStream = $probeOutput.streams | Where-Object { $_.codec_type -eq "video" } | Select-Object -First 1 $audioStream = $probeOutput.streams | Where-Object { $_.codec_type -eq "audio" } | Select-Object -First 1 $properties = @{ Duration = [math]::Round([double]$probeOutput.format.duration, 2) Width = [int]$videoStream.width Height = [int]$videoStream.height FrameRate = if ($videoStream.r_frame_rate) { $fps = $videoStream.r_frame_rate.Split('/') [math]::Round([double]$fps[0] / [double]$fps[1], 2) } else { 30 } VideoBitrate = if ($videoStream.bit_rate) { [int]$videoStream.bit_rate } else { 0 } AudioBitrate = if ($audioStream.bit_rate) { [int]$audioStream.bit_rate } else { 128000 } VideoCodec = $videoStream.codec_name AudioCodec = if ($audioStream) { $audioStream.codec_name } else { "none" } FileSize = [math]::Round((Get-Item $VideoPath).Length / 1MB, 2) } return $properties } catch { Write-Host "Error analyzing video: $($_.Exception.Message)" -ForegroundColor Red return $null } } function Get-OptimalCompressionSettings { <# .SYNOPSIS Determines optimal compression settings based on video properties and target platform #> param( [Parameter(Mandatory = $true)] [hashtable]$VideoProperties, [Parameter(Mandatory = $false)] [string]$CompressionMode = "Balanced" ) $width = $VideoProperties.Width $height = $VideoProperties.Height $fps = $VideoProperties.FrameRate $duration = $VideoProperties.Duration # Determine target resolution (maintain aspect ratio) $targetWidth = $width $targetHeight = $height # Optimize for cloud storage - limit resolution for better streaming if ($width -gt 1920 -or $height -gt 1080) { # Scale down to 1080p max while maintaining aspect ratio $aspectRatio = $width / $height if ($aspectRatio -gt (16/9)) { $targetWidth = 1920 $targetHeight = [math]::Round(1920 / $aspectRatio / 2) * 2 # Even number } else { $targetHeight = 1080 $targetWidth = [math]::Round(1080 * $aspectRatio / 2) * 2 # Even number } } # Optimize frame rate $targetFps = $fps if ($fps -gt 60) { $targetFps = 60 } elseif ($fps -gt 30 -and $duration -gt 600) { $targetFps = 30 } # Long videos benefit from 30fps # Determine CRF based on content type and duration $crf = 23 # Default balanced quality if ($duration -lt 300) { $crf = 21 } # Short videos - higher quality elseif ($duration -gt 3600) { $crf = 25 } # Long videos - more compression # Audio bitrate optimization $audioBitrate = "128k" if ($VideoProperties.AudioBitrate -gt 0) { if ($VideoProperties.AudioBitrate -le 96000) { $audioBitrate = "96k" } elseif ($VideoProperties.AudioBitrate -ge 256000) { $audioBitrate = "192k" } } # Choose preset and CRF based on compression mode switch ($CompressionMode) { "Fast" { $preset = "fast" $crf = $crf + 2 # Slightly higher CRF for faster encoding } "Quality" { $preset = "slow" $crf = $crf - 1 # Lower CRF for better quality } default { # "Balanced" $preset = "medium" # Keep calculated CRF as is } } # Try to detect hardware acceleration capabilities (only if ffmpeg is available) $hwEncoder = $null $hwAvailable = $false if (Get-Command ffmpeg -ErrorAction SilentlyContinue) { # Check for Intel QuickSync (common on Intel CPUs like Core Ultra) try { $null = ffmpeg -hide_banner -f lavfi -i testsrc2=duration=1:size=320x240:rate=1 -c:v h264_qsv -f null - 2>$null if ($LASTEXITCODE -eq 0) { $hwEncoder = "h264_qsv" $hwAvailable = $true } } catch { } # Check for NVIDIA NVENC if QuickSync not available if (-not $hwAvailable) { try { $null = ffmpeg -hide_banner -f lavfi -i testsrc2=duration=1:size=320x240:rate=1 -c:v h264_nvenc -f null - 2>$null if ($LASTEXITCODE -eq 0) { $hwEncoder = "h264_nvenc" $hwAvailable = $true } } catch { } } } $settings = @{ Resolution = "${targetWidth}x${targetHeight}" FrameRate = $targetFps CRF = $crf AudioBitrate = $audioBitrate Preset = $preset Profile = "high" Level = "4.0" HardwareEncoder = $hwEncoder HardwareAvailable = $hwAvailable } return $settings } function Get-OutputDirectory { <# .SYNOPSIS Determines the best output directory (OneDrive or Videos folder) #> # Check if OneDrive is available and service is running $oneDriveAvailable = $false if ($env:OneDrive -and (Test-Path $env:OneDrive)) { # Check if OneDrive service is running $oneDriveService = Get-Process -Name "OneDrive" -ErrorAction SilentlyContinue if ($oneDriveService) { $oneDriveAvailable = $true $outputDir = Join-Path $env:OneDrive "CompressedVideos" } } if (-not $oneDriveAvailable) { # Fallback to Videos directory using .NET method try { $videosPath = [System.Environment]::GetFolderPath('MyVideos') $outputDir = Join-Path $videosPath "CompressedVideos" } catch { # Final fallback to user profile $outputDir = Join-Path $env:USERPROFILE "Videos\CompressedVideos" } } # Create directory if it doesn't exist if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null Write-Host "Created output directory: $outputDir" -ForegroundColor Green } return $outputDir } function Compress-Video { <# .SYNOPSIS Compresses video files with optimal settings for cloud storage platforms .DESCRIPTION This function compresses video files using FFmpeg with settings optimized for cloud storage platforms like OneDrive, YouTube, SharePoint, and MS Stream. .PARAMETER SourceVideo Path to the source video file to compress .PARAMETER OutputDirectory Optional custom output directory. If not specified, uses OneDrive or Videos folder .PARAMETER CompressionMode Choose compression speed/quality balance: Fast, Balanced, Quality - Fast: Quick processing, good quality (faster than real-time) - Balanced: Good balance of speed and compression (default) - Quality: Best compression, slower processing .EXAMPLE Compress-Video "C:\Videos\MyVideo.mp4" .EXAMPLE Compress-Video -SourceVideo ".\Local Development Environment Setup Guide.mp4" -CompressionMode Fast #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$SourceVideo, [Parameter(Mandatory = $false)] [string]$OutputDirectory, [Parameter(Mandatory = $false)] [ValidateSet("Fast", "Balanced", "Quality")] [string]$CompressionMode = "Balanced" ) # Check if FFmpeg is available if (-not (Test-FFmpegInstallation)) { return } # Validate source file if (-not (Test-Path $SourceVideo)) { Write-Host "Error: Source video file not found: $SourceVideo" -ForegroundColor Red return } Write-Host "Analyzing video properties..." -ForegroundColor Yellow $videoProps = Get-VideoProperties -VideoPath $SourceVideo if (-not $videoProps) { Write-Host "Failed to analyze video properties." -ForegroundColor Red return } # Display video information Write-Host "`nVideo Information:" -ForegroundColor Cyan Write-Host "Duration: $($videoProps.Duration) seconds" Write-Host "Resolution: $($videoProps.Width)x$($videoProps.Height)" Write-Host "Frame Rate: $($videoProps.FrameRate) fps" Write-Host "File Size: $($videoProps.FileSize) MB" Write-Host "Video Codec: $($videoProps.VideoCodec)" Write-Host "Audio Codec: $($videoProps.AudioCodec)" # Get optimal compression settings $compressionSettings = Get-OptimalCompressionSettings -VideoProperties $videoProps -CompressionMode $CompressionMode Write-Host "`nOptimal Compression Settings:" -ForegroundColor Cyan Write-Host "Compression Mode: $CompressionMode" Write-Host "Target Resolution: $($compressionSettings.Resolution)" Write-Host "Target Frame Rate: $($compressionSettings.FrameRate) fps" Write-Host "CRF Quality: $($compressionSettings.CRF)" Write-Host "Audio Bitrate: $($compressionSettings.AudioBitrate)" Write-Host "Preset: $($compressionSettings.Preset)" if ($compressionSettings.HardwareAvailable) { Write-Host "Hardware Encoder: $($compressionSettings.HardwareEncoder) (faster processing)" -ForegroundColor Green } else { Write-Host "Hardware Encoder: Software only (h264)" -ForegroundColor Yellow } # Determine output directory and file path if (-not $OutputDirectory) { $OutputDirectory = Get-OutputDirectory } $sourceFileName = [System.IO.Path]::GetFileNameWithoutExtension($SourceVideo) $outputFileName = "${sourceFileName}_compressed.mp4" $outputPath = Join-Path $OutputDirectory $outputFileName # Check if output file already exists if (Test-Path $outputPath) { $counter = 1 do { $outputFileName = "${sourceFileName}_compressed_${counter}.mp4" $outputPath = Join-Path $OutputDirectory $outputFileName $counter++ } while (Test-Path $outputPath) } Write-Host "`nStarting compression..." -ForegroundColor Green Write-Host "Output will be saved to: $outputPath" -ForegroundColor Yellow # Build FFmpeg command with optimal settings if ($compressionSettings.HardwareAvailable -and $CompressionMode -ne "Quality") { # Use hardware encoder for faster processing (except in Quality mode) $videoCodec = $compressionSettings.HardwareEncoder # Calculate target bitrate based on resolution and frame rate $pixelCount = ($compressionSettings.Resolution -split 'x')[0] * ($compressionSettings.Resolution -split 'x')[1] $targetBitrate = [math]::Round(($pixelCount * $compressionSettings.FrameRate * 0.1) / 1000) # Rough estimate if ($targetBitrate -lt 1000) { $targetBitrate = 1000 } if ($targetBitrate -gt 8000) { $targetBitrate = 8000 } $ffmpegArgs = @( "-i", "`"$SourceVideo`"" "-c:v", $videoCodec "-b:v", "${targetBitrate}k" "-maxrate", "$([math]::Round($targetBitrate * 1.5))k" "-bufsize", "$([math]::Round($targetBitrate * 2))k" "-vf", "scale=$($compressionSettings.Resolution)" "-r", $compressionSettings.FrameRate "-c:a", "aac" "-b:a", $compressionSettings.AudioBitrate "-movflags", "+faststart" "-avoid_negative_ts", "make_zero" "-fflags", "+genpts" "-y" "`"$outputPath`"" ) } else { # Use software encoder with CRF $ffmpegArgs = @( "-i", "`"$SourceVideo`"" "-c:v", "libx264" "-preset", $compressionSettings.Preset "-crf", $compressionSettings.CRF "-profile:v", $compressionSettings.Profile "-level", $compressionSettings.Level "-vf", "scale=$($compressionSettings.Resolution)" "-r", $compressionSettings.FrameRate "-c:a", "aac" "-b:a", $compressionSettings.AudioBitrate "-movflags", "+faststart" "-avoid_negative_ts", "make_zero" "-fflags", "+genpts" "-y" "`"$outputPath`"" ) } try { $startTime = Get-Date Write-Host "Executing: ffmpeg $($ffmpegArgs -join ' ')" -ForegroundColor Gray # Execute FFmpeg command & ffmpeg @ffmpegArgs $endTime = Get-Date $processingTime = ($endTime - $startTime).TotalSeconds if (Test-Path $outputPath) { $outputFileSize = [math]::Round((Get-Item $outputPath).Length / 1MB, 2) $compressionRatio = [math]::Round((1 - ($outputFileSize / $videoProps.FileSize)) * 100, 1) Write-Host "`nCompression completed successfully!" -ForegroundColor Green Write-Host "Processing time: $([math]::Round($processingTime, 1)) seconds" Write-Host "Original size: $($videoProps.FileSize) MB" Write-Host "Compressed size: $outputFileSize MB" Write-Host "Compression ratio: $compressionRatio%" Write-Host "Output location: $outputPath" # Open output directory $openDir = Read-Host "`nOpen output directory? (y/n)" if ($openDir -eq 'y' -or $openDir -eq 'Y') { Start-Process "explorer.exe" -ArgumentList $OutputDirectory } } else { Write-Host "Compression failed - output file not found." -ForegroundColor Red } } catch { Write-Host "Error during compression: $($_.Exception.Message)" -ForegroundColor Red } } # Export the main function (only when loaded as a module) if ($MyInvocation.MyCommand.Path -and $MyInvocation.MyCommand.Path.EndsWith('.psm1')) { Export-ModuleMember -Function Compress-Video } -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 537 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,537 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 26 additions and 24 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,20 +1,24 @@ # VideoCompressor - Quick Start Guide **GitHub Gist**: https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879 ## TLDR - Two Simple Commands **Step 1: Download script to profile directory** ```powershell $profileDir = Split-Path $PROFILE -Parent; if(!(Test-Path $profileDir)){md $profileDir -Force}; iwr 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1' -OutFile "$profileDir\VideoCompressor.ps1" -UseBasicParsing ``` **Step 2: Add to PowerShell profile** ```powershell if(!(Select-String -Path $PROFILE -Pattern 'VideoCompressor.ps1' -Quiet -ErrorAction SilentlyContinue)){Add-Content -Path $PROFILE -Value "`n. '$((Split-Path $PROFILE -Parent))\VideoCompressor.ps1'" -Encoding UTF8} ``` **Step 3: Restart PowerShell** and use: `Compress-Video "video.mp4"` --- ## Detailed Installation Options ### Option 1: Install to PowerShell Profile (Recommended) @@ -34,8 +38,6 @@ powershell.exe -ExecutionPolicy Bypass -Command "& { }" ``` ### Option 2: Direct Execution (No Installation) **Run directly from gist without installing:** @@ -58,7 +60,7 @@ powershell.exe -ExecutionPolicy Bypass -Command " " ``` ## Quick Examples ```powershell # Basic compression (balanced mode) @@ -74,39 +76,39 @@ Compress-Video "MyVideo.mp4" -CompressionMode Quality Compress-Video "MyVideo.mp4" -OutputDirectory "C:\Compressed" ``` ## What It Does - Auto-installs FFmpeg if not found - Hardware acceleration (Intel/NVIDIA) - Reduces file size by 60-80% - Maintains visual quality - Optimized for cloud storage - Works with all video formats ## Requirements - Windows 10/11 - PowerShell 5.1+ - Internet connection (for FFmpeg auto-install) ## Profile Installation Details The two-step installation: 1. **Downloads script** to `$(Split-Path $PROFILE -Parent)\VideoCompressor.ps1` 2. **Adds profile entry** `. 'path\to\VideoCompressor.ps1'` to your `$PROFILE` 3. **Auto-loads** when PowerShell starts **Profile Path Examples:** - `C:\Users\YourName\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1` - `C:\Users\YourName\Documents\PowerShell\Microsoft.PowerShell_profile.ps1` (PowerShell 7+) ## For Developers 1. **Clone this gist**: `git clone https://gist.github.com/868fbc801667e65e334679fec62b6879.git` 2. **Install locally**: Run `.\Install-VideoCompressor.ps1` 3. **Customize**: Edit `VideoCompressor.ps1` as needed --- Perfect for preparing videos for **OneDrive**, **YouTube**, **SharePoint**, or any cloud platform! -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 135 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,135 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 537 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,537 @@ # VideoCompressor - PowerShell Video Compression Tool # Optimized for cloud storage platforms (OneDrive, YouTube, SharePoint, etc.) function Test-FFmpegInstallation { <# .SYNOPSIS Checks if FFmpeg is available and installs it if not found #> # Check if ffmpeg is available in PATH $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue $ffprobeAvailable = Get-Command ffprobe -ErrorAction SilentlyContinue # If not found in PATH, check winget packages directory if (-not $ffmpegAvailable -or -not $ffprobeAvailable) { Write-Host "FFmpeg not found in PATH. Checking winget packages..." -ForegroundColor Yellow $wingetPath = "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" if (Test-Path $wingetPath) { # Look for FFmpeg packages $ffmpegDirs = @( "Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe", "BtbN.FFmpeg*", "*FFmpeg*" ) foreach ($pattern in $ffmpegDirs) { $packageDirs = Get-ChildItem -Path $wingetPath -Directory -Name $pattern -ErrorAction SilentlyContinue foreach ($packageDir in $packageDirs) { $fullPackagePath = Join-Path $wingetPath $packageDir # Look for bin directories recursively $binDirs = Get-ChildItem -Path $fullPackagePath -Recurse -Directory -Name "bin" -ErrorAction SilentlyContinue foreach ($binDir in $binDirs) { $binPath = Join-Path $fullPackagePath $binDir $ffmpegExe = Join-Path $binPath "ffmpeg.exe" $ffprobeExe = Join-Path $binPath "ffprobe.exe" if ((Test-Path $ffmpegExe) -and (Test-Path $ffprobeExe)) { Write-Host "Found FFmpeg installation at: $binPath" -ForegroundColor Green # Add to current session PATH if ($env:PATH -notlike "*$binPath*") { $env:PATH += ";$binPath" Write-Host "Added to current session PATH: $binPath" -ForegroundColor Green } # Ask user if they want to add to permanent PATH $addToPermanentPath = Read-Host "Add FFmpeg to permanent system PATH? (y/n)" if ($addToPermanentPath -eq 'y' -or $addToPermanentPath -eq 'Y') { try { # Get current user PATH $userPath = [System.Environment]::GetEnvironmentVariable("PATH", "User") if ($userPath -notlike "*$binPath*") { $newUserPath = "$userPath;$binPath" [System.Environment]::SetEnvironmentVariable("PATH", $newUserPath, "User") Write-Host "Added to permanent user PATH. Restart PowerShell for changes to take effect." -ForegroundColor Green } else { Write-Host "FFmpeg is already in permanent PATH." -ForegroundColor Yellow } } catch { Write-Host "Failed to update permanent PATH: $($_.Exception.Message)" -ForegroundColor Red } } # Verify the commands are now available $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue $ffprobeAvailable = Get-Command ffprobe -ErrorAction SilentlyContinue if ($ffmpegAvailable -and $ffprobeAvailable) { Write-Host "FFmpeg is now available!" -ForegroundColor Green return $true } } } } } } } if (-not $ffmpegAvailable -or -not $ffprobeAvailable) { Write-Host "FFmpeg is not recognized as an internal or external command." -ForegroundColor Red Write-Host "FFmpeg is required for video compression." -ForegroundColor Yellow Write-Host "" Write-Host "Available installation options via winget:" -ForegroundColor Cyan Write-Host "1. Gyan.FFmpeg (MSVC build - Best Windows compatibility)" -ForegroundColor Green Write-Host "2. BtbN.FFmpeg.GPL (MinGW build - Latest features)" -ForegroundColor Yellow Write-Host "" $install = Read-Host "Do you want to install FFmpeg now? (y/n)" if ($install -eq 'y' -or $install -eq 'Y') { Write-Host "Installing FFmpeg (Gyan.FFmpeg)..." -ForegroundColor Yellow try { winget install Gyan.FFmpeg --accept-package-agreements --accept-source-agreements # Refresh PATH in current session $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") # Verify installation Start-Sleep -Seconds 3 $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue if (-not $ffmpegAvailable) { Write-Host "Primary installation failed. Trying alternative package (BtbN.FFmpeg.GPL)..." -ForegroundColor Yellow winget install BtbN.FFmpeg.GPL --accept-package-agreements --accept-source-agreements # Refresh PATH again $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") Start-Sleep -Seconds 3 $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue } if ($ffmpegAvailable) { Write-Host "FFmpeg installed successfully!" -ForegroundColor Green Write-Host "You may need to restart PowerShell for PATH changes to take effect." -ForegroundColor Yellow return $true } else { Write-Host "FFmpeg installation failed. Please install manually or restart PowerShell." -ForegroundColor Red Write-Host "Manual installation: Download from https://ffmpeg.org/download.html" -ForegroundColor Yellow return $false } } catch { Write-Host "Error installing FFmpeg: $($_.Exception.Message)" -ForegroundColor Red Write-Host "Please try installing manually:" -ForegroundColor Yellow Write-Host " winget install Gyan.FFmpeg" -ForegroundColor Cyan Write-Host " or: winget install BtbN.FFmpeg.GPL" -ForegroundColor Cyan return $false } } else { Write-Host "FFmpeg installation cancelled. Cannot proceed without FFmpeg." -ForegroundColor Red return $false } } return $true } function Get-VideoProperties { <# .SYNOPSIS Uses ffprobe to analyze video properties for optimal compression #> param( [Parameter(Mandatory = $true)] [string]$VideoPath ) try { # Get video information using ffprobe $probeOutput = ffprobe -v quiet -print_format json -show_streams -show_format "$VideoPath" | ConvertFrom-Json $videoStream = $probeOutput.streams | Where-Object { $_.codec_type -eq "video" } | Select-Object -First 1 $audioStream = $probeOutput.streams | Where-Object { $_.codec_type -eq "audio" } | Select-Object -First 1 $properties = @{ Duration = [math]::Round([double]$probeOutput.format.duration, 2) Width = [int]$videoStream.width Height = [int]$videoStream.height FrameRate = if ($videoStream.r_frame_rate) { $fps = $videoStream.r_frame_rate.Split('/') [math]::Round([double]$fps[0] / [double]$fps[1], 2) } else { 30 } VideoBitrate = if ($videoStream.bit_rate) { [int]$videoStream.bit_rate } else { 0 } AudioBitrate = if ($audioStream.bit_rate) { [int]$audioStream.bit_rate } else { 128000 } VideoCodec = $videoStream.codec_name AudioCodec = if ($audioStream) { $audioStream.codec_name } else { "none" } FileSize = [math]::Round((Get-Item $VideoPath).Length / 1MB, 2) } return $properties } catch { Write-Host "Error analyzing video: $($_.Exception.Message)" -ForegroundColor Red return $null } } function Get-OptimalCompressionSettings { <# .SYNOPSIS Determines optimal compression settings based on video properties and target platform #> param( [Parameter(Mandatory = $true)] [hashtable]$VideoProperties, [Parameter(Mandatory = $false)] [string]$CompressionMode = "Balanced" ) $width = $VideoProperties.Width $height = $VideoProperties.Height $fps = $VideoProperties.FrameRate $duration = $VideoProperties.Duration # Determine target resolution (maintain aspect ratio) $targetWidth = $width $targetHeight = $height # Optimize for cloud storage - limit resolution for better streaming if ($width -gt 1920 -or $height -gt 1080) { # Scale down to 1080p max while maintaining aspect ratio $aspectRatio = $width / $height if ($aspectRatio -gt (16/9)) { $targetWidth = 1920 $targetHeight = [math]::Round(1920 / $aspectRatio / 2) * 2 # Even number } else { $targetHeight = 1080 $targetWidth = [math]::Round(1080 * $aspectRatio / 2) * 2 # Even number } } # Optimize frame rate $targetFps = $fps if ($fps -gt 60) { $targetFps = 60 } elseif ($fps -gt 30 -and $duration -gt 600) { $targetFps = 30 } # Long videos benefit from 30fps # Determine CRF based on content type and duration $crf = 23 # Default balanced quality if ($duration -lt 300) { $crf = 21 } # Short videos - higher quality elseif ($duration -gt 3600) { $crf = 25 } # Long videos - more compression # Audio bitrate optimization $audioBitrate = "128k" if ($VideoProperties.AudioBitrate -gt 0) { if ($VideoProperties.AudioBitrate -le 96000) { $audioBitrate = "96k" } elseif ($VideoProperties.AudioBitrate -ge 256000) { $audioBitrate = "192k" } } # Choose preset and CRF based on compression mode switch ($CompressionMode) { "Fast" { $preset = "fast" $crf = $crf + 2 # Slightly higher CRF for faster encoding } "Quality" { $preset = "slow" $crf = $crf - 1 # Lower CRF for better quality } default { # "Balanced" $preset = "medium" # Keep calculated CRF as is } } # Try to detect hardware acceleration capabilities (only if ffmpeg is available) $hwEncoder = $null $hwAvailable = $false if (Get-Command ffmpeg -ErrorAction SilentlyContinue) { # Check for Intel QuickSync (common on Intel CPUs like Core Ultra) try { $null = ffmpeg -hide_banner -f lavfi -i testsrc2=duration=1:size=320x240:rate=1 -c:v h264_qsv -f null - 2>$null if ($LASTEXITCODE -eq 0) { $hwEncoder = "h264_qsv" $hwAvailable = $true } } catch { } # Check for NVIDIA NVENC if QuickSync not available if (-not $hwAvailable) { try { $null = ffmpeg -hide_banner -f lavfi -i testsrc2=duration=1:size=320x240:rate=1 -c:v h264_nvenc -f null - 2>$null if ($LASTEXITCODE -eq 0) { $hwEncoder = "h264_nvenc" $hwAvailable = $true } } catch { } } } $settings = @{ Resolution = "${targetWidth}x${targetHeight}" FrameRate = $targetFps CRF = $crf AudioBitrate = $audioBitrate Preset = $preset Profile = "high" Level = "4.0" HardwareEncoder = $hwEncoder HardwareAvailable = $hwAvailable } return $settings } function Get-OutputDirectory { <# .SYNOPSIS Determines the best output directory (OneDrive or Videos folder) #> # Check if OneDrive is available and service is running $oneDriveAvailable = $false if ($env:OneDrive -and (Test-Path $env:OneDrive)) { # Check if OneDrive service is running $oneDriveService = Get-Process -Name "OneDrive" -ErrorAction SilentlyContinue if ($oneDriveService) { $oneDriveAvailable = $true $outputDir = Join-Path $env:OneDrive "CompressedVideos" } } if (-not $oneDriveAvailable) { # Fallback to Videos directory using .NET method try { $videosPath = [System.Environment]::GetFolderPath('MyVideos') $outputDir = Join-Path $videosPath "CompressedVideos" } catch { # Final fallback to user profile $outputDir = Join-Path $env:USERPROFILE "Videos\CompressedVideos" } } # Create directory if it doesn't exist if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null Write-Host "Created output directory: $outputDir" -ForegroundColor Green } return $outputDir } function Compress-Video { <# .SYNOPSIS Compresses video files with optimal settings for cloud storage platforms .DESCRIPTION This function compresses video files using FFmpeg with settings optimized for cloud storage platforms like OneDrive, YouTube, SharePoint, and MS Stream. .PARAMETER SourceVideo Path to the source video file to compress .PARAMETER OutputDirectory Optional custom output directory. If not specified, uses OneDrive or Videos folder .PARAMETER CompressionMode Choose compression speed/quality balance: Fast, Balanced, Quality - Fast: Quick processing, good quality (faster than real-time) - Balanced: Good balance of speed and compression (default) - Quality: Best compression, slower processing .EXAMPLE Compress-Video "C:\Videos\MyVideo.mp4" .EXAMPLE Compress-Video -SourceVideo ".\Local Development Environment Setup Guide.mp4" -CompressionMode Fast #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$SourceVideo, [Parameter(Mandatory = $false)] [string]$OutputDirectory, [Parameter(Mandatory = $false)] [ValidateSet("Fast", "Balanced", "Quality")] [string]$CompressionMode = "Balanced" ) # Check if FFmpeg is available if (-not (Test-FFmpegInstallation)) { return } # Validate source file if (-not (Test-Path $SourceVideo)) { Write-Host "Error: Source video file not found: $SourceVideo" -ForegroundColor Red return } Write-Host "Analyzing video properties..." -ForegroundColor Yellow $videoProps = Get-VideoProperties -VideoPath $SourceVideo if (-not $videoProps) { Write-Host "Failed to analyze video properties." -ForegroundColor Red return } # Display video information Write-Host "`nVideo Information:" -ForegroundColor Cyan Write-Host "Duration: $($videoProps.Duration) seconds" Write-Host "Resolution: $($videoProps.Width)x$($videoProps.Height)" Write-Host "Frame Rate: $($videoProps.FrameRate) fps" Write-Host "File Size: $($videoProps.FileSize) MB" Write-Host "Video Codec: $($videoProps.VideoCodec)" Write-Host "Audio Codec: $($videoProps.AudioCodec)" # Get optimal compression settings $compressionSettings = Get-OptimalCompressionSettings -VideoProperties $videoProps -CompressionMode $CompressionMode Write-Host "`nOptimal Compression Settings:" -ForegroundColor Cyan Write-Host "Compression Mode: $CompressionMode" Write-Host "Target Resolution: $($compressionSettings.Resolution)" Write-Host "Target Frame Rate: $($compressionSettings.FrameRate) fps" Write-Host "CRF Quality: $($compressionSettings.CRF)" Write-Host "Audio Bitrate: $($compressionSettings.AudioBitrate)" Write-Host "Preset: $($compressionSettings.Preset)" if ($compressionSettings.HardwareAvailable) { Write-Host "Hardware Encoder: $($compressionSettings.HardwareEncoder) (faster processing)" -ForegroundColor Green } else { Write-Host "Hardware Encoder: Software only (h264)" -ForegroundColor Yellow } # Determine output directory and file path if (-not $OutputDirectory) { $OutputDirectory = Get-OutputDirectory } $sourceFileName = [System.IO.Path]::GetFileNameWithoutExtension($SourceVideo) $outputFileName = "${sourceFileName}_compressed.mp4" $outputPath = Join-Path $OutputDirectory $outputFileName # Check if output file already exists if (Test-Path $outputPath) { $counter = 1 do { $outputFileName = "${sourceFileName}_compressed_${counter}.mp4" $outputPath = Join-Path $OutputDirectory $outputFileName $counter++ } while (Test-Path $outputPath) } Write-Host "`nStarting compression..." -ForegroundColor Green Write-Host "Output will be saved to: $outputPath" -ForegroundColor Yellow # Build FFmpeg command with optimal settings if ($compressionSettings.HardwareAvailable -and $CompressionMode -ne "Quality") { # Use hardware encoder for faster processing (except in Quality mode) $videoCodec = $compressionSettings.HardwareEncoder # Calculate target bitrate based on resolution and frame rate $pixelCount = ($compressionSettings.Resolution -split 'x')[0] * ($compressionSettings.Resolution -split 'x')[1] $targetBitrate = [math]::Round(($pixelCount * $compressionSettings.FrameRate * 0.1) / 1000) # Rough estimate if ($targetBitrate -lt 1000) { $targetBitrate = 1000 } if ($targetBitrate -gt 8000) { $targetBitrate = 8000 } $ffmpegArgs = @( "-i", "`"$SourceVideo`"" "-c:v", $videoCodec "-b:v", "${targetBitrate}k" "-maxrate", "$([math]::Round($targetBitrate * 1.5))k" "-bufsize", "$([math]::Round($targetBitrate * 2))k" "-vf", "scale=$($compressionSettings.Resolution)" "-r", $compressionSettings.FrameRate "-c:a", "aac" "-b:a", $compressionSettings.AudioBitrate "-movflags", "+faststart" "-avoid_negative_ts", "make_zero" "-fflags", "+genpts" "-y" "`"$outputPath`"" ) } else { # Use software encoder with CRF $ffmpegArgs = @( "-i", "`"$SourceVideo`"" "-c:v", "libx264" "-preset", $compressionSettings.Preset "-crf", $compressionSettings.CRF "-profile:v", $compressionSettings.Profile "-level", $compressionSettings.Level "-vf", "scale=$($compressionSettings.Resolution)" "-r", $compressionSettings.FrameRate "-c:a", "aac" "-b:a", $compressionSettings.AudioBitrate "-movflags", "+faststart" "-avoid_negative_ts", "make_zero" "-fflags", "+genpts" "-y" "`"$outputPath`"" ) } try { $startTime = Get-Date Write-Host "Executing: ffmpeg $($ffmpegArgs -join ' ')" -ForegroundColor Gray # Execute FFmpeg command & ffmpeg @ffmpegArgs $endTime = Get-Date $processingTime = ($endTime - $startTime).TotalSeconds if (Test-Path $outputPath) { $outputFileSize = [math]::Round((Get-Item $outputPath).Length / 1MB, 2) $compressionRatio = [math]::Round((1 - ($outputFileSize / $videoProps.FileSize)) * 100, 1) Write-Host "`nCompression completed successfully!" -ForegroundColor Green Write-Host "Processing time: $([math]::Round($processingTime, 1)) seconds" Write-Host "Original size: $($videoProps.FileSize) MB" Write-Host "Compressed size: $outputFileSize MB" Write-Host "Compression ratio: $compressionRatio%" Write-Host "Output location: $outputPath" # Open output directory $openDir = Read-Host "`nOpen output directory? (y/n)" if ($openDir -eq 'y' -or $openDir -eq 'Y') { Start-Process "explorer.exe" -ArgumentList $OutputDirectory } } else { Write-Host "Compression failed - output file not found." -ForegroundColor Red } } catch { Write-Host "Error during compression: $($_.Exception.Message)" -ForegroundColor Red } } # Export the main function (only when loaded as a module) if ($MyInvocation.MyCommand.Path -and $MyInvocation.MyCommand.Path.EndsWith('.psm1')) { Export-ModuleMember -Function Compress-Video } # Display information when script is loaded Write-Host "`nVideoCompressor loaded successfully!" -ForegroundColor Green Write-Host "Usage Examples:" -ForegroundColor Yellow Write-Host " Compress-Video `"video.mp4`" # Balanced mode (default)" -ForegroundColor White Write-Host " Compress-Video `"video.mp4`" -CompressionMode Fast # Fast processing" -ForegroundColor White Write-Host " Compress-Video `"video.mp4`" -CompressionMode Quality # Best quality" -ForegroundColor White Write-Host "Optimized for: OneDrive, YouTube, SharePoint, MS Stream" -ForegroundColor Cyan Write-Host "Hardware acceleration: Auto-detected (Intel QuickSync, NVIDIA NVENC)" -ForegroundColor Green -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 537 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,537 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 537 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,537 @@ # VideoCompressor - PowerShell Video Compression Tool # Optimized for cloud storage platforms (OneDrive, YouTube, SharePoint, etc.) function Test-FFmpegInstallation { <# .SYNOPSIS Checks if FFmpeg is available and installs it if not found #> # Check if ffmpeg is available in PATH $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue $ffprobeAvailable = Get-Command ffprobe -ErrorAction SilentlyContinue # If not found in PATH, check winget packages directory if (-not $ffmpegAvailable -or -not $ffprobeAvailable) { Write-Host "FFmpeg not found in PATH. Checking winget packages..." -ForegroundColor Yellow $wingetPath = "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" if (Test-Path $wingetPath) { # Look for FFmpeg packages $ffmpegDirs = @( "Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe", "BtbN.FFmpeg*", "*FFmpeg*" ) foreach ($pattern in $ffmpegDirs) { $packageDirs = Get-ChildItem -Path $wingetPath -Directory -Name $pattern -ErrorAction SilentlyContinue foreach ($packageDir in $packageDirs) { $fullPackagePath = Join-Path $wingetPath $packageDir # Look for bin directories recursively $binDirs = Get-ChildItem -Path $fullPackagePath -Recurse -Directory -Name "bin" -ErrorAction SilentlyContinue foreach ($binDir in $binDirs) { $binPath = Join-Path $fullPackagePath $binDir $ffmpegExe = Join-Path $binPath "ffmpeg.exe" $ffprobeExe = Join-Path $binPath "ffprobe.exe" if ((Test-Path $ffmpegExe) -and (Test-Path $ffprobeExe)) { Write-Host "Found FFmpeg installation at: $binPath" -ForegroundColor Green # Add to current session PATH if ($env:PATH -notlike "*$binPath*") { $env:PATH += ";$binPath" Write-Host "Added to current session PATH: $binPath" -ForegroundColor Green } # Ask user if they want to add to permanent PATH $addToPermanentPath = Read-Host "Add FFmpeg to permanent system PATH? (y/n)" if ($addToPermanentPath -eq 'y' -or $addToPermanentPath -eq 'Y') { try { # Get current user PATH $userPath = [System.Environment]::GetEnvironmentVariable("PATH", "User") if ($userPath -notlike "*$binPath*") { $newUserPath = "$userPath;$binPath" [System.Environment]::SetEnvironmentVariable("PATH", $newUserPath, "User") Write-Host "Added to permanent user PATH. Restart PowerShell for changes to take effect." -ForegroundColor Green } else { Write-Host "FFmpeg is already in permanent PATH." -ForegroundColor Yellow } } catch { Write-Host "Failed to update permanent PATH: $($_.Exception.Message)" -ForegroundColor Red } } # Verify the commands are now available $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue $ffprobeAvailable = Get-Command ffprobe -ErrorAction SilentlyContinue if ($ffmpegAvailable -and $ffprobeAvailable) { Write-Host "FFmpeg is now available!" -ForegroundColor Green return $true } } } } } } } if (-not $ffmpegAvailable -or -not $ffprobeAvailable) { Write-Host "FFmpeg is not recognized as an internal or external command." -ForegroundColor Red Write-Host "FFmpeg is required for video compression." -ForegroundColor Yellow Write-Host "" Write-Host "Available installation options via winget:" -ForegroundColor Cyan Write-Host "1. Gyan.FFmpeg (MSVC build - Best Windows compatibility)" -ForegroundColor Green Write-Host "2. BtbN.FFmpeg.GPL (MinGW build - Latest features)" -ForegroundColor Yellow Write-Host "" $install = Read-Host "Do you want to install FFmpeg now? (y/n)" if ($install -eq 'y' -or $install -eq 'Y') { Write-Host "Installing FFmpeg (Gyan.FFmpeg)..." -ForegroundColor Yellow try { winget install Gyan.FFmpeg --accept-package-agreements --accept-source-agreements # Refresh PATH in current session $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") # Verify installation Start-Sleep -Seconds 3 $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue if (-not $ffmpegAvailable) { Write-Host "Primary installation failed. Trying alternative package (BtbN.FFmpeg.GPL)..." -ForegroundColor Yellow winget install BtbN.FFmpeg.GPL --accept-package-agreements --accept-source-agreements # Refresh PATH again $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") Start-Sleep -Seconds 3 $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue } if ($ffmpegAvailable) { Write-Host "FFmpeg installed successfully!" -ForegroundColor Green Write-Host "You may need to restart PowerShell for PATH changes to take effect." -ForegroundColor Yellow return $true } else { Write-Host "FFmpeg installation failed. Please install manually or restart PowerShell." -ForegroundColor Red Write-Host "Manual installation: Download from https://ffmpeg.org/download.html" -ForegroundColor Yellow return $false } } catch { Write-Host "Error installing FFmpeg: $($_.Exception.Message)" -ForegroundColor Red Write-Host "Please try installing manually:" -ForegroundColor Yellow Write-Host " winget install Gyan.FFmpeg" -ForegroundColor Cyan Write-Host " or: winget install BtbN.FFmpeg.GPL" -ForegroundColor Cyan return $false } } else { Write-Host "FFmpeg installation cancelled. Cannot proceed without FFmpeg." -ForegroundColor Red return $false } } return $true } function Get-VideoProperties { <# .SYNOPSIS Uses ffprobe to analyze video properties for optimal compression #> param( [Parameter(Mandatory = $true)] [string]$VideoPath ) try { # Get video information using ffprobe $probeOutput = ffprobe -v quiet -print_format json -show_streams -show_format "$VideoPath" | ConvertFrom-Json $videoStream = $probeOutput.streams | Where-Object { $_.codec_type -eq "video" } | Select-Object -First 1 $audioStream = $probeOutput.streams | Where-Object { $_.codec_type -eq "audio" } | Select-Object -First 1 $properties = @{ Duration = [math]::Round([double]$probeOutput.format.duration, 2) Width = [int]$videoStream.width Height = [int]$videoStream.height FrameRate = if ($videoStream.r_frame_rate) { $fps = $videoStream.r_frame_rate.Split('/') [math]::Round([double]$fps[0] / [double]$fps[1], 2) } else { 30 } VideoBitrate = if ($videoStream.bit_rate) { [int]$videoStream.bit_rate } else { 0 } AudioBitrate = if ($audioStream.bit_rate) { [int]$audioStream.bit_rate } else { 128000 } VideoCodec = $videoStream.codec_name AudioCodec = if ($audioStream) { $audioStream.codec_name } else { "none" } FileSize = [math]::Round((Get-Item $VideoPath).Length / 1MB, 2) } return $properties } catch { Write-Host "Error analyzing video: $($_.Exception.Message)" -ForegroundColor Red return $null } } function Get-OptimalCompressionSettings { <# .SYNOPSIS Determines optimal compression settings based on video properties and target platform #> param( [Parameter(Mandatory = $true)] [hashtable]$VideoProperties, [Parameter(Mandatory = $false)] [string]$CompressionMode = "Balanced" ) $width = $VideoProperties.Width $height = $VideoProperties.Height $fps = $VideoProperties.FrameRate $duration = $VideoProperties.Duration # Determine target resolution (maintain aspect ratio) $targetWidth = $width $targetHeight = $height # Optimize for cloud storage - limit resolution for better streaming if ($width -gt 1920 -or $height -gt 1080) { # Scale down to 1080p max while maintaining aspect ratio $aspectRatio = $width / $height if ($aspectRatio -gt (16/9)) { $targetWidth = 1920 $targetHeight = [math]::Round(1920 / $aspectRatio / 2) * 2 # Even number } else { $targetHeight = 1080 $targetWidth = [math]::Round(1080 * $aspectRatio / 2) * 2 # Even number } } # Optimize frame rate $targetFps = $fps if ($fps -gt 60) { $targetFps = 60 } elseif ($fps -gt 30 -and $duration -gt 600) { $targetFps = 30 } # Long videos benefit from 30fps # Determine CRF based on content type and duration $crf = 23 # Default balanced quality if ($duration -lt 300) { $crf = 21 } # Short videos - higher quality elseif ($duration -gt 3600) { $crf = 25 } # Long videos - more compression # Audio bitrate optimization $audioBitrate = "128k" if ($VideoProperties.AudioBitrate -gt 0) { if ($VideoProperties.AudioBitrate -le 96000) { $audioBitrate = "96k" } elseif ($VideoProperties.AudioBitrate -ge 256000) { $audioBitrate = "192k" } } # Choose preset and CRF based on compression mode switch ($CompressionMode) { "Fast" { $preset = "fast" $crf = $crf + 2 # Slightly higher CRF for faster encoding } "Quality" { $preset = "slow" $crf = $crf - 1 # Lower CRF for better quality } default { # "Balanced" $preset = "medium" # Keep calculated CRF as is } } # Try to detect hardware acceleration capabilities (only if ffmpeg is available) $hwEncoder = $null $hwAvailable = $false if (Get-Command ffmpeg -ErrorAction SilentlyContinue) { # Check for Intel QuickSync (common on Intel CPUs like Core Ultra) try { $null = ffmpeg -hide_banner -f lavfi -i testsrc2=duration=1:size=320x240:rate=1 -c:v h264_qsv -f null - 2>$null if ($LASTEXITCODE -eq 0) { $hwEncoder = "h264_qsv" $hwAvailable = $true } } catch { } # Check for NVIDIA NVENC if QuickSync not available if (-not $hwAvailable) { try { $null = ffmpeg -hide_banner -f lavfi -i testsrc2=duration=1:size=320x240:rate=1 -c:v h264_nvenc -f null - 2>$null if ($LASTEXITCODE -eq 0) { $hwEncoder = "h264_nvenc" $hwAvailable = $true } } catch { } } } $settings = @{ Resolution = "${targetWidth}x${targetHeight}" FrameRate = $targetFps CRF = $crf AudioBitrate = $audioBitrate Preset = $preset Profile = "high" Level = "4.0" HardwareEncoder = $hwEncoder HardwareAvailable = $hwAvailable } return $settings } function Get-OutputDirectory { <# .SYNOPSIS Determines the best output directory (OneDrive or Videos folder) #> # Check if OneDrive is available and service is running $oneDriveAvailable = $false if ($env:OneDrive -and (Test-Path $env:OneDrive)) { # Check if OneDrive service is running $oneDriveService = Get-Process -Name "OneDrive" -ErrorAction SilentlyContinue if ($oneDriveService) { $oneDriveAvailable = $true $outputDir = Join-Path $env:OneDrive "CompressedVideos" } } if (-not $oneDriveAvailable) { # Fallback to Videos directory using .NET method try { $videosPath = [System.Environment]::GetFolderPath('MyVideos') $outputDir = Join-Path $videosPath "CompressedVideos" } catch { # Final fallback to user profile $outputDir = Join-Path $env:USERPROFILE "Videos\CompressedVideos" } } # Create directory if it doesn't exist if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null Write-Host "Created output directory: $outputDir" -ForegroundColor Green } return $outputDir } function Compress-Video { <# .SYNOPSIS Compresses video files with optimal settings for cloud storage platforms .DESCRIPTION This function compresses video files using FFmpeg with settings optimized for cloud storage platforms like OneDrive, YouTube, SharePoint, and MS Stream. .PARAMETER SourceVideo Path to the source video file to compress .PARAMETER OutputDirectory Optional custom output directory. If not specified, uses OneDrive or Videos folder .PARAMETER CompressionMode Choose compression speed/quality balance: Fast, Balanced, Quality - Fast: Quick processing, good quality (faster than real-time) - Balanced: Good balance of speed and compression (default) - Quality: Best compression, slower processing .EXAMPLE Compress-Video "C:\Videos\MyVideo.mp4" .EXAMPLE Compress-Video -SourceVideo ".\Local Development Environment Setup Guide.mp4" -CompressionMode Fast #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$SourceVideo, [Parameter(Mandatory = $false)] [string]$OutputDirectory, [Parameter(Mandatory = $false)] [ValidateSet("Fast", "Balanced", "Quality")] [string]$CompressionMode = "Balanced" ) # Check if FFmpeg is available if (-not (Test-FFmpegInstallation)) { return } # Validate source file if (-not (Test-Path $SourceVideo)) { Write-Host "Error: Source video file not found: $SourceVideo" -ForegroundColor Red return } Write-Host "Analyzing video properties..." -ForegroundColor Yellow $videoProps = Get-VideoProperties -VideoPath $SourceVideo if (-not $videoProps) { Write-Host "Failed to analyze video properties." -ForegroundColor Red return } # Display video information Write-Host "`nVideo Information:" -ForegroundColor Cyan Write-Host "Duration: $($videoProps.Duration) seconds" Write-Host "Resolution: $($videoProps.Width)x$($videoProps.Height)" Write-Host "Frame Rate: $($videoProps.FrameRate) fps" Write-Host "File Size: $($videoProps.FileSize) MB" Write-Host "Video Codec: $($videoProps.VideoCodec)" Write-Host "Audio Codec: $($videoProps.AudioCodec)" # Get optimal compression settings $compressionSettings = Get-OptimalCompressionSettings -VideoProperties $videoProps -CompressionMode $CompressionMode Write-Host "`nOptimal Compression Settings:" -ForegroundColor Cyan Write-Host "Compression Mode: $CompressionMode" Write-Host "Target Resolution: $($compressionSettings.Resolution)" Write-Host "Target Frame Rate: $($compressionSettings.FrameRate) fps" Write-Host "CRF Quality: $($compressionSettings.CRF)" Write-Host "Audio Bitrate: $($compressionSettings.AudioBitrate)" Write-Host "Preset: $($compressionSettings.Preset)" if ($compressionSettings.HardwareAvailable) { Write-Host "Hardware Encoder: $($compressionSettings.HardwareEncoder) (faster processing)" -ForegroundColor Green } else { Write-Host "Hardware Encoder: Software only (h264)" -ForegroundColor Yellow } # Determine output directory and file path if (-not $OutputDirectory) { $OutputDirectory = Get-OutputDirectory } $sourceFileName = [System.IO.Path]::GetFileNameWithoutExtension($SourceVideo) $outputFileName = "${sourceFileName}_compressed.mp4" $outputPath = Join-Path $OutputDirectory $outputFileName # Check if output file already exists if (Test-Path $outputPath) { $counter = 1 do { $outputFileName = "${sourceFileName}_compressed_${counter}.mp4" $outputPath = Join-Path $OutputDirectory $outputFileName $counter++ } while (Test-Path $outputPath) } Write-Host "`nStarting compression..." -ForegroundColor Green Write-Host "Output will be saved to: $outputPath" -ForegroundColor Yellow # Build FFmpeg command with optimal settings if ($compressionSettings.HardwareAvailable -and $CompressionMode -ne "Quality") { # Use hardware encoder for faster processing (except in Quality mode) $videoCodec = $compressionSettings.HardwareEncoder # Calculate target bitrate based on resolution and frame rate $pixelCount = ($compressionSettings.Resolution -split 'x')[0] * ($compressionSettings.Resolution -split 'x')[1] $targetBitrate = [math]::Round(($pixelCount * $compressionSettings.FrameRate * 0.1) / 1000) # Rough estimate if ($targetBitrate -lt 1000) { $targetBitrate = 1000 } if ($targetBitrate -gt 8000) { $targetBitrate = 8000 } $ffmpegArgs = @( "-i", "`"$SourceVideo`"" "-c:v", $videoCodec "-b:v", "${targetBitrate}k" "-maxrate", "$([math]::Round($targetBitrate * 1.5))k" "-bufsize", "$([math]::Round($targetBitrate * 2))k" "-vf", "scale=$($compressionSettings.Resolution)" "-r", $compressionSettings.FrameRate "-c:a", "aac" "-b:a", $compressionSettings.AudioBitrate "-movflags", "+faststart" "-avoid_negative_ts", "make_zero" "-fflags", "+genpts" "-y" "`"$outputPath`"" ) } else { # Use software encoder with CRF $ffmpegArgs = @( "-i", "`"$SourceVideo`"" "-c:v", "libx264" "-preset", $compressionSettings.Preset "-crf", $compressionSettings.CRF "-profile:v", $compressionSettings.Profile "-level", $compressionSettings.Level "-vf", "scale=$($compressionSettings.Resolution)" "-r", $compressionSettings.FrameRate "-c:a", "aac" "-b:a", $compressionSettings.AudioBitrate "-movflags", "+faststart" "-avoid_negative_ts", "make_zero" "-fflags", "+genpts" "-y" "`"$outputPath`"" ) } try { $startTime = Get-Date Write-Host "Executing: ffmpeg $($ffmpegArgs -join ' ')" -ForegroundColor Gray # Execute FFmpeg command & ffmpeg @ffmpegArgs $endTime = Get-Date $processingTime = ($endTime - $startTime).TotalSeconds if (Test-Path $outputPath) { $outputFileSize = [math]::Round((Get-Item $outputPath).Length / 1MB, 2) $compressionRatio = [math]::Round((1 - ($outputFileSize / $videoProps.FileSize)) * 100, 1) Write-Host "`nCompression completed successfully!" -ForegroundColor Green Write-Host "Processing time: $([math]::Round($processingTime, 1)) seconds" Write-Host "Original size: $($videoProps.FileSize) MB" Write-Host "Compressed size: $outputFileSize MB" Write-Host "Compression ratio: $compressionRatio%" Write-Host "Output location: $outputPath" # Open output directory $openDir = Read-Host "`nOpen output directory? (y/n)" if ($openDir -eq 'y' -or $openDir -eq 'Y') { Start-Process "explorer.exe" -ArgumentList $OutputDirectory } } else { Write-Host "Compression failed - output file not found." -ForegroundColor Red } } catch { Write-Host "Error during compression: $($_.Exception.Message)" -ForegroundColor Red } } # Export the main function (only when loaded as a module) if ($MyInvocation.MyCommand.Path -and $MyInvocation.MyCommand.Path.EndsWith('.psm1')) { Export-ModuleMember -Function Compress-Video } # Display information when script is loaded Write-Host "`nVideoCompressor loaded successfully!" -ForegroundColor Green Write-Host "Usage Examples:" -ForegroundColor Yellow Write-Host " Compress-Video `"video.mp4`" # Balanced mode (default)" -ForegroundColor White Write-Host " Compress-Video `"video.mp4`" -CompressionMode Fast # Fast processing" -ForegroundColor White Write-Host " Compress-Video `"video.mp4`" -CompressionMode Quality # Best quality" -ForegroundColor White Write-Host "Optimized for: OneDrive, YouTube, SharePoint, MS Stream" -ForegroundColor Cyan Write-Host "Hardware acceleration: Auto-detected (Intel QuickSync, NVIDIA NVENC)" -ForegroundColor Green -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 537 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,537 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 537 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,537 @@ # VideoCompressor - PowerShell Video Compression Tool # Optimized for cloud storage platforms (OneDrive, YouTube, SharePoint, etc.) function Test-FFmpegInstallation { <# .SYNOPSIS Checks if FFmpeg is available and installs it if not found #> # Check if ffmpeg is available in PATH $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue $ffprobeAvailable = Get-Command ffprobe -ErrorAction SilentlyContinue # If not found in PATH, check winget packages directory if (-not $ffmpegAvailable -or -not $ffprobeAvailable) { Write-Host "FFmpeg not found in PATH. Checking winget packages..." -ForegroundColor Yellow $wingetPath = "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" if (Test-Path $wingetPath) { # Look for FFmpeg packages $ffmpegDirs = @( "Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe", "BtbN.FFmpeg*", "*FFmpeg*" ) foreach ($pattern in $ffmpegDirs) { $packageDirs = Get-ChildItem -Path $wingetPath -Directory -Name $pattern -ErrorAction SilentlyContinue foreach ($packageDir in $packageDirs) { $fullPackagePath = Join-Path $wingetPath $packageDir # Look for bin directories recursively $binDirs = Get-ChildItem -Path $fullPackagePath -Recurse -Directory -Name "bin" -ErrorAction SilentlyContinue foreach ($binDir in $binDirs) { $binPath = Join-Path $fullPackagePath $binDir $ffmpegExe = Join-Path $binPath "ffmpeg.exe" $ffprobeExe = Join-Path $binPath "ffprobe.exe" if ((Test-Path $ffmpegExe) -and (Test-Path $ffprobeExe)) { Write-Host "Found FFmpeg installation at: $binPath" -ForegroundColor Green # Add to current session PATH if ($env:PATH -notlike "*$binPath*") { $env:PATH += ";$binPath" Write-Host "Added to current session PATH: $binPath" -ForegroundColor Green } # Ask user if they want to add to permanent PATH $addToPermanentPath = Read-Host "Add FFmpeg to permanent system PATH? (y/n)" if ($addToPermanentPath -eq 'y' -or $addToPermanentPath -eq 'Y') { try { # Get current user PATH $userPath = [System.Environment]::GetEnvironmentVariable("PATH", "User") if ($userPath -notlike "*$binPath*") { $newUserPath = "$userPath;$binPath" [System.Environment]::SetEnvironmentVariable("PATH", $newUserPath, "User") Write-Host "Added to permanent user PATH. Restart PowerShell for changes to take effect." -ForegroundColor Green } else { Write-Host "FFmpeg is already in permanent PATH." -ForegroundColor Yellow } } catch { Write-Host "Failed to update permanent PATH: $($_.Exception.Message)" -ForegroundColor Red } } # Verify the commands are now available $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue $ffprobeAvailable = Get-Command ffprobe -ErrorAction SilentlyContinue if ($ffmpegAvailable -and $ffprobeAvailable) { Write-Host "FFmpeg is now available!" -ForegroundColor Green return $true } } } } } } } if (-not $ffmpegAvailable -or -not $ffprobeAvailable) { Write-Host "FFmpeg is not recognized as an internal or external command." -ForegroundColor Red Write-Host "FFmpeg is required for video compression." -ForegroundColor Yellow Write-Host "" Write-Host "Available installation options via winget:" -ForegroundColor Cyan Write-Host "1. Gyan.FFmpeg (MSVC build - Best Windows compatibility)" -ForegroundColor Green Write-Host "2. BtbN.FFmpeg.GPL (MinGW build - Latest features)" -ForegroundColor Yellow Write-Host "" $install = Read-Host "Do you want to install FFmpeg now? (y/n)" if ($install -eq 'y' -or $install -eq 'Y') { Write-Host "Installing FFmpeg (Gyan.FFmpeg)..." -ForegroundColor Yellow try { winget install Gyan.FFmpeg --accept-package-agreements --accept-source-agreements # Refresh PATH in current session $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") # Verify installation Start-Sleep -Seconds 3 $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue if (-not $ffmpegAvailable) { Write-Host "Primary installation failed. Trying alternative package (BtbN.FFmpeg.GPL)..." -ForegroundColor Yellow winget install BtbN.FFmpeg.GPL --accept-package-agreements --accept-source-agreements # Refresh PATH again $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") Start-Sleep -Seconds 3 $ffmpegAvailable = Get-Command ffmpeg -ErrorAction SilentlyContinue } if ($ffmpegAvailable) { Write-Host "FFmpeg installed successfully!" -ForegroundColor Green Write-Host "You may need to restart PowerShell for PATH changes to take effect." -ForegroundColor Yellow return $true } else { Write-Host "FFmpeg installation failed. Please install manually or restart PowerShell." -ForegroundColor Red Write-Host "Manual installation: Download from https://ffmpeg.org/download.html" -ForegroundColor Yellow return $false } } catch { Write-Host "Error installing FFmpeg: $($_.Exception.Message)" -ForegroundColor Red Write-Host "Please try installing manually:" -ForegroundColor Yellow Write-Host " winget install Gyan.FFmpeg" -ForegroundColor Cyan Write-Host " or: winget install BtbN.FFmpeg.GPL" -ForegroundColor Cyan return $false } } else { Write-Host "FFmpeg installation cancelled. Cannot proceed without FFmpeg." -ForegroundColor Red return $false } } return $true } function Get-VideoProperties { <# .SYNOPSIS Uses ffprobe to analyze video properties for optimal compression #> param( [Parameter(Mandatory = $true)] [string]$VideoPath ) try { # Get video information using ffprobe $probeOutput = ffprobe -v quiet -print_format json -show_streams -show_format "$VideoPath" | ConvertFrom-Json $videoStream = $probeOutput.streams | Where-Object { $_.codec_type -eq "video" } | Select-Object -First 1 $audioStream = $probeOutput.streams | Where-Object { $_.codec_type -eq "audio" } | Select-Object -First 1 $properties = @{ Duration = [math]::Round([double]$probeOutput.format.duration, 2) Width = [int]$videoStream.width Height = [int]$videoStream.height FrameRate = if ($videoStream.r_frame_rate) { $fps = $videoStream.r_frame_rate.Split('/') [math]::Round([double]$fps[0] / [double]$fps[1], 2) } else { 30 } VideoBitrate = if ($videoStream.bit_rate) { [int]$videoStream.bit_rate } else { 0 } AudioBitrate = if ($audioStream.bit_rate) { [int]$audioStream.bit_rate } else { 128000 } VideoCodec = $videoStream.codec_name AudioCodec = if ($audioStream) { $audioStream.codec_name } else { "none" } FileSize = [math]::Round((Get-Item $VideoPath).Length / 1MB, 2) } return $properties } catch { Write-Host "Error analyzing video: $($_.Exception.Message)" -ForegroundColor Red return $null } } function Get-OptimalCompressionSettings { <# .SYNOPSIS Determines optimal compression settings based on video properties and target platform #> param( [Parameter(Mandatory = $true)] [hashtable]$VideoProperties, [Parameter(Mandatory = $false)] [string]$CompressionMode = "Balanced" ) $width = $VideoProperties.Width $height = $VideoProperties.Height $fps = $VideoProperties.FrameRate $duration = $VideoProperties.Duration # Determine target resolution (maintain aspect ratio) $targetWidth = $width $targetHeight = $height # Optimize for cloud storage - limit resolution for better streaming if ($width -gt 1920 -or $height -gt 1080) { # Scale down to 1080p max while maintaining aspect ratio $aspectRatio = $width / $height if ($aspectRatio -gt (16/9)) { $targetWidth = 1920 $targetHeight = [math]::Round(1920 / $aspectRatio / 2) * 2 # Even number } else { $targetHeight = 1080 $targetWidth = [math]::Round(1080 * $aspectRatio / 2) * 2 # Even number } } # Optimize frame rate $targetFps = $fps if ($fps -gt 60) { $targetFps = 60 } elseif ($fps -gt 30 -and $duration -gt 600) { $targetFps = 30 } # Long videos benefit from 30fps # Determine CRF based on content type and duration $crf = 23 # Default balanced quality if ($duration -lt 300) { $crf = 21 } # Short videos - higher quality elseif ($duration -gt 3600) { $crf = 25 } # Long videos - more compression # Audio bitrate optimization $audioBitrate = "128k" if ($VideoProperties.AudioBitrate -gt 0) { if ($VideoProperties.AudioBitrate -le 96000) { $audioBitrate = "96k" } elseif ($VideoProperties.AudioBitrate -ge 256000) { $audioBitrate = "192k" } } # Choose preset and CRF based on compression mode switch ($CompressionMode) { "Fast" { $preset = "fast" $crf = $crf + 2 # Slightly higher CRF for faster encoding } "Quality" { $preset = "slow" $crf = $crf - 1 # Lower CRF for better quality } default { # "Balanced" $preset = "medium" # Keep calculated CRF as is } } # Try to detect hardware acceleration capabilities (only if ffmpeg is available) $hwEncoder = $null $hwAvailable = $false if (Get-Command ffmpeg -ErrorAction SilentlyContinue) { # Check for Intel QuickSync (common on Intel CPUs like Core Ultra) try { $null = ffmpeg -hide_banner -f lavfi -i testsrc2=duration=1:size=320x240:rate=1 -c:v h264_qsv -f null - 2>$null if ($LASTEXITCODE -eq 0) { $hwEncoder = "h264_qsv" $hwAvailable = $true } } catch { } # Check for NVIDIA NVENC if QuickSync not available if (-not $hwAvailable) { try { $null = ffmpeg -hide_banner -f lavfi -i testsrc2=duration=1:size=320x240:rate=1 -c:v h264_nvenc -f null - 2>$null if ($LASTEXITCODE -eq 0) { $hwEncoder = "h264_nvenc" $hwAvailable = $true } } catch { } } } $settings = @{ Resolution = "${targetWidth}x${targetHeight}" FrameRate = $targetFps CRF = $crf AudioBitrate = $audioBitrate Preset = $preset Profile = "high" Level = "4.0" HardwareEncoder = $hwEncoder HardwareAvailable = $hwAvailable } return $settings } function Get-OutputDirectory { <# .SYNOPSIS Determines the best output directory (OneDrive or Videos folder) #> # Check if OneDrive is available and service is running $oneDriveAvailable = $false if ($env:OneDrive -and (Test-Path $env:OneDrive)) { # Check if OneDrive service is running $oneDriveService = Get-Process -Name "OneDrive" -ErrorAction SilentlyContinue if ($oneDriveService) { $oneDriveAvailable = $true $outputDir = Join-Path $env:OneDrive "CompressedVideos" } } if (-not $oneDriveAvailable) { # Fallback to Videos directory using .NET method try { $videosPath = [System.Environment]::GetFolderPath('MyVideos') $outputDir = Join-Path $videosPath "CompressedVideos" } catch { # Final fallback to user profile $outputDir = Join-Path $env:USERPROFILE "Videos\CompressedVideos" } } # Create directory if it doesn't exist if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null Write-Host "Created output directory: $outputDir" -ForegroundColor Green } return $outputDir } function Compress-Video { <# .SYNOPSIS Compresses video files with optimal settings for cloud storage platforms .DESCRIPTION This function compresses video files using FFmpeg with settings optimized for cloud storage platforms like OneDrive, YouTube, SharePoint, and MS Stream. .PARAMETER SourceVideo Path to the source video file to compress .PARAMETER OutputDirectory Optional custom output directory. If not specified, uses OneDrive or Videos folder .PARAMETER CompressionMode Choose compression speed/quality balance: Fast, Balanced, Quality - Fast: Quick processing, good quality (faster than real-time) - Balanced: Good balance of speed and compression (default) - Quality: Best compression, slower processing .EXAMPLE Compress-Video "C:\Videos\MyVideo.mp4" .EXAMPLE Compress-Video -SourceVideo ".\Local Development Environment Setup Guide.mp4" -CompressionMode Fast #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$SourceVideo, [Parameter(Mandatory = $false)] [string]$OutputDirectory, [Parameter(Mandatory = $false)] [ValidateSet("Fast", "Balanced", "Quality")] [string]$CompressionMode = "Balanced" ) # Check if FFmpeg is available if (-not (Test-FFmpegInstallation)) { return } # Validate source file if (-not (Test-Path $SourceVideo)) { Write-Host "Error: Source video file not found: $SourceVideo" -ForegroundColor Red return } Write-Host "Analyzing video properties..." -ForegroundColor Yellow $videoProps = Get-VideoProperties -VideoPath $SourceVideo if (-not $videoProps) { Write-Host "Failed to analyze video properties." -ForegroundColor Red return } # Display video information Write-Host "`nVideo Information:" -ForegroundColor Cyan Write-Host "Duration: $($videoProps.Duration) seconds" Write-Host "Resolution: $($videoProps.Width)x$($videoProps.Height)" Write-Host "Frame Rate: $($videoProps.FrameRate) fps" Write-Host "File Size: $($videoProps.FileSize) MB" Write-Host "Video Codec: $($videoProps.VideoCodec)" Write-Host "Audio Codec: $($videoProps.AudioCodec)" # Get optimal compression settings $compressionSettings = Get-OptimalCompressionSettings -VideoProperties $videoProps -CompressionMode $CompressionMode Write-Host "`nOptimal Compression Settings:" -ForegroundColor Cyan Write-Host "Compression Mode: $CompressionMode" Write-Host "Target Resolution: $($compressionSettings.Resolution)" Write-Host "Target Frame Rate: $($compressionSettings.FrameRate) fps" Write-Host "CRF Quality: $($compressionSettings.CRF)" Write-Host "Audio Bitrate: $($compressionSettings.AudioBitrate)" Write-Host "Preset: $($compressionSettings.Preset)" if ($compressionSettings.HardwareAvailable) { Write-Host "Hardware Encoder: $($compressionSettings.HardwareEncoder) (faster processing)" -ForegroundColor Green } else { Write-Host "Hardware Encoder: Software only (h264)" -ForegroundColor Yellow } # Determine output directory and file path if (-not $OutputDirectory) { $OutputDirectory = Get-OutputDirectory } $sourceFileName = [System.IO.Path]::GetFileNameWithoutExtension($SourceVideo) $outputFileName = "${sourceFileName}_compressed.mp4" $outputPath = Join-Path $OutputDirectory $outputFileName # Check if output file already exists if (Test-Path $outputPath) { $counter = 1 do { $outputFileName = "${sourceFileName}_compressed_${counter}.mp4" $outputPath = Join-Path $OutputDirectory $outputFileName $counter++ } while (Test-Path $outputPath) } Write-Host "`nStarting compression..." -ForegroundColor Green Write-Host "Output will be saved to: $outputPath" -ForegroundColor Yellow # Build FFmpeg command with optimal settings if ($compressionSettings.HardwareAvailable -and $CompressionMode -ne "Quality") { # Use hardware encoder for faster processing (except in Quality mode) $videoCodec = $compressionSettings.HardwareEncoder # Calculate target bitrate based on resolution and frame rate $pixelCount = ($compressionSettings.Resolution -split 'x')[0] * ($compressionSettings.Resolution -split 'x')[1] $targetBitrate = [math]::Round(($pixelCount * $compressionSettings.FrameRate * 0.1) / 1000) # Rough estimate if ($targetBitrate -lt 1000) { $targetBitrate = 1000 } if ($targetBitrate -gt 8000) { $targetBitrate = 8000 } $ffmpegArgs = @( "-i", "`"$SourceVideo`"" "-c:v", $videoCodec "-b:v", "${targetBitrate}k" "-maxrate", "$([math]::Round($targetBitrate * 1.5))k" "-bufsize", "$([math]::Round($targetBitrate * 2))k" "-vf", "scale=$($compressionSettings.Resolution)" "-r", $compressionSettings.FrameRate "-c:a", "aac" "-b:a", $compressionSettings.AudioBitrate "-movflags", "+faststart" "-avoid_negative_ts", "make_zero" "-fflags", "+genpts" "-y" "`"$outputPath`"" ) } else { # Use software encoder with CRF $ffmpegArgs = @( "-i", "`"$SourceVideo`"" "-c:v", "libx264" "-preset", $compressionSettings.Preset "-crf", $compressionSettings.CRF "-profile:v", $compressionSettings.Profile "-level", $compressionSettings.Level "-vf", "scale=$($compressionSettings.Resolution)" "-r", $compressionSettings.FrameRate "-c:a", "aac" "-b:a", $compressionSettings.AudioBitrate "-movflags", "+faststart" "-avoid_negative_ts", "make_zero" "-fflags", "+genpts" "-y" "`"$outputPath`"" ) } try { $startTime = Get-Date Write-Host "Executing: ffmpeg $($ffmpegArgs -join ' ')" -ForegroundColor Gray # Execute FFmpeg command & ffmpeg @ffmpegArgs $endTime = Get-Date $processingTime = ($endTime - $startTime).TotalSeconds if (Test-Path $outputPath) { $outputFileSize = [math]::Round((Get-Item $outputPath).Length / 1MB, 2) $compressionRatio = [math]::Round((1 - ($outputFileSize / $videoProps.FileSize)) * 100, 1) Write-Host "`nCompression completed successfully!" -ForegroundColor Green Write-Host "Processing time: $([math]::Round($processingTime, 1)) seconds" Write-Host "Original size: $($videoProps.FileSize) MB" Write-Host "Compressed size: $outputFileSize MB" Write-Host "Compression ratio: $compressionRatio%" Write-Host "Output location: $outputPath" # Open output directory $openDir = Read-Host "`nOpen output directory? (y/n)" if ($openDir -eq 'y' -or $openDir -eq 'Y') { Start-Process "explorer.exe" -ArgumentList $OutputDirectory } } else { Write-Host "Compression failed - output file not found." -ForegroundColor Red } } catch { Write-Host "Error during compression: $($_.Exception.Message)" -ForegroundColor Red } } # Export the main function (only when loaded as a module) if ($MyInvocation.MyCommand.Path -and $MyInvocation.MyCommand.Path.EndsWith('.psm1')) { Export-ModuleMember -Function Compress-Video } # Display information when script is loaded Write-Host "`nVideoCompressor loaded successfully!" -ForegroundColor Green Write-Host "Usage Examples:" -ForegroundColor Yellow Write-Host " Compress-Video `"video.mp4`" # Balanced mode (default)" -ForegroundColor White Write-Host " Compress-Video `"video.mp4`" -CompressionMode Fast # Fast processing" -ForegroundColor White Write-Host " Compress-Video `"video.mp4`" -CompressionMode Quality # Best quality" -ForegroundColor White Write-Host "Optimized for: OneDrive, YouTube, SharePoint, MS Stream" -ForegroundColor Cyan Write-Host "Hardware acceleration: Auto-detected (Intel QuickSync, NVIDIA NVENC)" -ForegroundColor Green -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 537 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,537 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 135 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,135 @@ # VideoCompressor - Installation & Usage Guide 🎬 **GitHub Gist**: https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879 ## 🚀 TLDR - One-Line Install **Copy and paste this command in PowerShell:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& { $d = Split-Path $PROFILE -Parent; if (!(Test-Path $d)) { md $d -Force }; $u = 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'; $f = Join-Path $d 'VideoCompressor.ps1'; iwr $u -OutFile $f -UseBasicParsing; if (!(Select-String 'VideoCompressor.ps1' $PROFILE -Quiet 2>$null)) { Add-Content $PROFILE \"`n. '$f'\" -Encoding UTF8 }; Write-Host '✅ VideoCompressor installed! Restart PowerShell and use: Compress-Video `"video.mp4`\"' -ForegroundColor Green }" ``` **Then restart PowerShell and use:** `Compress-Video "video.mp4"` --- ## 📋 Detailed Installation Options ### Option 1: Install to PowerShell Profile (Recommended) **One-time setup for permanent availability:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& { $profileDir = Split-Path $PROFILE -Parent if (-not (Test-Path $profileDir)) { New-Item -ItemType Directory -Path $profileDir -Force } $scriptUrl = 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1' $localPath = Join-Path $profileDir 'VideoCompressor.ps1' try { Invoke-WebRequest -Uri $scriptUrl -OutFile $localPath -UseBasicParsing Write-Host 'VideoCompressor downloaded successfully!' -ForegroundColor Green $profileContent = if (Test-Path $PROFILE) { Get-Content $PROFILE -Raw } else { '' } $dotSourceLine = '. `"$localPath`"' if ($profileContent -notlike "*VideoCompressor.ps1*") { Add-Content -Path $PROFILE -Value "`n# VideoCompressor Auto-Load`n$dotSourceLine" -Encoding UTF8 Write-Host 'Added to PowerShell profile. Restart PowerShell or run: . $PROFILE' -ForegroundColor Yellow } else { Write-Host 'VideoCompressor already in profile!' -ForegroundColor Yellow } Write-Host 'Installation complete! Usage: Compress-Video `"video.mp4`"' -ForegroundColor Green } catch { Write-Error "Failed to download: $_" } }" ``` After installation, just use: `Compress-Video "your-video.mp4"` ### Option 2: Run Directly from Gist (No Installation) **Basic usage:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))); Compress-Video 'video.mp4'" ``` **With compression mode:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))); Compress-Video -SourceVideo 'video.mp4' -CompressionMode Fast" ``` **Advanced with parameters:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command " $params = @{ SourceVideo = 'C:\Users\$env:USERNAME\Downloads\video.mp4' CompressionMode = 'Quality' OutputDirectory = 'C:\Users\$env:USERNAME\OneDrive\CompressedVideos' } & ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))) Compress-Video @params " ``` ## 🎯 Compression Modes | Mode | Speed | Quality | Best For | |------|-------|---------|----------| | `Fast` | ⚡⚡⚡ | ⭐⭐⭐ | Large batches, quick processing | | `Balanced` | ⚡⚡ | ⭐⭐⭐⭐ | **Default** - Best balance | | `Quality` | ⚡ | ⭐⭐⭐⭐⭐ | Archival, best compression | ## ⚡ Key Features - **Auto FFmpeg Install**: Installs FFmpeg via winget if missing - **Hardware Acceleration**: Intel QuickSync, NVIDIA NVENC support - **Cloud Optimized**: Perfect for OneDrive, YouTube, SharePoint - **Smart Scaling**: Auto-scales >1080p videos maintaining aspect ratio - **Batch Processing**: Easy to process multiple files ## 💡 Quick Examples ```powershell # Default balanced compression Compress-Video "MyVideo.mp4" # Fast mode for quick processing Compress-Video "MyVideo.mp4" -CompressionMode Fast # Best quality compression Compress-Video "MyVideo.mp4" -CompressionMode Quality # Custom output location Compress-Video "MyVideo.mp4" -OutputDirectory "C:\MyCompressed" # Batch process all MP4 files Get-ChildItem "*.mp4" | ForEach-Object { Compress-Video $_.Name } ``` ## 🛠️ Requirements - Windows 10/11 + PowerShell 5.1+ - FFmpeg (auto-installed if missing) - Internet connection (for FFmpeg download) ## 📊 Typical Results - **File size reduction**: 60-80% smaller - **Quality**: Visually lossless for most content - **Compatibility**: Works with all major platforms - **Speed**: Hardware acceleration when available Perfect for sharing large recordings, uploading to cloud storage, or preparing videos for web streaming! 🎬 ## 🔧 How the One-Liner Works The TLDR command installs VideoCompressor by: 1. **Creates profile directory** if it doesn't exist 2. **Downloads script** to `$(Split-Path $PROFILE -Parent)\VideoCompressor.ps1` 3. **Updates $PROFILE** to auto-load the script (if not already present) 4. **Ready to use** after restarting PowerShell -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 135 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,135 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 135 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,135 @@ # VideoCompressor - Installation & Usage Guide 🎬 **GitHub Gist**: https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879 ## 🚀 TLDR - One-Line Install **Copy and paste this command in PowerShell:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& { $d = Split-Path $PROFILE -Parent; if (!(Test-Path $d)) { md $d -Force }; $u = 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'; $f = Join-Path $d 'VideoCompressor.ps1'; iwr $u -OutFile $f -UseBasicParsing; if (!(Select-String 'VideoCompressor.ps1' $PROFILE -Quiet 2>$null)) { Add-Content $PROFILE \"`n. '$f'\" -Encoding UTF8 }; Write-Host '✅ VideoCompressor installed! Restart PowerShell and use: Compress-Video `"video.mp4`\"' -ForegroundColor Green }" ``` **Then restart PowerShell and use:** `Compress-Video "video.mp4"` --- ## 📋 Detailed Installation Options ### Option 1: Install to PowerShell Profile (Recommended) **One-time setup for permanent availability:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& { $profileDir = Split-Path $PROFILE -Parent if (-not (Test-Path $profileDir)) { New-Item -ItemType Directory -Path $profileDir -Force } $scriptUrl = 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1' $localPath = Join-Path $profileDir 'VideoCompressor.ps1' try { Invoke-WebRequest -Uri $scriptUrl -OutFile $localPath -UseBasicParsing Write-Host 'VideoCompressor downloaded successfully!' -ForegroundColor Green $profileContent = if (Test-Path $PROFILE) { Get-Content $PROFILE -Raw } else { '' } $dotSourceLine = '. `"$localPath`"' if ($profileContent -notlike "*VideoCompressor.ps1*") { Add-Content -Path $PROFILE -Value "`n# VideoCompressor Auto-Load`n$dotSourceLine" -Encoding UTF8 Write-Host 'Added to PowerShell profile. Restart PowerShell or run: . $PROFILE' -ForegroundColor Yellow } else { Write-Host 'VideoCompressor already in profile!' -ForegroundColor Yellow } Write-Host 'Installation complete! Usage: Compress-Video `"video.mp4`"' -ForegroundColor Green } catch { Write-Error "Failed to download: $_" } }" ``` After installation, just use: `Compress-Video "your-video.mp4"` ### Option 2: Run Directly from Gist (No Installation) **Basic usage:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))); Compress-Video 'video.mp4'" ``` **With compression mode:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))); Compress-Video -SourceVideo 'video.mp4' -CompressionMode Fast" ``` **Advanced with parameters:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command " $params = @{ SourceVideo = 'C:\Users\$env:USERNAME\Downloads\video.mp4' CompressionMode = 'Quality' OutputDirectory = 'C:\Users\$env:USERNAME\OneDrive\CompressedVideos' } & ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))) Compress-Video @params " ``` ## 🎯 Compression Modes | Mode | Speed | Quality | Best For | |------|-------|---------|----------| | `Fast` | ⚡⚡⚡ | ⭐⭐⭐ | Large batches, quick processing | | `Balanced` | ⚡⚡ | ⭐⭐⭐⭐ | **Default** - Best balance | | `Quality` | ⚡ | ⭐⭐⭐⭐⭐ | Archival, best compression | ## ⚡ Key Features - **Auto FFmpeg Install**: Installs FFmpeg via winget if missing - **Hardware Acceleration**: Intel QuickSync, NVIDIA NVENC support - **Cloud Optimized**: Perfect for OneDrive, YouTube, SharePoint - **Smart Scaling**: Auto-scales >1080p videos maintaining aspect ratio - **Batch Processing**: Easy to process multiple files ## 💡 Quick Examples ```powershell # Default balanced compression Compress-Video "MyVideo.mp4" # Fast mode for quick processing Compress-Video "MyVideo.mp4" -CompressionMode Fast # Best quality compression Compress-Video "MyVideo.mp4" -CompressionMode Quality # Custom output location Compress-Video "MyVideo.mp4" -OutputDirectory "C:\MyCompressed" # Batch process all MP4 files Get-ChildItem "*.mp4" | ForEach-Object { Compress-Video $_.Name } ``` ## 🛠️ Requirements - Windows 10/11 + PowerShell 5.1+ - FFmpeg (auto-installed if missing) - Internet connection (for FFmpeg download) ## 📊 Typical Results - **File size reduction**: 60-80% smaller - **Quality**: Visually lossless for most content - **Compatibility**: Works with all major platforms - **Speed**: Hardware acceleration when available Perfect for sharing large recordings, uploading to cloud storage, or preparing videos for web streaming! 🎬 ## 🔧 How the One-Liner Works The TLDR command installs VideoCompressor by: 1. **Creates profile directory** if it doesn't exist 2. **Downloads script** to `$(Split-Path $PROFILE -Parent)\VideoCompressor.ps1` 3. **Updates $PROFILE** to auto-load the script (if not already present) 4. **Ready to use** after restarting PowerShell -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 112 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,112 @@ # VideoCompressor - Quick Start Guide **🎬 GitHub Gist**: https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879 ## 🚀 TLDR - One-Line Install to PowerShell Profile **Copy, paste, and run this single command in PowerShell:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& { $d = Split-Path $PROFILE -Parent; if (!(Test-Path $d)) { md $d -Force }; $u = 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'; $f = Join-Path $d 'VideoCompressor.ps1'; iwr $u -OutFile $f -UseBasicParsing; if (!(Select-String 'VideoCompressor.ps1' $PROFILE -Quiet 2>$null)) { Add-Content $PROFILE \"`n. '$f'\" -Encoding UTF8 }; Write-Host '✅ VideoCompressor installed! Restart PowerShell and use: Compress-Video `"video.mp4`\"' -ForegroundColor Green }" ``` **That's it!** Restart PowerShell and use: `Compress-Video "video.mp4"` --- ## 📋 Detailed Installation Options ### Option 1: Install to PowerShell Profile (Recommended) **Standard installation command:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& { $profileDir = Split-Path `$PROFILE -Parent if (-not (Test-Path `$profileDir)) { New-Item -ItemType Directory -Path `$profileDir -Force } `$scriptUrl = 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1' `$localPath = Join-Path `$profileDir 'VideoCompressor.ps1' Invoke-WebRequest -Uri `$scriptUrl -OutFile `$localPath -UseBasicParsing Add-Content -Path `$PROFILE -Value `"`n. ```"`$localPath```"`" -Encoding UTF8 Write-Host 'VideoCompressor installed!' -ForegroundColor Green }" ``` After installation, restart PowerShell and use: `Compress-Video "video.mp4"` ### Option 2: Direct Execution (No Installation) **Run directly from gist without installing:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))); Compress-Video 'your-video.mp4'" ``` ### Option 3: Advanced with Parameters ```powershell powershell.exe -ExecutionPolicy Bypass -Command " $params = @{ SourceVideo = 'C:\Users\$env:USERNAME\Downloads\video.mp4' CompressionMode = 'Quality' OutputDirectory = 'C:\Users\$env:USERNAME\OneDrive\CompressedVideos' } & ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))) Compress-Video @params " ``` ## ⚡ Quick Examples ```powershell # Basic compression (balanced mode) Compress-Video "MyVideo.mp4" # Fast processing Compress-Video "MyVideo.mp4" -CompressionMode Fast # Best quality Compress-Video "MyVideo.mp4" -CompressionMode Quality # Custom output folder Compress-Video "MyVideo.mp4" -OutputDirectory "C:\Compressed" ``` ## 🎯 What It Does - ✅ **Auto-installs FFmpeg** if not found - ✅ **Hardware acceleration** (Intel/NVIDIA) - ✅ **Reduces file size by 60-80%** - ✅ **Maintains visual quality** - ✅ **Optimized for cloud storage** - ✅ **Works with all video formats** ## 📋 Requirements - Windows 10/11 - PowerShell 5.1+ - Internet connection (for FFmpeg auto-install) ## 🛠️ Profile Installation Details The one-liner installs VideoCompressor to your PowerShell profile by: 1. **Script Location**: `$(Split-Path $PROFILE -Parent)\VideoCompressor.ps1` 2. **Profile Entry**: Adds `. 'path\to\VideoCompressor.ps1'` to your `$PROFILE` 3. **Auto-Loading**: Script loads automatically when PowerShell starts **Profile Path Examples:** - `C:\Users\YourName\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1` - `C:\Users\YourName\Documents\PowerShell\Microsoft.PowerShell_profile.ps1` (PowerShell 7+) ## 🔧 For Developers 1. **Clone this gist**: `git clone https://gist.github.com/868fbc801667e65e334679fec62b6879.git` 2. **Install locally**: Run `.\Install-VideoCompressor.ps1` 3. **Customize**: Edit `VideoCompressor.ps1` as needed --- Perfect for preparing videos for **OneDrive**, **YouTube**, **SharePoint**, or any cloud platform! 🎬 -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 64 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,64 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 64 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,64 @@ # VideoCompressor - Quick Start Guide ## 🚀 Installation Options ### Option 1: One-Click Install to Profile (Recommended) **Copy and paste this command into PowerShell:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "iex (irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1')" ``` After installation, restart PowerShell and use: `Compress-Video "video.mp4"` ### Option 2: Direct Execution (No Installation) **Compress any video file directly:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))); Compress-Video 'your-video.mp4'" ``` **Replace `YOUR_GIST_ID` with your actual gist ID** ## ⚡ Quick Examples ```powershell # Basic compression (balanced mode) Compress-Video "MyVideo.mp4" # Fast processing Compress-Video "MyVideo.mp4" -CompressionMode Fast # Best quality Compress-Video "MyVideo.mp4" -CompressionMode Quality # Custom output folder Compress-Video "MyVideo.mp4" -OutputDirectory "C:\Compressed" ``` ## 🎯 What It Does - ✅ **Auto-installs FFmpeg** if not found - ✅ **Hardware acceleration** (Intel/NVIDIA) - ✅ **Reduces file size by 60-80%** - ✅ **Maintains visual quality** - ✅ **Optimized for cloud storage** - ✅ **Works with all video formats** ## 📋 Requirements - Windows 10/11 - PowerShell 5.1+ - Internet connection (for FFmpeg auto-install) ## 🛠️ For Developers 1. **Create your own gist**: Run `.\Create-Gist.ps1` 2. **Install locally**: Run `.\Install-VideoCompressor.ps1` 3. **Customize**: Edit `VideoCompressor.ps1` as needed --- Perfect for preparing videos for **OneDrive**, **YouTube**, **SharePoint**, or any cloud platform! 🎬 -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 64 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,64 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 64 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,64 @@ # VideoCompressor - Quick Start Guide ## 🚀 Installation Options ### Option 1: One-Click Install to Profile (Recommended) **Copy and paste this command into PowerShell:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "iex (irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1')" ``` After installation, restart PowerShell and use: `Compress-Video "video.mp4"` ### Option 2: Direct Execution (No Installation) **Compress any video file directly:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))); Compress-Video 'your-video.mp4'" ``` **Replace `YOUR_GIST_ID` with your actual gist ID** ## ⚡ Quick Examples ```powershell # Basic compression (balanced mode) Compress-Video "MyVideo.mp4" # Fast processing Compress-Video "MyVideo.mp4" -CompressionMode Fast # Best quality Compress-Video "MyVideo.mp4" -CompressionMode Quality # Custom output folder Compress-Video "MyVideo.mp4" -OutputDirectory "C:\Compressed" ``` ## 🎯 What It Does - ✅ **Auto-installs FFmpeg** if not found - ✅ **Hardware acceleration** (Intel/NVIDIA) - ✅ **Reduces file size by 60-80%** - ✅ **Maintains visual quality** - ✅ **Optimized for cloud storage** - ✅ **Works with all video formats** ## 📋 Requirements - Windows 10/11 - PowerShell 5.1+ - Internet connection (for FFmpeg auto-install) ## 🛠️ For Developers 1. **Create your own gist**: Run `.\Create-Gist.ps1` 2. **Install locally**: Run `.\Install-VideoCompressor.ps1` 3. **Customize**: Edit `VideoCompressor.ps1` as needed --- Perfect for preparing videos for **OneDrive**, **YouTube**, **SharePoint**, or any cloud platform! 🎬 -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 117 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,117 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 64 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,64 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 64 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,64 @@ # VideoCompressor - Quick Start Guide ## 🚀 Installation Options ### Option 1: One-Click Install to Profile (Recommended) **Copy and paste this command into PowerShell:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "iex (irm 'https://raw.githubusercontent.com/emilwojcik93/VideoCompressor-PowerShell/main/Install-VideoCompressor.ps1')" ``` After installation, restart PowerShell and use: `Compress-Video "video.mp4"` ### Option 2: Direct Execution (No Installation) **Compress any video file directly:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/YOUR_GIST_ID/raw/VideoCompressor.ps1'))); Compress-Video 'your-video.mp4'" ``` **Replace `YOUR_GIST_ID` with your actual gist ID** ## ⚡ Quick Examples ```powershell # Basic compression (balanced mode) Compress-Video "MyVideo.mp4" # Fast processing Compress-Video "MyVideo.mp4" -CompressionMode Fast # Best quality Compress-Video "MyVideo.mp4" -CompressionMode Quality # Custom output folder Compress-Video "MyVideo.mp4" -OutputDirectory "C:\Compressed" ``` ## 🎯 What It Does - ✅ **Auto-installs FFmpeg** if not found - ✅ **Hardware acceleration** (Intel/NVIDIA) - ✅ **Reduces file size by 60-80%** - ✅ **Maintains visual quality** - ✅ **Optimized for cloud storage** - ✅ **Works with all video formats** ## 📋 Requirements - Windows 10/11 - PowerShell 5.1+ - Internet connection (for FFmpeg auto-install) ## 🛠️ For Developers 1. **Create your own gist**: Run `.\Create-Gist.ps1` 2. **Install locally**: Run `.\Install-VideoCompressor.ps1` 3. **Customize**: Edit `VideoCompressor.ps1` as needed --- Perfect for preparing videos for **OneDrive**, **YouTube**, **SharePoint**, or any cloud platform! 🎬 -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 64 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,64 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 117 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,117 @@ # VideoCompressor - Installation & Usage Guide ## 🚀 Quick Start Options ### Option 1: Install to PowerShell Profile (Recommended) **One-time setup for permanent availability:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& { $profileDir = Split-Path $PROFILE -Parent if (-not (Test-Path $profileDir)) { New-Item -ItemType Directory -Path $profileDir -Force } $scriptUrl = 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1' $localPath = Join-Path $profileDir 'VideoCompressor.ps1' try { Invoke-WebRequest -Uri $scriptUrl -OutFile $localPath -UseBasicParsing Write-Host 'VideoCompressor downloaded successfully!' -ForegroundColor Green $profileContent = if (Test-Path $PROFILE) { Get-Content $PROFILE -Raw } else { '' } $dotSourceLine = '. `"$localPath`"' if ($profileContent -notlike "*VideoCompressor.ps1*") { Add-Content -Path $PROFILE -Value "`n# VideoCompressor Auto-Load`n$dotSourceLine" -Encoding UTF8 Write-Host 'Added to PowerShell profile. Restart PowerShell or run: . $PROFILE' -ForegroundColor Yellow } else { Write-Host 'VideoCompressor already in profile!' -ForegroundColor Yellow } Write-Host 'Installation complete! Usage: Compress-Video `"video.mp4`"' -ForegroundColor Green } catch { Write-Error "Failed to download: $_" } }" ``` After installation, just use: `Compress-Video "your-video.mp4"` ### Option 2: Run Directly from Gist (No Installation) **Basic usage:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))); Compress-Video 'video.mp4'" ``` **With compression mode:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))); Compress-Video -SourceVideo 'video.mp4' -CompressionMode Fast" ``` **Advanced with parameters:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command " $params = @{ SourceVideo = 'C:\Users\$env:USERNAME\Downloads\video.mp4' CompressionMode = 'Quality' OutputDirectory = 'C:\Users\$env:USERNAME\OneDrive\CompressedVideos' } & ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1'))) Compress-Video @params " ``` ## 🎯 Compression Modes | Mode | Speed | Quality | Best For | |------|-------|---------|----------| | `Fast` | ⚡⚡⚡ | ⭐⭐⭐ | Large batches, quick processing | | `Balanced` | ⚡⚡ | ⭐⭐⭐⭐ | **Default** - Best balance | | `Quality` | ⚡ | ⭐⭐⭐⭐⭐ | Archival, best compression | ## ⚡ Key Features - **Auto FFmpeg Install**: Installs FFmpeg via winget if missing - **Hardware Acceleration**: Intel QuickSync, NVIDIA NVENC support - **Cloud Optimized**: Perfect for OneDrive, YouTube, SharePoint - **Smart Scaling**: Auto-scales >1080p videos maintaining aspect ratio - **Batch Processing**: Easy to process multiple files ## 💡 Quick Examples ```powershell # Default balanced compression Compress-Video "MyVideo.mp4" # Fast mode for quick processing Compress-Video "MyVideo.mp4" -CompressionMode Fast # Best quality compression Compress-Video "MyVideo.mp4" -CompressionMode Quality # Custom output location Compress-Video "MyVideo.mp4" -OutputDirectory "C:\MyCompressed" # Batch process all MP4 files Get-ChildItem "*.mp4" | ForEach-Object { Compress-Video $_.Name } ``` ## 🛠️ Requirements - Windows 10/11 + PowerShell 5.1+ - FFmpeg (auto-installed if missing) - Internet connection (for FFmpeg download) ## 📊 Typical Results - **File size reduction**: 60-80% smaller - **Quality**: Visually lossless for most content - **Compatibility**: Works with all major platforms - **Speed**: Hardware acceleration when available Perfect for sharing large recordings, uploading to cloud storage, or preparing videos for web streaming! 🎬 --- **Note**: Replace the gist URL with your actual gist URL when creating your own version. -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 64 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,64 @@ # VideoCompressor - Quick Start Guide ## 🚀 Installation Options ### Option 1: One-Click Install to Profile (Recommended) **Copy and paste this command into PowerShell:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "iex (irm 'https://raw.githubusercontent.com/emilwojcik93/VideoCompressor-PowerShell/main/Install-VideoCompressor.ps1')" ``` After installation, restart PowerShell and use: `Compress-Video "video.mp4"` ### Option 2: Direct Execution (No Installation) **Compress any video file directly:** ```powershell powershell.exe -ExecutionPolicy Bypass -Command "& ([ScriptBlock]::Create((irm 'https://gist.github.com/emilwojcik93/YOUR_GIST_ID/raw/VideoCompressor.ps1'))); Compress-Video 'your-video.mp4'" ``` **Replace `YOUR_GIST_ID` with your actual gist ID** ## ⚡ Quick Examples ```powershell # Basic compression (balanced mode) Compress-Video "MyVideo.mp4" # Fast processing Compress-Video "MyVideo.mp4" -CompressionMode Fast # Best quality Compress-Video "MyVideo.mp4" -CompressionMode Quality # Custom output folder Compress-Video "MyVideo.mp4" -OutputDirectory "C:\Compressed" ``` ## 🎯 What It Does - ✅ **Auto-installs FFmpeg** if not found - ✅ **Hardware acceleration** (Intel/NVIDIA) - ✅ **Reduces file size by 60-80%** - ✅ **Maintains visual quality** - ✅ **Optimized for cloud storage** - ✅ **Works with all video formats** ## 📋 Requirements - Windows 10/11 - PowerShell 5.1+ - Internet connection (for FFmpeg auto-install) ## 🛠️ For Developers 1. **Create your own gist**: Run `.\Create-Gist.ps1` 2. **Install locally**: Run `.\Install-VideoCompressor.ps1` 3. **Customize**: Edit `VideoCompressor.ps1` as needed --- Perfect for preparing videos for **OneDrive**, **YouTube**, **SharePoint**, or any cloud platform! 🎬 -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 64 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,64 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 0 additions and 108 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,108 +0,0 @@ -
emilwojcik93 revised this gist
Sep 15, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -64,7 +64,7 @@ try { Write-Host "" # Show usage examples with the actual gist URL $rawUrl = "https://gist.github.com/emilwojcik93/868fbc801667e65e334679fec62b6879/raw/VideoCompressor.ps1" Write-Host "Usage Examples:" -ForegroundColor Cyan Write-Host "" -
emilwojcik93 revised this gist
Sep 15, 2025 . No changes.There are no files selected for viewing
-
emilwojcik93 revised this gist
Sep 15, 2025 . No changes.There are no files selected for viewing
-
emilwojcik93 revised this gist
Sep 15, 2025 . No changes.There are no files selected for viewing
NewerOlder