What Is RTMP
RTMP (Real-Time Messaging Protocol) is a live-streaming protocol developed by Adobe. Almost every major live platform, including YouTube Live and Twitch, accepts RTMP (and RTMPS, which is RTMP inside TLS encryption). Since May 2019, Facebook Live has accepted only RTMPS (Meta).
FFmpeg works as the RTMP client. It encodes your video and audio in real time and keeps sending them to the platform’s RTMP server, which passes the stream on to viewers. The destination URL contains a stream key (STREAM-KEY). Each account has its own key, and it tells the server which channel the broadcast belongs to.
You get the stream key from the platform’s dashboard (YouTube Studio, Twitch’s Creator Dashboard and so on). Treat the stream key like a password. Anyone who has it can stream to your channel, so keep it out of screenshots and off your broadcast screen.
The Minimal Push Command
The most basic form re-encodes a video file on your computer and pushes it to YouTube Live:
ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -b:v 4500k -maxrate 4500k -bufsize 9000k -pix_fmt yuv420p -g 60 -c:a aac -b:a 128k -ar 44100 -f flv rtmp://a.rtmp.youtube.com/live2/STREAM-KEY
Replace STREAM-KEY with your own key, and input.mp4 streams to YouTube Live in real time.
What Each Option Means
| Option | Description |
|---|---|
-re |
Read the input at its own frame rate, in real time. Needed when the input is a file; usually left out for webcams and capture devices |
-i input.mp4 |
Input file (a device such as a webcam also works) |
-c:v libx264 |
Encode the video as H.264 |
-preset veryfast |
Trade-off between encoding speed and quality. A fast setting that keeps up in real time |
-b:v 4500k |
Target video bitrate |
-maxrate 4500k |
Maximum bitrate |
-bufsize 9000k |
Rate-control buffer size (about 2× the maxrate is a good rule) |
-pix_fmt yuv420p |
Pixel format. Required for compatibility |
-g 60 |
Keyframe (GOP) interval |
-c:a aac -b:a 128k -ar 44100 |
Encode audio as AAC, 128 kbps, 44.1 kHz |
-f flv |
Use FLV as the output container. Required for RTMP |
-re: Read in Real Time
-re makes FFmpeg read the input at its own frame rate. FFmpeg can read a file from disk as fast as the disk allows, so without -re it would send a video of several dozen seconds in a few seconds, and the broadcast would not work. With -re, a 30 fps video is read at 30 frames per second and sent out in real time. Use it whenever the input is a file. Live devices such as webcams already deliver frames in real time, so they sometimes do not need it.
-f flv: The RTMP Container
RTMP carries the stream in the FLV container. FFmpeg does not work this out from an RTMP URL, so you must pass -f flv yourself. Without it, FFmpeg stops with Unable to choose an output format for 'rtmp://…'.
-g: Keyframe (GOP) Interval
-g sets how many frames apart the keyframes (I-frames) are. Many platforms recommend a keyframe every 2 seconds (a 2-second GOP), so set -g to the frame rate × 2.
- 30 fps →
-g 60 - 60 fps →
-g 120
Playback can only start, or switch to another quality, at a keyframe. If keyframes are too far apart, starting and switching take longer. If they are too close together, the stream needs more bitrate for the same quality.
-pix_fmt yuv420p: Required for Compatibility
Some sources use a pixel format such as yuv444p or yuvj420p. Sent as it is, the stream may not play on some players or platforms. -pix_fmt yuv420p converts it to the format that plays almost everywhere.
-maxrate / -bufsize: Pseudo-CBR
Live streams work best at a steady, constant bitrate (CBR). libx264 leans toward a variable bitrate (VBR) by default, so set -maxrate to the same value as -b:v and -bufsize to about twice that. This gives a near-constant bitrate (pseudo-CBR) that keeps the bitrate from overshooting, so the stream is less likely to exceed what your connection or the platform can handle.
Streaming to YouTube Live
Copy the stream key from the live dashboard in YouTube Studio and paste it at the end of the URL. YouTube’s RTMP address is rtmp://a.rtmp.youtube.com/live2/.
ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -b:v 4500k -maxrate 4500k -bufsize 9000k -pix_fmt yuv420p -g 60 -c:a aac -b:a 128k -ar 44100 -f flv rtmp://a.rtmp.youtube.com/live2/STREAM-KEY
For H.264, YouTube recommends 10 Mbps for 1080p at 30 fps, 12 Mbps for 1080p at 60 fps, and 4 Mbps for 720p or lower at 30 fps (YouTube Help). The 4500 kbps in this command is close to the 720p value. For 1080p at 30 fps, set -b:v and -maxrate to 10000k and -bufsize to 20000k if your upload speed allows it. -g 60 is a 2-second GOP at 30 fps. For 60 fps, change it to -g 120.
Streaming to Twitch
Streaming to Twitch works the same way. Only the destination URL and the bitrate limit are different. Twitch’s address is rtmp://live.twitch.tv/app/, and you get the stream key from the Creator Dashboard.
ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -b:v 6000k -maxrate 6000k -bufsize 12000k -pix_fmt yuv420p -g 120 -c:a aac -b:a 160k -ar 44100 -f flv rtmp://live.twitch.tv/app/STREAM-KEY
Twitch’s guideline limit for video is about 6000 kbps. Going over it can cause buffering for viewers, so keep -b:v and -maxrate at 6000k or lower. This command assumes 60 fps, so it uses -g 120 (a 2-second GOP), and it sets the audio to 160 kbps.
Pushing Without Re-Encoding (-c copy)
If the source is already H.264 video with AAC audio, and its resolution, bitrate and GOP meet the platform’s requirements, you can send it as it is, without re-encoding. Nothing is recompressed, so the CPU load drops sharply and there is no quality loss.
ffmpeg -re -i input.mp4 -c copy -f flv rtmp://server/app/STREAM-KEY
-c copy copies the video and audio streams unchanged. The conditions are strict, though:
- The codecs must be ones the platform accepts. H.264 video with AAC audio works almost everywhere; YouTube also accepts HEVC or AV1 video and MP3 audio (YouTube Help).
- The resolution, frame rate and bitrate must be within the platform’s limits.
- The GOP (keyframe interval) must meet the requirements. With copy,
-gcannot change it, so the source must already have a 2-second GOP.
If any condition is not met, re-encode with libx264 instead. When a stream sent with -c copy will not start or the picture glitches, one of these conditions is almost always the cause.
Live Streaming a Webcam
To stream a webcam and a microphone instead of a file, this Linux example uses v4l2 for the camera and ALSA for the sound:
ffmpeg -f v4l2 -i /dev/video0 -f alsa -i default -c:v libx264 -preset veryfast -b:v 3000k -maxrate 3000k -bufsize 6000k -pix_fmt yuv420p -g 60 -c:a aac -b:a 128k -f flv rtmp://a.rtmp.youtube.com/live2/STREAM-KEY
The command has two inputs: -f v4l2 -i /dev/video0 is the camera and -f alsa -i default is the microphone. FFmpeg combines them into one live stream. On your system the camera may be /dev/video1 or similar; list the devices with ls /dev/video*.
A webcam already delivers frames in real time, so the command has no -re. The bitrate is kept at 3000 kbps, which suits a camera stream.
On Windows, use
-f dshowfor devices; on macOS, use-f avfoundation. The way you list device names, and how you write them after-i, also differ by OS.
Common Errors and Fixes
Operation not permitted / Connection Refused
Operation not permitted means the server answered but rejected the stream. FFmpeg usually prints the server’s reason on a Server error: line just before it. The usual cause:
- Wrong stream key: copy the current key from the dashboard again. Keys can be regenerated from time to time.
If FFmpeg cannot reach the server at all, it prints Cannot open connection tcp://… instead:
- Firewall or network block: check that the RTMP port (1935 by default) is not blocked by a firewall or network device.
Broken pipe
The connection dropped during the stream. This happens when the network cuts out for a moment, or when your upload speed is too low for the server to receive everything and it disconnects. Measure your real upload speed with a tool such as iperf3, and check that it is comfortably above your stream bitrate (video + audio). If it is not, lower -b:v.
Buffering Due to Excessive Bitrate
If the bitrate you set is above what your connection or the platform allows, viewers see frequent buffering and the broadcast becomes unstable. Lower -b:v and -maxrate to the platform’s recommended values (YouTube with H.264: 10 Mbps for 1080p at 30 fps, 4 Mbps for 720p at 30 fps; Twitch: about 6000 kbps), and set -bufsize to about twice the maxrate.
No Audio
If the video arrives but there is no sound, the audio codec was usually not set. Set it explicitly, for example -c:a aac -b:a 128k. With -c copy, the source audio may be something other than AAC (Opus, for example) that the platform does not accept.
Slow Start Because the GOP Is Too Long
If you leave out -g, or set it too high, the picture takes a while to appear when a viewer opens the stream, because playback starts at a keyframe. Set a 2-second GOP with the frame rate × 2 (30 fps → -g 60, 60 fps → -g 120).
Related Articles
- HLS Segmenting — Creating Segments and Playlists for Web Streaming
- Generate MPEG-DASH Segments
- Compressing Video — CRF and Target Bitrate
- Changing the Frame Rate
- GPU Hardware Encoding (NVENC)
FAQ
Is -re really necessary?
Yes, when the input is a file. Without -re, FFmpeg reads the file far faster than real time and sends a video of several dozen seconds almost at once. Webcams and capture devices already deliver frames in real time, so they often do not need -re.
-c copy or re-encoding — which should I use?
If the source is already H.264/AAC and its resolution, bitrate and GOP meet the platform’s requirements, use -c copy. It uses almost no CPU and loses no quality. If even one condition is not met, re-encode with libx264.
What value should I use for the GOP (-g)?
Platforms recommend a 2-second GOP. Multiply the frame rate by 2: -g 60 for 30 fps, -g 120 for 60 fps. With a longer GOP, playback starts and switches quality more slowly.
What happens if my stream key leaks?
Someone else can stream to your channel. Keep the key as secret as a password, and never show it on your broadcast screen or in screenshots. If it leaks, generate a new stream key in the platform’s dashboard.