FFmpeg is a powerful open-source multimedia framework for encoding, decoding, transcoding, and streaming audio and video. It is the tool of choice for automated workflows, headless servers, and custom streaming pipelines. This guide covers streaming to WAVE via RTMP and SRT, transcoding files for WAVE ingest, and common FFmpeg patterns.
Before you begin, make sure you have:
ffmpeg -protocols 2>&1 | grep srt){% tabs %} {% tab label=“macOS” %} Install FFmpeg with Homebrew:
brew install ffmpeg
Homebrew builds include SRT and most codecs by default. {% /tab %}
{% tab label=“Linux” %} Install from your distribution’s package manager:
# Ubuntu / Debian
sudo apt update && sudo apt install ffmpeg
# Fedora
sudo dnf install ffmpeg
If your distribution’s FFmpeg does not include SRT support, build from source with --enable-libsrt.
{% /tab %}
{% tab label=“Windows” %} Download a static build from gyan.dev/ffmpeg or install via Chocolatey:
choco install ffmpeg
The ffmpeg-full builds include SRT support.
{% /tab %}
{% /tabs %}
Verify your installation:
ffmpeg -version
ffmpeg -protocols 2>&1 | grep srt
The second command should output srt if SRT support is available.
This command captures video from a local camera and streams it to WAVE over RTMP:
ffmpeg \
-f v4l2 -video_size 1920x1080 -framerate 30 -i /dev/video0 \
-f alsa -i default \
-c:v libx264 -preset veryfast -b:v 5000k -maxrate 5000k -bufsize 10000k \
-g 60 -keyint_min 60 \
-c:a aac -b:a 160k -ar 48000 \
-f flv "rtmp://ingest.wave.online/live/{stream-key}"
Replace {stream-key} with your actual WAVE stream key.
{% callout type=“info” title=“Platform-specific capture devices” %}
The example above uses Video4Linux (v4l2) and ALSA for Linux. On macOS, use -f avfoundation -i "0:0". On Windows, use -f dshow -i video="Camera Name":audio="Microphone Name". Run ffmpeg -devices to list available capture devices on your system.
{% /callout %}
To stream a pre-recorded file as if it were a live broadcast:
ffmpeg \
-re \
-i input.mp4 \
-c:v libx264 -preset veryfast -b:v 5000k -maxrate 5000k -bufsize 10000k \
-g 60 -keyint_min 60 \
-c:a aac -b:a 160k -ar 48000 \
-f flv "rtmp://ingest.wave.online/live/{stream-key}"
The -re flag reads the input at its native frame rate, simulating a live source. Without it, FFmpeg sends the file as fast as possible, which overwhelms the ingest server.
ffmpeg \
-re \
-i input.mp4 \
-c:v libx264 -preset veryfast -b:v 5000k -maxrate 5000k -bufsize 10000k \
-g 60 -keyint_min 60 \
-c:a aac -b:a 160k -ar 48000 \
-f flv "rtmps://ingest.wave.online:443/live/{stream-key}"
ffmpeg \
-f v4l2 -video_size 1920x1080 -framerate 30 -i /dev/video0 \
-f alsa -i default \
-c:v libx264 -preset veryfast -b:v 5000k -maxrate 5000k -bufsize 10000k \
-g 60 -keyint_min 60 \
-c:a aac -b:a 160k -ar 48000 \
-f mpegts "srt://ingest.wave.online:9710?streamid={stream-key}&latency=200000"
{% callout type=“warning” title=“SRT output format must be mpegts” %}
SRT transports MPEG-TS. Use -f mpegts (not -f flv). Using the wrong container format causes a silent connection failure.
{% /callout %}
ffmpeg \
-re \
-i input.mp4 \
-c:v libx264 -preset veryfast -b:v 5000k -maxrate 5000k -bufsize 10000k \
-g 60 -keyint_min 60 \
-c:a aac -b:a 160k -ar 48000 \
-f mpegts "srt://ingest.wave.online:9710?streamid={stream-key}&latency=200000"
To enable AES encryption on the SRT connection:
ffmpeg \
-re \
-i input.mp4 \
-c:v libx264 -preset veryfast -b:v 5000k \
-g 60 -keyint_min 60 \
-c:a aac -b:a 160k -ar 48000 \
-f mpegts "srt://ingest.wave.online:9710?streamid={stream-key}&latency=200000&pbkeylen=16&passphrase=YourSecurePassphrase"
pbkeylen=16 enables AES-128. Use pbkeylen=32 for AES-256.passphrase must match the passphrase configured in your WAVE stream settings exactly.If you need to prepare files for upload to WAVE rather than live streaming, transcode them to a WAVE-compatible format:
ffmpeg \
-i input.mov \
-c:v libx264 -preset medium -crf 22 -profile:v high -level 4.1 \
-pix_fmt yuv420p \
-c:a aac -b:a 192k -ar 48000 \
-movflags +faststart \
output.mp4
Key settings:
-crf 22 — Constant Rate Factor for quality-based encoding. Lower values produce higher quality. Range: 18 (high quality) to 28 (lower quality).-profile:v high -level 4.1 — Ensures broad player compatibility.-pix_fmt yuv420p — Required for compatibility with most players and WAVE’s transcoding pipeline.-movflags +faststart — Moves the MP4 metadata to the beginning of the file, enabling progressive playback.| Option | Description |
|---|---|
-re | Read input at native frame rate (required for file-to-live) |
-c:v libx264 | Use H.264 software encoder |
-c:v h264_nvenc | Use NVIDIA hardware encoder |
-c:v h264_qsv | Use Intel Quick Sync hardware encoder |
-preset veryfast | Encoding speed/quality tradeoff (ultrafast to placebo) |
-b:v 5000k | Target video bitrate |
-maxrate 5000k | Maximum video bitrate (pair with -bufsize) |
-bufsize 10000k | Rate control buffer size (typically 2x target bitrate) |
-g 60 | Keyframe interval in frames (60 frames = 2 seconds at 30 fps) |
-keyint_min 60 | Minimum keyframe interval (set equal to -g for fixed interval) |
-c:a aac | Use AAC audio encoder |
-b:a 160k | Audio bitrate |
-ar 48000 | Audio sample rate (48 kHz) |
-f flv | FLV output format (required for RTMP) |
-f mpegts | MPEG-TS output format (required for SRT) |
/live at the end.ffmpeg -protocols lists srt. If it does not, your FFmpeg build lacks SRT support.nc -vz ingest.wave.online 1935nc -vzu ingest.wave.online 9710-re flag is included. Without it, FFmpeg sends frames faster than real-time, causing timestamp issues on the ingest server.-framerate value in the command.-vsync cfr to force constant frame rate output if the source has variable frame rate.-b:v and -maxrate to the same value.-preset value. veryfast is a good balance for real-time streaming. If your CPU has headroom, try faster or fast for better quality at the same bitrate.-f mpegts as the output format. MPEG-TS is required for SRT; FLV does not work.streamid parameter must match your WAVE stream key exactly.latency parameter if you are on a high-loss network (try 500000 for 500ms).-loglevel verbose to see the full server response before the pipe closes.{% contact-support category=“technical” /%}
{% related-articles /%}