ffmpeg is a powerful tool to process video and audio files. Let's create a cheat sheet of the commands I use from time to time!
#Remove audio from a video
Shell
ffmpeg -i input.mp4 -an -c:v copy output.mp4
-i input.mp4: Input file-an: Remove audio stream-c:v copy: Copy the video stream without re-encoding
#Prepare a video for streaming
Remove metadata and move the moov atom to the beginning of the file for faster playback start.
Shell
ffmpeg -i input.mp4 -map_metadata -1 -movflags faststart output.mp4
-i input.mp4: Input file-map_metadata -1: Remove all metadata-movflags faststart: Move the moov atom to the beginning of the file
#Encode a video by chunks
PowerShell
# Split the video into 10-minute chunks and remove audio
ffmpeg -i input.mp4 -c copy -an -map 0 -segment_time 600 -f segment chunk%03d.mp4
foreach ($file in Get-ChildItem -Filter "chunk*.mp4") {
# Encode each chunk
ffmpeg -i $file.FullName -c:v libx265 -preset medium -c:a aac -b:a 128k converted$($file.BaseName).mp4
}
# Concatenate the chunks into a single video
foreach($file in Get-ChildItem -Filter "converted*.mp4") {
"file '$($file.FullName)'" | Out-File -Append -Encoding utf8 concat.txt
}
ffmpeg -f concat -safe 1 -i concat.txt -c copy concat.mp4
# Merge video and audio
ffmpeg -i concat.mp4 -i input.mp4 -c copy -map 0:v:0 -map 1:a:0 converted.mp4
# Remove temporary files
Remove-Item concat.txt
Remove-Item chunk*.mp4
Remove-Item converted*.mp4
-segment_time 600: Split the video into chunks of 600 seconds (10 minutes)-f segment: Use the segment muxer to split the video-c:v libx265: Encode the video using the H.265 codec-preset medium: Use the medium preset for encoding (balance between speed and compression)-c:a aac: Encode the audio using the AAC codec-b:a 128k: Set the audio bitrate to 128 kbps-f concat: Use the concat demuxer to merge the chunks-safe 1: Prevent the use of unsafe file paths in the concat file-map 0:v:0: Select the first video stream from the first input file-map 1:a:0: Select the first audio stream from the second input file
#Merge video and subtitles
Shell
ffmpeg -i input.mp4 -i subtitles.srt -c copy -c:s mov_text output.mp4
-i input.mp4: Input video file-i subtitles.srt: Input subtitle file-c copy: Copy video and audio streams-c:s mov_text: Convert subtitles to mov_text format (required for MP4 container)
#Split a cue sheet into individual tracks
PowerShell
param(
[Parameter(Mandatory=$true)]
[string]$FlacFile,
[Parameter(Mandatory=$true)]
[string]$CueFile,
[Parameter(Mandatory=$false)]
[string]$OutputDir = ""
)
# Verify files exist
if (-not (Test-Path $FlacFile)) {
Write-Error "FLAC file not found: $FlacFile"
exit 1
}
if (-not (Test-Path $CueFile)) {
Write-Error "CUE file not found: $CueFile"
exit 1
}
# Verify ffmpeg is available
try {
$null = Get-Command ffmpeg -ErrorAction Stop
} catch {
Write-Error "ffmpeg not found in PATH. Please install ffmpeg first."
exit 1
}
# Set output directory
if ([string]::IsNullOrWhiteSpace($OutputDir)) {
$OutputDir = Split-Path $FlacFile -Parent
}
if (-not (Test-Path $OutputDir)) {
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
}
Write-Host "Reading CUE file: $CueFile" -ForegroundColor Cyan
# Parse CUE file
$cueContent = Get-Content $CueFile -Encoding UTF8
$tracks = @()
$currentTrack = $null
$performer = ""
$album = ""
foreach ($line in $cueContent) {
$line = $line.Trim()
# Get album info
if ($line -match '^PERFORMER\s+"(.+)"') {
if ($null -eq $currentTrack) {
$performer = $matches[1]
} else {
$currentTrack.Performer = $matches[1]
}
}
elseif ($line -match '^TITLE\s+"(.+)"') {
if ($null -eq $currentTrack) {
$album = $matches[1]
} else {
$currentTrack.Title = $matches[1]
}
}
elseif ($line -match '^TRACK\s+(\d+)\s+AUDIO') {
if ($null -ne $currentTrack) {
$tracks += $currentTrack
}
$currentTrack = @{
Number = [int]$matches[1]
Title = ""
Performer = $performer
StartTime = ""
}
}
elseif ($line -match '^\s*INDEX\s+01\s+(\d+):(\d+):(\d+)') {
if ($null -ne $currentTrack) {
$minutes = [int]$matches[1]
$seconds = [int]$matches[2]
$frames = [int]$matches[3]
# Convert to seconds (75 frames per second in CD audio)
$totalSeconds = $minutes * 60 + $seconds + ($frames / 75.0)
$currentTrack.StartTime = $totalSeconds
}
}
}
# Add the last track
if ($null -ne $currentTrack) {
$tracks += $currentTrack
}
if ($tracks.Count -eq 0) {
Write-Error "No tracks found in CUE file"
exit 1
}
Write-Host "Found $($tracks.Count) tracks" -ForegroundColor Green
# Split the FLAC file
for ($i = 0; $i -lt $tracks.Count; $i++) {
$track = $tracks[$i]
$trackNum = $track.Number.ToString("D2")
# Sanitize filename
$title = $track.Title -replace '[\\/:*?"<>|]', '_'
$outputFile = Join-Path $OutputDir "$trackNum - $title.flac"
Write-Host "Extracting Track $trackNum`: $($track.Title)" -ForegroundColor Yellow
# Build ffmpeg command
$ffmpegArgs = @(
"-i", $FlacFile,
"-ss", $track.StartTime.ToString("F3")
)
# Add duration if not the last track
if ($i -lt $tracks.Count - 1) {
$duration = $tracks[$i + 1].StartTime - $track.StartTime
$ffmpegArgs += "-t", $duration.ToString("F3")
}
# Add metadata and output settings
$ffmpegArgs += @(
"-metadata", "artist=$($track.Performer)",
"-metadata", "title=$($track.Title)",
"-metadata", "album=$album",
"-metadata", "track=$($track.Number)",
"-c:a", "flac",
"-compression_level", "8",
$outputFile
)
# Execute ffmpeg
& ffmpeg @ffmpegArgs -y 2>&1 | Out-Null
if ($LASTEXITCODE -eq 0) {
Write-Host " ✓ Created: $outputFile" -ForegroundColor Green
} else {
Write-Error " ✗ Failed to extract track $trackNum"
}
}
Write-Host "`nSplit complete! Output directory: $OutputDir" -ForegroundColor Cyan
Do you have a question or a suggestion about this post? Contact me!