mcpField
F
ffmpeg-cicd-runners

ffmpeg-cicd-runners

github.com/josiahsiegelCloud & DevOps5973 installsUpdated 19w ago
Repository

About ffmpeg-cicd-runners

ffmpeg-cicd-runners is a practical guide to running FFmpeg in CI/CD pipelines, aimed at teams processing video in automated builds. It covers installation, containers, caching, parallel and multi-format jobs, and runner-specific considerations across GitHub Actions, GitLab CI, and Jenkins.

Key features

  1. 01FFmpeg setup examples for CI systems
  2. 02Docker-based runner configurations
  3. 03Caching FFmpeg and dependencies
  4. 04Parallel and matrix processing patterns
  5. 05Windows runner considerations

Use cases

  1. 01Transcoding videos in CI jobs
  2. 02Validating video files on pull requests
  3. 03Generating thumbnails and audio tracks
  4. 04Saving processed outputs as build artifacts

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill ffmpeg-cicd-runners

After installing, type/ffmpeg-cicd-runnersin Claude Code to confirm it loaded.

Details

From the project README

CRITICAL GUIDELINES

Windows File Path Requirements

MANDATORY: Always Use Backslashes on Windows for File Paths

When using Edit or Write tools on Windows, you MUST use backslashes (\) in file paths, NOT forward slashes (/).


Quick Reference

PlatformInstall MethodExample
GitHub Actionsapt-get or actionuses: FedericoCarboni/setup-ffmpeg@v3
GitLab CIDocker imageimage: jrottenberg/ffmpeg:7.1-ubuntu2404
JenkinsDocker containerdocker { image 'jrottenberg/ffmpeg:7.1' }
TaskYAML Snippet
Cache FFmpeguses: actions/cache@v4 with path: /usr/local/bin/ffmpeg
Upload artifactuses: actions/upload-artifact@v4
Matrix buildstrategy: { matrix: { format: [mp4, webm, mkv] } }

When to Use This Skill

Use for CI/CD video processing pipelines:

  • GitHub Actions FFmpeg workflows
  • GitLab CI/CD video transcoding
  • Jenkins video processing jobs
  • Caching FFmpeg for faster builds
  • Windows runner workarounds

FFmpeg in CI/CD Pipelines (2025)

Comprehensive guide to using FFmpeg in GitHub Actions, GitLab CI, Jenkins, and other CI/CD systems.

Overview

Common CI/CD Use Cases
  • Video validation: Check uploaded videos meet requirements
  • Transcoding: Convert videos to multiple formats/resolutions
  • Thumbnail generation: Create preview images
  • Audio extraction: Process audio tracks
  • Quality checks: Validate encoding parameters
  • Testing: Test video processing pipelines
Key Considerations
  • Build time: FFmpeg compilation takes 20-40+ minutes
  • Runner resources: CPU/memory limits affect processing
  • Caching: Cache FFmpeg builds for faster runs
  • Platform differences: Windows runners have unique issues
  • Dependencies: Codec libraries may need installation

GitHub Actions

Install FFmpeg (Quick)
name: Video Processing

on: [push, pull_request]

jobs:
  process:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install FFmpeg
        run: |
          sudo apt-get update
          sudo apt-get install -y ffmpeg

      - name: Check FFmpeg version
        run: ffmpeg -version

      - name: Process video
        run: |
          ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4
Install Specific FFmpeg Version
jobs:
  process:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install FFmpeg 7.1
        run: |
          wget https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n7.1-latest-linux64-gpl-7.1.tar.xz
          tar xf ffmpeg-n7.1-latest-linux64-gpl-7.1.tar.xz
          sudo cp ffmpeg-n7.1-latest-linux64-gpl-7.1/bin/* /usr/local/bin/
          ffmpeg -version
Use FedericoCarboni/setup-ffmpeg Action
jobs:
  process:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup FFmpeg
        uses: FedericoCarboni/setup-ffmpeg@v3
        with:
          ffmpeg-version: release
          github-token: ${{ secrets.GITHUB_TOKEN }}

      - name: Process video
        run: ffmpeg -i input.mp4 output.webm
Docker-Based FFmpeg
jobs:
  process:
    runs-on: ubuntu-latest
    container:
      image: jrottenberg/ffmpeg:7.1-ubuntu2404

    steps:
      - uses: actions/checkout@v4

      - name: Process video
        run: |
          ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4
Caching FFmpeg Build
jobs:
  build-ffmpeg:
    runs-on: ubuntu-latest

    steps:
      - name: Cache FFmpeg
        id: cache-ffmpeg
        uses: actions/cache@v4
        with:
          path: /usr/local/bin/ffmpeg
          key: ffmpeg-7.1-linux-${{ runner.arch }}

      - name: Build FFmpeg (if not cached)
        if: steps.cache-ffmpeg.outputs.cache-hit != 'true'
        run: |
          wget https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n7.1-latest-linux64-gpl-7.1.tar.xz
          tar xf ffmpeg-n7.1-latest-linux64-gpl-7.1.tar.xz
          sudo cp ffmpeg-n7.1-latest-linux64-gpl-7.1/bin/ffmpeg /usr/local/bin/
Matrix Build (Multiple Platforms)
jobs:
  process:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v4

      - name: Setup FFmpeg
        uses: FedericoCarboni/setup-ffmpeg@v3

      - name: Process video
        run: ffmpeg -i input.mp4 -c:v libx264 output_${{ matrix.os }}.mp4
        shell: bash
Windows Runner (Known Issues)

Issue: Windows runners take significantly longer (up to 4 hours for vcpkg FFmpeg builds)

Solutions:

jobs:
  windows-ffmpeg:
    runs-on: windows-latest

    steps:
      - uses: actions/checkout@v4

      # Option 1: Use pre-built binaries (recommended)
      - name: Download FFmpeg
        run: |
          Invoke-WebRequest -Uri "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n7.1-latest-win64-gpl-7.1.zip" -OutFile ffmpeg.zip
          Expand-Archive ffmpeg.zip -DestinationPath .
          $env:PATH = "$PWD\ffmpeg-n7.1-latest-win64-gpl-7.1\bin;$env:PATH"
          ffmpeg -version

      # Option 2: Use setup-ffmpeg action
      - name: Setup FFmpeg
        uses: FedericoCarboni/setup-ffmpeg@v3

      - name: Process video
        run: ffmpeg -i input.mp4 output.mp4
GPU-Enabled Runners
jobs:
  gpu-process:
    runs-on: [self-hosted, gpu, linux]

    steps:
      - uses: actions/checkout@v4

      - name: Process with NVIDIA GPU
        run: |
          ffmpeg -hwaccel cuda -hwaccel_output_format cuda \
            -i input.mp4 \
            -c:v h264_nvenc \
            -preset p4 \
            output.mp4
Artifact Upload
jobs:
  process:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install FFmpeg
        run: sudo apt-get update && sudo apt-get install -y ffmpeg

      - name: Generate outputs
        run: |
          mkdir -p outputs
          ffmpeg -i input.mp4 -vf scale=1920:1080 outputs/1080p.mp4
          ffmpeg -i input.mp4 -vf scale=1280:720 outputs/720p.mp4
          ffmpeg -i input.mp4 -ss 00:00:05 -vframes 1 outputs/thumbnail.jpg

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: video-outputs
          path: outputs/
          retention-days: 7
Video Validation Workflow
name: Validate Videos

on:
  pull_request:
    paths:
      - '**.mp4'
      - '**.webm'
      - '**.mov'

jobs:
  validate:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install FFmpeg
        run: sudo apt-get update && sudo apt-get install -y ffmpeg

      - name: Validate videos
        run: |
          for video in $(find . -name "*.mp4" -o -name "*.webm" -o -name "*.mov"); do
            echo "Validating: $video"

            # Check if valid
            if ! ffprobe -v error "$video"; then
              echo "Invalid video: $video"
              exit 1
            fi

            # Get info
            duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$video")
            resolution=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 "$video")

            echo "Duration: ${duration}s"
            echo "Resolution: $resolution"

            # Validate constraints
            if (( $(echo "$duration > 300" | bc -l) )); then
              echo "Video too long: $video ($duration seconds)"
              exit 1
            fi
          done

GitLab CI

Basic Pipeline
# .gitlab-ci.yml

stages:
  - process

video-process:
  stage: process
  image: jrottenberg/ffmpeg:7.1-ubuntu2404
  script:
    - ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4
  artifacts:
    paths:
      - output.mp4
    expire_in: 1 week
Multi-Format Transcoding
transcode:
  stage: process
  image: jrottenberg/ffmpeg:7.1-ubuntu2404
  script:
    - mkdir -p outputs
    - ffmpeg -i input.mp4 -c:v libx264 -crf 23 outputs/h264.mp4
    - ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 outputs/vp9.webm
    - ffmpeg -i input.mp4 -vf scale=1280:720 outputs/720p.mp4
  artifacts:
    paths:
      - outputs/
Parallel Processing
.process-template: &process-template
  stage: process
  image: jrottenberg/ffmpeg:7.1-ubuntu2404

process-1080p:
  <<: *process-template
  script:
    - ffmpeg -i input.mp4 -vf scale=1920:1080 output_1080p.mp4
  artifacts:
    paths:
      - output_1080p.mp4

process-720p:
  <<: *process-template
  script:
    - ffmpeg -i input.mp4 -vf scale=1280:720 output_720p.mp4
  artifacts:
    paths:
      - output_720p.mp4

process-480p:
  <<: *process-template
  script:
    - ffmpeg -i input.mp4 -vf scale=854:480 output_480p.mp4
  artifacts:
    paths:
      - output_480p.mp4
GPU Runner (GitLab)
gpu-transcode:
  stage: process
  tags:
    - gpu
    - linux
  image: jrottenberg/ffmpeg:7.1-nvidia2404
  script:
    - ffmpeg -hwaccel cuda -i input.mp4 -c:v h264_nvenc output.mp4

Jenkins

Declarative Pipeline
pipeline {
    agent {
        docker {
            image 'jrottenberg/ffmpeg:7.1-ubuntu2404'
            args '-v /data/videos:/videos'
        }
    }

    stages {
        stage('Process') {
            steps {
                sh '''
                    ffmpeg -i /videos/input.mp4 \
                           -c:v libx264 -crf 23 \
                           -c:a aac -b:a 128k \
                           /videos/output.mp4
                '''
            }
        }
    }

    post {
        success {
            archiveArtifacts artifacts: '/videos/output.mp4'
        }
    }
}
Parallel Transcoding
pipeline {
    agent any

    stages {
        stage('Transcode') {
            parallel {
                stage('1080p') {
                    agent {
                        docker { image 'jrottenberg/ffmpeg:7.1-ubuntu2404' }
                    }
                    steps {
                        sh 'ffmpeg -i input.mp4 -vf scale=1920:1080 output_1080p.mp4'
                    }
                }
                stage('720p') {
                    agent {
                        docker { image 'jrottenberg/ffmpeg:7.1-ubuntu2404' }
                    }
                    steps {
                        sh 'ffmpeg -i input.mp4 -vf scale=1280:720 output_720p.mp4'
                    }
                }
            }
        }
    }
}

BtbN/FFmpeg-Builds

Overview

BtbN/FFmpeg-Builds is the most popular automated FFmpeg build system, providing pre-built static binaries for multiple platforms.

Build Matrix
TargetVariantsFeatures
win64gpl, lgpl, gpl-shared, lgpl-sharedFull Windows 64-bit
winarm64gpl, lgplWindows ARM64
linux64gpl, lgpl, gpl-shared, lgpl-sharedFull Linux 64-bit
linuxarm64gpl, lgplLinux ARM64
Download in CI
- name: Download FFmpeg
  run: |
    # Latest release
    wget https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n7.1-latest-linux64-gpl-7.1.tar.xz

    # Specific version
    wget https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2025-01-15-12-50/ffmpeg-n7.1-latest-linux64-gpl-7.1.tar.xz

Performance Optimization

Parallel Processing
# Process multiple files in parallel
jobs:
  process:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        video: [video1.mp4, video2.mp4, video3.mp4]
      max-parallel: 3

    steps:
      - name: Process ${{ matrix.video }}
        run: ffmpeg -i ${{ matrix.video }} -c:v libx264 output_${{ matrix.video }}
Resource-Optimized Encoding
- name: Optimized encoding
  run: |
    # Use appropriate threads for runner
    THREADS=$(nproc)

    ffmpeg -i input.mp4 \
      -threads $THREADS \
      -c:v libx264 \
      -preset fast \
      -crf 23 \
      output.mp4
Caching Dependencies
- name: Cache FFmpeg and libraries
  uses: actions/cache@v4
  with:
    path: |
      ~/.local/bin/ffmpeg
      ~/.local/lib/
    key: ffmpeg-${{ runner.os }}-${{ hashFiles('ffmpeg-version.txt') }}

Troubleshooting

Common Issues

"ffmpeg: command not found"

# Ensure FFmpeg is in PATH
- name: Add FFmpeg to PATH
  run: echo "/path/to/ffmpeg/bin" >> $GITHUB_PATH

"Cannot allocate memory"

# Reduce memory usage
- name: Process with low memory
  run: |
    ffmpeg -i input.mp4 \
      -threads 2 \
      -preset ultrafast \
      -vf scale=1280:720 \
      output.mp4

Windows path issues

# Use forward slashes on Windows
- name: Process on Windows
  run: ffmpeg -i "./input.mp4" "./output.mp4"
  shell: bash
Debugging
- name: Debug FFmpeg
  run: |
    # Check FFmpeg capabilities
    ffmpeg -version
    ffmpeg -encoders
    ffmpeg -decoders
    ffmpeg -formats

    # Verbose processing
    ffmpeg -v verbose -i input.mp4 -c:v libx264 output.mp4 2>&1 | tee ffmpeg.log

- name: Upload logs
  if: failure()
  uses: actions/upload-artifact@v4
  with:
    name: ffmpeg-logs
    path: ffmpeg.log

Best Practices

  1. Use pre-built binaries - Avoid compiling FFmpeg in CI (slow)
  2. Cache FFmpeg installation - Reduce setup time
  3. Use Docker containers - Consistent FFmpeg environment
  4. Optimize for runner resources - Match threads/preset to available CPU
  5. Validate inputs - Check video files before processing
  6. Upload artifacts - Store outputs for review
  7. Use matrix builds - Parallelize multi-format transcoding
  8. Monitor build times - Windows runners are slower
  9. Pin versions - Avoid latest for reproducibility
  10. Use -preset fast/ultrafast - Faster encoding for CI

This guide covers CI/CD FFmpeg patterns. For hardware acceleration in CI, consider self-hosted GPU runners.

Comments

Markdown supported