Ahosting Logo
Knowledge Base

Getting Started with FFmpeg on Your Ahosting VPS

On an Ahosting FFmpeg VPS, FFmpeg and FFprobe are already installed. Connect over SSH, confirm the build, and you can start work: there is no compilation step unless you need something the packaged build does not include.

This covers the first connection, checking what your build actually supports, a first transcode, and how to run long jobs so they survive a dropped connection.

Connect and confirm

Connect over SSH using the details in your welcome email:

ssh username@your-server-ip

Then check what you have:

ffmpeg -version
ffprobe -version

The version line matters less than the encoder list. Builds differ substantially in what they include, and a missing encoder is not something a command change can fix:

# Is x264 there?
ffmpeg -encoders | grep 264

# What about x265 and VP9?
ffmpeg -encoders | grep -E "265|vp9"

# Full list of everything the build supports
ffmpeg -encoders | less

Do this before writing anything substantial. Discovering that libx264 is absent halfway through building a pipeline is a bad way to spend an afternoon, and the error message, Unknown encoder, reads like a typo rather than a missing feature.

Your first conversion

Upload a test file, then:

ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4

FFmpeg prints its progress: frame number, frames per second, elapsed time and estimated size. The fps figure is the useful one; it tells you whether this job takes two minutes or two hours, immediately rather than after waiting.

If it finishes suspiciously fast, check the output actually has content. A command that silently produced nothing looks the same as a fast success from the outside.

Check before you transcode

The habit that saves the most time is inspecting the file first:

ffprobe -hide_banner input.mkv

If the codecs inside are already what you need, you do not need to re-encode. Changing only the container is instant and lossless:

ffmpeg -i input.mkv -c copy output.mp4

People reach for a full transcode by reflex, and a large share of the time a stream copy would have done the job in seconds with no quality loss at all.

Running long jobs over SSH without losing themCheck what your build supportsffmpeg -encoders,before assuming a codecexistsStart a terminal multiplexerscreen or tmux, beforestarting the jobRun the encode inside itnow the connectiondropping is irrelevantDetach and reattachcheck progress wheneveryou likeA command run directly dies with the connection, and hours of encoding go with it. This is one command to avoid that.

Long jobs need to survive a disconnection

A transcode running directly in an SSH session dies when the connection drops. On a long encode that is hours of work lost with nothing to show for it, and connections drop for reasons that have nothing to do with you.

Use a terminal multiplexer:

screen -S encode
ffmpeg -i big.mp4 -c:v libx264 -crf 23 output.mp4
# Ctrl+A then D to detach

The job continues after you disconnect. Come back with:

screen -r encode

For something you do not need to watch, redirect the output and let it run in the background:

nohup ffmpeg -i big.mp4 -c:v libx264 -crf 23 output.mp4 > encode.log 2>&1 &

Then check progress with tail -f encode.log.

Do not saturate the machine

FFmpeg will use every core it can. On a server also running a website, that makes the site slow for as long as the encode runs.

Two controls. Limit threads:

ffmpeg -threads 2 -i input.mp4 -c:v libx264 -crf 23 output.mp4

Or lower the priority so the encode yields to anything else that needs CPU:

nice -n 19 ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4

nice is usually the better answer: the encode still uses idle capacity, so it is not much slower, but it steps aside when a visitor arrives.

Queue jobs rather than running several at once. Two encodes competing for the same cores finish later than the same two run in sequence, and the machine stays usable throughout.

Watch disk as well as CPU

Video work fills disks quickly, and an intermediate file left behind after a failed job is easy to miss.

df -h
du -sh /home/username/*

Reading the source and writing the output on the same volume also competes for the same I/O. If encodes are slow while the cores sit idle, that is usually why.

Automating it

For scheduled work, a cron job is the right tool. Two things differ from running commands by hand.

Use absolute paths, for the FFmpeg binary and for every file. Cron does not start in your home directory and does not inherit your PATH:

/usr/bin/ffmpeg -y -i /home/user/in.mp4 -c:v libx264 -crf 23 /home/user/out.mp4 >> /home/user/ffmpeg.log 2>&1

And include -y. Without it FFmpeg prompts before overwriting an existing file, and under cron that prompt waits forever with nobody to answer it.

Setting up cron jobs in cPanel explains the scheduling side.

Building FFmpeg yourself

Only worth doing when the packaged build genuinely lacks something you need. A specific encoder, or a version newer than what is packaged.

It is a real commitment: a self-built binary does not receive security updates with the system, so you own the job of rebuilding it. Check that the packaged build is actually missing what you need first, using the encoder list above. It usually is not.

Where to go next

The commands cheat sheet is the reference for day-to-day work. Converting video formats walks through the decisions behind a transcode, and performance optimization explains making it faster once you have something working.

Once FFmpeg is running, it is worth checking whether the machine can encode on dedicated hardware instead of the processor. How to Use Hardware Acceleration with FFmpeg walks through finding out and deciding.

Confirm what your build actually supports

Commands copied from elsewhere fail on a build without the relevant component, and the error rarely says so plainly.

ffmpeg -hide_banner -encoders | grep -E 'libx264|libx265|libvpx|aac|libmp3lame'
ffmpeg -hide_banner -filters | grep -E 'scale|loudnorm|subtitles|drawtext'
ffmpeg -hide_banner -version | head -3

Read the configuration line in the version output. It lists which libraries were compiled in, and anything absent there cannot be used no matter how the command is written.

The three that most often turn out to be missing are the newer video encoder, the subtitle filter and text drawing, because each depends on an external library that packages sometimes omit. Knowing before writing a pipeline is considerably cheaper than after.

Keep a job from taking the machine with it

A single conversion will use every core it is given, which on a server also doing other work is a self inflicted outage.

nice -n 19 ionice -c2 -n7 ffmpeg -hide_banner -threads 2 -i in.mp4 -c:v libx264 -crf 23 out.mp4
systemd-run --scope -p CPUQuota=200% -p MemoryMax=2G ffmpeg -i in.mp4 out.mp4

Limiting threads bounds the processor use directly. Running it at a lower priority means it yields to the web server rather than competing with it, which is the difference between a slow conversion and a slow site.

The second form applies a hard ceiling and is worth using for anything triggered by a visitor, since the input size is then outside your control.

Handle files you did not create defensively

Anything arriving from a customer should be treated as unknown until inspected, both for cost and for correctness.

ffprobe -v error -show_entries format=format_name,duration,size -of default=nw=1 upload.mp4
ffprobe -v error -select_streams v:0 -show_entries stream=width,height,codec_name -of csv=p=0 upload.mp4

Reject what you cannot read before it reaches the queue. A file with no duration is truncated, and one whose real format does not match its extension will fail partway through a job that has already consumed processor time.

Set an upper bound on dimensions and duration as well. Without one, a single very large upload occupies the queue for hours and every other customer waits behind it. Running FFmpeg jobs in parallel covers the queue.