ffmpeg cheatsheet

 
 
  • Gérald Barré

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!

Follow me:
Enjoy this blog?