What You Will Learn

  • How RTMP works, and the flow by which FFmpeg “pushes” video to a streaming platform
  • The minimal push command, and the meaning of each option (-re, -f flv, -g, -pix_fmt, -maxrate/-bufsize)
  • Streaming commands for YouTube Live and Twitch (with recommended bitrates)
  • How to use -c copy to push without re-encoding when your source is already H.264/AAC
  • How to live stream a webcam plus microphone directly (Linux/v4l2)
  • Common errors and how to fix them

Tested with: FFmpeg 6.1 (verified against real FFmpeg)
Supported OS: Windows / macOS / Linux


What Is RTMP

RTMP (Real-Time Messaging Protocol) is a protocol for live video streaming developed by Adobe. Virtually all major live streaming platforms — YouTube Live, Twitch, Facebook Live, and others — support RTMP input (and RTMPS, RTMP wrapped in TLS).

The streaming flow is simple. FFmpeg acts as an RTMP client, encoding your local video and audio in real time and continuously feeding it to the platform’s RTMP server. The server receives it and redistributes it to viewers. The destination URL includes a stream key (STREAM-KEY) unique to each account, which identifies “which channel this broadcast belongs to.”

You obtain the stream key from your streaming dashboard (YouTube Studio, Twitch’s Creator Dashboard, and so on). A stream key is secret information equivalent to a password. If it leaks, a third party can stream to your channel, so be careful not to expose it in screenshots or on your broadcast screen.


The Minimal Push Command

Let’s start with the most basic form: re-encode a local video file and push 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 the STREAM-KEY portion with your own stream key, and input.mp4 will flow to YouTube Live in real time. This command contains every element required for streaming, so let’s go through the meaning of each one in the next section.


What Each Option Means

OptionDescription
-reRead the input at its native (real-time) frame rate. Required for live streaming
-i input.mp4Input file (you can also specify a device such as a webcam, covered later)
-c:v libx264Encode the video as H.264
-preset veryfastBalance between encoding speed and quality. A faster setting suited to real-time processing
-b:v 4500kTarget video bitrate
-maxrate 4500kMaximum bitrate
-bufsize 9000kRate-control buffer size (roughly 2× the maxrate is a good guideline)
-pix_fmt yuv420pPixel format. Required for compatibility
-g 60Keyframe (GOP) interval
-c:a aac -b:a 128k -ar 44100Encode audio as AAC, 128 kbps, 44.1 kHz
-f flvSpecify FLV as the output container. Required for RTMP

-re: Read in Real Time

-re is the flag that “reads the input at its native frame rate.” Because a file can normally be read from disk all at once, without this flag FFmpeg would push out a video of several dozen seconds in just a few seconds — which won’t work as a broadcast. With -re, a 30 fps video is read at a pace of 30 frames per second and pushed out in real time. It is required when live streaming from a file as input (it is sometimes unnecessary for live devices such as webcams, since they already produce input in real time).

-f flv: The RTMP Container

RTMP uses the FLV container as its transport. Even when the destination is an RTMP URL, you must explicitly pass -f flv to FFmpeg. Forgetting this results in errors such as Unable to find a suitable output format.

-g: Keyframe (GOP) Interval

-g specifies how many frames apart keyframes (I-frames) are inserted. Many platforms recommend a 2-second GOP — that is, specify “frame rate × 2.”

  • 30 fps → -g 60
  • 60 fps → -g 120

Keyframes serve as the starting points when a viewer begins playback or switches between quality variants. If the interval is too long, starting playback and switching quality take longer; if it’s too short, bitrate efficiency drops.

-pix_fmt yuv420p: Required for Compatibility

Depending on the H.264 source material, the pixel format may be yuv444p, yuvj420p, or similar, and pushing it as-is can prevent playback on some players or platforms. Specify -pix_fmt yuv420p to standardize on a widely compatible format.

-maxrate / -bufsize: Pseudo-CBR

To maintain stable bandwidth, live streaming favors a constant bitrate (CBR). By default libx264 leans toward variable bitrate (VBR), so in addition to -b:v, set -maxrate to the same value and -bufsize to roughly twice that, creating a pseudo-CBR that suppresses bitrate overshoot. This makes it less likely to exceed the bandwidth assumed by your connection or the platform.


Streaming to YouTube Live

In YouTube Studio’s live dashboard, copy the stream key and paste it at the end of the URL. YouTube’s RTMP endpoint 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

When streaming 1080p to YouTube, a good video bitrate guideline is 4500–6000 kbps. If your connection and PC performance have headroom, adjust within this range. -g 60 is a 2-second GOP assuming 30 fps; for 60 fps streaming, change it to -g 120.


Streaming to Twitch

Pushing to Twitch has the same basic structure as YouTube — only the destination URL and the bitrate ceiling differ. Twitch’s endpoint 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 video bitrate ceiling is roughly 6000 kbps as a guideline. Exceeding it can cause buffering on the viewer side or disconnect the broadcast, so keep -b:v and -maxrate at or below 6000k. Here we assume 60 fps with -g 120 (2-second GOP) and set audio to 160 kbps.


Pushing Without Re-Encoding (-c copy)

If your source is already H.264 video / AAC audio and its resolution, bitrate, and GOP meet the platform’s requirements, you can push it straight through as a pass-through without re-encoding. Because the video isn’t recompressed, CPU load drops dramatically and there’s no quality degradation.

ffmpeg -re -i input.mp4 -c copy -f flv rtmp://server/app/STREAM-KEY

-c copy copies both the video and audio streams as-is. The conditions, however, are fairly strict:

  • Video must be H.264 and audio must be AAC (VP9, Opus, and the like are not allowed)
  • Resolution, frame rate, and bitrate must be within the platform’s acceptable range
  • The GOP (keyframe interval) must meet the requirements (with copy you can’t change it later with -g, so you need to author the source with a 2-second GOP from the start)

If the conditions don’t match, you’ll ultimately need to re-encode with libx264 as in the earlier sections. When “I just sent it with -c copy but the broadcast won’t start / the video glitches,” this requirement mismatch is almost always the cause.


Live Streaming a Webcam

Here’s an example of live streaming webcam video and microphone audio on the spot, rather than a file. The following combines Linux’s v4l2 (video) and ALSA (audio).

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 key point is that there are two inputs. -f v4l2 -i /dev/video0 is the camera and -f alsa -i default is the microphone; FFmpeg combines the two and pushes them out as a single live stream. The camera device may be /dev/video1 or similar depending on your environment, so check with ls /dev/video*.

Since a webcam already produces input in real time, -re is not included. The bitrate is held to 3000 kbps, suited to camera streaming.

On Windows, device input is specified with -f dshow; on macOS, with -f avfoundation. Note that how you look up device names and the format you specify differ from one OS to another.


Common Errors and Fixes

Operation not permitted / Connection Refused

This is when the connection to the server itself is refused. The two main causes are:

  • Wrong stream key: Re-copy the latest key accurately from the dashboard. Keys can be regenerated periodically.
  • Firewall / network blocking: Check that the RTMP send port (1935 by default) isn’t blocked by a firewall or network equipment.

Broken pipe

This is the error when the connection drops during streaming. It occurs on a momentary network interruption or when insufficient upload bandwidth prevents the server from receiving everything and it disconnects. Measure your effective upload bandwidth with a tool like iperf3 and confirm there’s enough headroom for your streaming bitrate (video + audio). If bandwidth is insufficient, lower -b:v.

Buffering Due to Excessive Bitrate

If your configured bitrate exceeds your connection’s or the platform’s ceiling, viewers experience frequent buffering and the broadcast becomes unstable. Lower -b:v and -maxrate to within the platform’s recommended values (4500–6000 kbps for YouTube 1080p, around 6000 kbps for Twitch), and set -bufsize to roughly twice the maxrate.

No Audio

If video is being streamed but there’s no audio, a missing audio codec specification is the typical cause. Explicitly specify audio encoding such as -c:a aac -b:a 128k. If you’re using -c copy, the source audio may be something other than AAC (such as Opus) that the platform doesn’t accept.

Slow Start Because the GOP Is Too Long

If you don’t specify -g, or the value is too large, it takes time for video to appear after a viewer opens the broadcast. This is because playback starts from a keyframe. Set a 2-second GOP with frame rate × 2 (30 fps → -g 60, 60 fps → -g 120).



Tested with: ffmpeg 6.1.1 / Ubuntu 24.04 (verified against real FFmpeg)
Primary sources: trac.ffmpeg.org/wiki/StreamingGuide / ffmpeg.org/ffmpeg-formats.html


FAQ

Is -re really necessary?

It is required when live streaming from a file as input. Without -re, FFmpeg reads the file far faster than real time and pushes out a video of several dozen seconds in an instant. Webcams and capture devices, on the other hand, produce input in real time to begin with, so -re is often unnecessary.

-c copy or re-encoding — which should I use?

If your source is already H.264/AAC and its resolution, bitrate, and GOP meet the platform’s requirements, -c copy is optimal. CPU load is nearly zero and there’s no quality degradation. If even one condition is off, re-encode with libx264.

What value should I use for the GOP (-g)?

The platform recommendation is a 2-second GOP. Calculate it as “frame rate × 2”: specify -g 60 for 30 fps and -g 120 for 60 fps. Too long, and starting playback and switching quality become slow.

What happens if my stream key leaks?

A third party can stream to your channel without permission. Treat it as secret information equivalent to a password, and don’t expose it on your broadcast screen or in screenshots. If it does leak, regenerate the stream key from each platform’s dashboard.