强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

FFmpeg 多媒体处理教程 / 流媒体基础

流媒体基础

概述

流媒体(Streaming Media)是指将多媒体内容通过网络实时传输的技术。FFmpeg 支持多种流媒体协议,包括 RTMP、HLS、DASH、RTSP 等,可用于推流、拉流和实时转码。

流媒体协议概览

常见协议对比

协议全称传输方式延迟兼容性适用场景
RTMPReal-Time Messaging ProtocolTCP直播推流
HLSHTTP Live StreamingHTTP极好点播/直播
DASHDynamic Adaptive Streaming over HTTPHTTP点播/直播
RTSPReal-Time Streaming ProtocolTCP/UDP监控/视频会议
SRTSecure Reliable TransportUDP专业直播
WebRTCWeb Real-Time CommunicationUDP极低视频通话

协议选择建议

场景推荐协议原因
直播推流RTMP广泛支持,低延迟
直播观看HLS兼容性最好
点播服务HLS/DASH自适应码率
视频监控RTSP低延迟,双向通信
视频会议WebRTC超低延迟
专业制作SRT可靠传输

RTMP 推流

RTMP 基础

RTMP(Real-Time Messaging Protocol)是 Adobe 开发的协议,广泛用于直播推流。

基本推流命令

# 基本推流
ffmpeg -re -i input.mp4 -c:v libx264 -c:a aac -f flv rtmp://server/live/stream_key

# 使用硬件加速推流
ffmpeg -re -i input.mp4 -c:v h264_nvenc -c:a aac -f flv rtmp://server/live/stream_key

# 低延迟推流
ffmpeg -re -i input.mp4 \
    -c:v libx264 -preset ultrafast -tune zerolatency \
    -b:v 2M -maxrate 2M -bufsize 4M \
    -c:a aac -b:a 128k \
    -f flv rtmp://server/live/stream_key

RTMP 参数详解

参数说明推荐值
-re按原始帧率读取必需
-preset编码预设ultrafast/fast
-tune调优参数zerolatency
-b:v视频码率2-6M
-maxrate最大码率与 b:v 相同
-bufsize缓冲区大小2× maxrate

主流平台推流

Bilibili 推流:

ffmpeg -re -i input.mp4 \
    -c:v libx264 -preset fast -tune zerolatency \
    -b:v 3M -maxrate 3M -bufsize 6M \
    -c:a aac -b:a 128k \
    -f flv rtmp://live-push.bilivideo.com/live-bvc/?streamname=your_stream_key

YouTube 推流:

ffmpeg -re -i input.mp4 \
    -c:v libx264 -preset fast -tune zerolatency \
    -b:v 4M -maxrate 4M -bufsize 8M \
    -c:a aac -b:a 128k \
    -f flv rtmp://a.rtmp.youtube.com/live2/your_stream_key

Twitch 推流:

ffmpeg -re -i input.mp4 \
    -c:v libx264 -preset fast -tune zerolatency \
    -b:v 3M -maxrate 3M -bufsize 6M \
    -c:a aac -b:a 128k \
    -f flv rtmp://live-jfk.twitch.tv/app/your_stream_key

推流脚本

#!/bin/bash
# rtmp_push.sh

INPUT=$1
SERVER=$2
KEY=$3
BITRATE=${4:-3M}

ffmpeg -re -i "$INPUT" \
    -c:v libx264 -preset fast -tune zerolatency \
    -b:v "$BITRATE" -maxrate "$BITRATE" -bufsize $((${BITRATE%M}*2))M \
    -c:a aac -b:a 128k \
    -f flv "${SERVER}/${KEY}"

HLS 流媒体

HLS 基础

HLS(HTTP Live Streaming)是 Apple 开发的协议,通过 HTTP 传输,兼容性极好。

基本 HLS 命令

# 基本 HLS 分片
ffmpeg -i input.mp4 \
    -c:v libx264 -c:a aac \
    -f hls -hls_time 4 -hls_list_size 0 \
    -hls_segment_filename "segment_%03d.ts" \
    playlist.m3u8

# 带多个码率的 HLS
ffmpeg -i input.mp4 \
    -map 0:v -map 0:a -map 0:v -map 0:a -map 0:v -map 0:a \
    -c:v libx264 -c:a aac \
    -b:v:0 2M -b:v:1 1M -b:v:2 500k \
    -f hls \
    -hls_time 4 -hls_list_size 0 \
    -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2" \
    -master_pl_name master.m3u8 \
    "stream_%v/playlist.m3u8"

HLS 参数详解

参数说明推荐值
-hls_time分片时长(秒)2-10
-hls_list_size播放列表大小0(全部)
-hls_segment_filename分片文件名segment_%03d.ts
-hls_flagsHLS 选项delete_segments
-hls_wrap分片序号回绕不推荐使用
-hls_allow_cache允许缓存1

HLS 选项

选项说明
delete_segments删除旧分片
append_list追加到播放列表
round_durations圆整时长
discont_start不连续开始
omit_endlist省略 ENDLIST
split_by_time按时间分割
independent_segments独立分片

自适应码率 HLS

#!/bin/bash
# hls_adaptive.sh

INPUT=$1
OUTPUT_DIR=${2:-hls}

mkdir -p "$OUTPUT_DIR"

# 多码率 HLS
ffmpeg -i "$INPUT" \
    -map 0:v -map 0:a -map 0:v -map 0:a -map 0:v -map 0:a \
    -c:v libx264 -c:a aac \
    -b:v:0 5M -maxrate:v:0 5M -bufsize:v:0 10M \
    -b:v:1 2M -maxrate:v:1 2M -bufsize:v:1 4M \
    -b:v:2 800k -maxrate:v:2 800k -bufsize:v:2 1600k \
    -s:v:0 1920x1080 -s:v:1 1280x720 -s:v:2 640x360 \
    -f hls \
    -hls_time 4 \
    -hls_list_size 0 \
    -hls_segment_filename "$OUTPUT_DIR/stream_%v/segment_%03d.ts" \
    -var_stream_map "v:0,a:0,name:1080p v:1,a:1,name:720p v:2,a:2,name:360p" \
    -master_pl_name "$OUTPUT_DIR/master.m3u8" \
    "$OUTPUT_DIR/stream_%v/playlist.m3u8"

echo "HLS 生成完成: $OUTPUT_DIR/master.m3u8"

HLS 加密

# 生成密钥
openssl rand 16 > encryption.key

# 创建密钥信息文件
cat > encryption_key_info.txt << EOF
encryption.key
$(cat encryption.key | base64)
$(openssl rand -hex 16)
EOF

# 加密 HLS
ffmpeg -i input.mp4 \
    -c:v libx264 -c:a aac \
    -f hls -hls_time 4 -hls_list_size 0 \
    -hls_key_info_file encryption_key_info.txt \
    -hls_segment_filename "segment_%03d.ts" \
    encrypted.m3u8

DASH 流媒体

DASH 基础

DASH(Dynamic Adaptive Streaming over HTTP)是开放标准,支持自适应码率。

基本 DASH 命令

# 基本 DASH 分片
ffmpeg -i input.mp4 \
    -c:v libx264 -c:a aac \
    -f dash \
    -seg_duration 4 \
    -window_size 5 \
    -extra_window_size 10 \
    manifest.mpd

# 多码率 DASH
ffmpeg -i input.mp4 \
    -map 0:v -map 0:a -map 0:v -map 0:a \
    -c:v libx264 -c:a aac \
    -b:v:0 2M -b:v:1 1M \
    -f dash \
    -seg_duration 4 \
    -adaptation_sets "id=0,streams=v id=1,streams=a" \
    manifest.mpd

DASH 参数详解

参数说明推荐值
-seg_duration分片时长(秒)2-10
-window_size滑动窗口大小5
-extra_window_size额外窗口大小10
-remove_at_exit退出时删除1
-use_template使用模板1
-use_timeline使用时间线1
-adaptation_sets自适应集根据流配置

自适应码率 DASH

#!/bin/bash
# dash_adaptive.sh

INPUT=$1
OUTPUT_DIR=${2:-dash}

mkdir -p "$OUTPUT_DIR"

ffmpeg -i "$INPUT" \
    -map 0:v -map 0:a -map 0:v -map 0:a -map 0:v -map 0:a \
    -c:v libx264 -c:a aac \
    -b:v:0 5M -maxrate:v:0 5M -bufsize:v:0 10M \
    -b:v:1 2M -maxrate:v:1 2M -bufsize:v:1 4M \
    -b:v:2 800k -maxrate:v:2 800k -bufsize:v:2 1600k \
    -s:v:0 1920x1080 -s:v:1 1280x720 -s:v:2 640x360 \
    -f dash \
    -seg_duration 4 \
    -adaptation_sets "id=0,streams=v id=1,streams=a" \
    -window_size 5 \
    -remove_at_exit 1 \
    "$OUTPUT_DIR/manifest.mpd"

echo "DASH 生成完成: $OUTPUT_DIR/manifest.mpd"

RTSP 拉流

RTSP 基础

RTSP(Real-Time Streaming Protocol)常用于视频监控和实时通信。

基本拉流命令

# RTSP 拉流并保存
ffmpeg -i rtsp://camera_ip:554/stream -c copy output.mp4

# RTSP 拉流并转码
ffmpeg -i rtsp://camera_ip:554/stream \
    -c:v libx264 -preset fast -c:a aac \
    output.mp4

# RTSP 拉流并推流
ffmpeg -i rtsp://camera_ip:554/stream \
    -c:v libx264 -preset fast -tune zerolatency \
    -c:a aac \
    -f flv rtmp://server/live/stream

RTSP 选项

# 设置 RTSP 传输方式
ffmpeg -rtsp_transport tcp -i rtsp://camera_ip:554/stream output.mp4

# 设置超时
ffmpeg -timeout 5000000 -i rtsp://camera_ip:554/stream output.mp4

# 设置缓冲区
ffmpeg -buffer_size 1024000 -i rtsp://camera_ip:554/stream output.mp4

流媒体转码

实时转码推流

# 基本实时转码
ffmpeg -i rtmp://source/live/stream \
    -c:v libx264 -preset fast -tune zerolatency \
    -b:v 2M -maxrate 2M -bufsize 4M \
    -c:a aac -b:a 128k \
    -f flv rtmp://target/live/stream

# 多码率转码
ffmpeg -i rtmp://source/live/stream \
    -map 0:v -map 0:a -map 0:v -map 0:a \
    -c:v libx264 -preset fast -tune zerolatency \
    -c:a aac \
    -b:v:0 4M -s:v:0 1920x1080 \
    -b:v:1 2M -s:v:1 1280x720 \
    -f tee \
    "[f=flv]rtmp://target/live/stream_1080p|[f=flv]rtmp://target/live/stream_720p"

转码脚本

#!/bin/bash
# transcode_stream.sh

SOURCE=$1
TARGET=$2
BITRATE=${3:-2M}

ffmpeg -i "$SOURCE" \
    -c:v libx264 -preset fast -tune zerolatency \
    -b:v "$BITRATE" -maxrate "$BITRATE" -bufsize $((${BITRATE%M}*2))M \
    -c:a aac -b:a 128k \
    -f flv "$TARGET"

流媒体录制

直播录制

# 录制直播流
ffmpeg -i rtmp://server/live/stream -c copy output.mp4

# 录制并转码
ffmpeg -i rtmp://server/live/stream \
    -c:v libx264 -crf 23 -c:a aac \
    output.mp4

# 分段录制
ffmpeg -i rtmp://server/live/stream \
    -c copy \
    -f segment \
    -segment_time 3600 \
    -segment_format mp4 \
    -strftime 1 \
    "recording_%Y%m%d_%H%M%S.mp4"

HLS 录制

# 录制 HLS 流
ffmpeg -i https://example.com/live/playlist.m3u8 -c copy output.mp4

# 录制 HLS 分片
ffmpeg -i https://example.com/live/playlist.m3u8 \
    -c copy \
    -f segment \
    -segment_time 60 \
    "segment_%03d.ts"

流媒体服务器

使用 FFmpeg 搭建简单服务器

# 接收 RTMP 推流并转为 HLS
ffmpeg -listen 1 -i rtmp://0.0.0.0:1935/live/stream \
    -c:v libx264 -c:a aac \
    -f hls -hls_time 4 -hls_list_size 10 \
    /var/www/html/live/stream.m3u8

# 接收 RTSP 流并转为 RTMP
ffmpeg -rtsp_transport tcp -i rtsp://camera_ip:554/stream \
    -c:v libx264 -preset fast -tune zerolatency \
    -c:a aac \
    -f flv rtmp://localhost/live/camera

使用 tee 多路输出

# 同时输出到多个目标
ffmpeg -i input.mp4 \
    -c:v libx264 -c:a aac \
    -f tee \
    "[f=flv]rtmp://server1/live/stream1|[f=mp4]output.mp4"

流媒体监控

流信息检测

# 检测 RTMP 流信息
ffprobe -v quiet -print_format json -show_streams rtmp://server/live/stream

# 检测 HLS 流信息
ffprobe -v quiet -print_format json -show_streams https://example.com/live/playlist.m3u8

# 检测 RTSP 流信息
ffprobe -v quiet -print_format json -show_streams rtsp://camera_ip:554/stream

流健康检查脚本

#!/bin/bash
# stream_health_check.sh

STREAM_URL=$1

# 获取流信息
INFO=$(ffprobe -v quiet -print_format json -show_streams "$STREAM_URL" 2>/dev/null)

if [ $? -ne 0 ]; then
    echo "ERROR: 无法连接流"
    exit 1
fi

# 检查视频流
VIDEO_CODEC=$(echo "$INFO" | jq -r '.streams[] | select(.codec_type=="video") | .codec_name')
VIDEO_WIDTH=$(echo "$INFO" | jq -r '.streams[] | select(.codec_type=="video") | .width')
VIDEO_HEIGHT=$(echo "$INFO" | jq -r '.streams[] | select(.codec_type=="video") | .height')
VIDEO_FPS=$(echo "$INFO" | jq -r '.streams[] | select(.codec_type=="video") | .r_frame_rate')

# 检查音频流
AUDIO_CODEC=$(echo "$INFO" | jq -r '.streams[] | select(.codec_type=="audio") | .codec_name')
AUDIO_SAMPLE_RATE=$(echo "$INFO" | jq -r '.streams[] | select(.codec_type=="audio") | .sample_rate')

echo "=== 流健康状态 ==="
echo "视频: $VIDEO_CODEC ${VIDEO_WIDTH}x${VIDEO_HEIGHT} @ ${VIDEO_FPS}fps"
echo "音频: $AUDIO_CODEC ${AUDIO_SAMPLE_RATE}Hz"
echo "状态: OK"

流媒体最佳实践

推流配置建议

场景分辨率帧率视频码率音频码率
游戏直播1080p60fps6M192k
聊天直播720p30fps2M128k
户外直播720p30fps3M128k
语音直播480p30fps1M128k

HLS 配置建议

参数推荐值说明
hls_time2-6 秒越短延迟越低
hls_list_size0 或 100 表示全部
分片格式TS兼容性最好
编码H.264 + AAC广泛支持

DASH 配置建议

参数推荐值说明
seg_duration2-6 秒越短延迟越低
window_size5滑动窗口
编码H.264 + AAC广泛支持

注意事项

  1. 网络带宽:确保上行带宽足够,建议至少为目标码率的 1.5 倍
  2. 编码延迟:使用 -preset ultrafast -tune zerolatency 降低延迟
  3. 缓冲区设置-bufsize 通常设为 -maxrate 的 2 倍
  4. 分片时长:HLS/DASH 分片时长影响延迟和兼容性
  5. 协议选择:根据使用场景选择合适的协议

业务场景

场景 1:多平台同时推流

#!/bin/bash
# multi_platform_push.sh

INPUT=$1

# 使用 tee 同时推流到多个平台
ffmpeg -re -i "$INPUT" \
    -c:v libx264 -preset fast -tune zerolatency \
    -b:v 3M -maxrate 3M -bufsize 6M \
    -c:a aac -b:a 128k \
    -f tee \
    "[f=flv]rtmp://live.bilibili.com/stream1|[f=flv]rtmp://live.twitch.tv/app/key2|[f=flv]rtmp://a.rtmp.youtube.com/live2/key3"

场景 2:监控摄像头转直播

#!/bin/bash
# camera_to_live.sh

CAMERA_RTSP=$1
RTMP_SERVER=$2

while true; do
    ffmpeg -rtsp_transport tcp -i "$CAMERA_RTSP" \
        -c:v libx264 -preset fast -tune zerolatency \
        -b:v 2M -maxrate 2M -bufsize 4M \
        -c:a aac -b:a 128k \
        -f flv "$RTMP_SERVER"
    
    echo "流断开,5 秒后重连..."
    sleep 5
done

场景 3:直播录制回放

#!/bin/bash
# live_record_replay.sh

RTMP_URL=$1
OUTPUT_DIR=${2:-recordings}

mkdir -p "$OUTPUT_DIR"

# 录制
ffmpeg -i "$RTMP_URL" \
    -c copy \
    -f segment \
    -segment_time 3600 \
    -segment_format mp4 \
    -strftime 1 \
    "$OUTPUT_DIR/live_%Y%m%d_%H%M%S.mp4"

扩展阅读

  1. HLS 规范
  2. DASH 规范
  3. RTMP 规范
  4. SRT 协议
  5. WebRTC 规范

总结

本章介绍了 FFmpeg 的流媒体功能,包括:

  • 流媒体协议概览
  • RTMP 推流
  • HLS 和 DASH 分片
  • RTSP 拉流
  • 流媒体转码和录制

掌握这些功能可以帮助您构建流媒体应用。