FFmpeg开发 Windows环境集成libsrt完整指南
概览流程
环境准备 → SRT库安装 → FFmpeg编译 → SRT支持 → 验证测试 → 开发集成
环境准备
安装MSYS2环境
# 1. 下载并安装MSYS2
# 访问 https://www.msys2.org/ 下载安装包
# 安装完成后运行 MSYS2 UCRT64
# 2. 更新系统包
pacman -Syu
pacman -Su
# 3. 安装编译工具链
pacman -S mingw-w64-ucrt-x86_64-toolchain
pacman -S mingw-w64-ucrt-x86_64-pkg-config
pacman -S make
pacman -S mingw-w64-ucrt-x86_64-yasm
pacman -S mingw-w64-ucrt-x86_64-nasm
pacman -S git
pacman -S mingw-w64-ucrt-x86_64-cmake
pacman -S mingw-w64-ucrt-x86_64-python
创建工作目录
# 在MSYS2环境中创建目录
mkdir -p /c/ffmpeg_dev/{sources,build,output}
cd /c/ffmpeg_dev
SRT库安装
方法一:使用MSYS2包管理器安装
# 安装SRT开发包
pacman -S mingw-w64-ucrt-x86_64-srt
# 安装SSL依赖(SRT需要)
pacman -S mingw-w64-ucrt-x86_64-openssl
# 验证安装
pacman -Q mingw-w64-ucrt-x86_64-srt
方法二:手动编译SRT库
# 下载SRT源码
cd /c/ffmpeg_dev/sources
# 克隆SRT源码
git clone https://github.com/Haivision/srt.git
cd srt
# 创建构建目录
mkdir -p build
cd build
# 配置CMake
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/c/ffmpeg_dev/build/srt \
-DENABLE_SHARED=OFF \
-DENABLE_STATIC=ON \
-DENABLE_APPS=OFF \
-DUSE_ENCLIB=openssl \
-DCMAKE_TOOLCHAIN_FILE=/ucrt64/share/cmake/toolchain-x86_64-w64-mingw32.cmake \
-DOPENSSL_ROOT_DIR=/ucrt64 \
-DOPENSSL_INCLUDE_DIR=/ucrt64/include
# 编译和安装
make -j$(nproc)
make install
方法三:使用预编译的SRT库
# 如果有预编译的SRT库文件,直接复制到指定目录
mkdir -p /c/ffmpeg_dev/build/srt/{include,lib}
# 复制头文件和库文件(示例路径)
# cp /path/to/srt/include/*.h /c/ffmpeg_dev/build/srt/include/
# cp /path/to/srt/lib/*.lib /c/ffmpeg_dev/build/srt/lib/
# cp /path/to/srt/lib/*.dll /c/ffmpeg_dev/build/srt/lib/
FFmpeg源码编译
下载FFmpeg源码
# 进入源码目录
cd /c/ffmpeg_dev/sources
# 克隆FFmpeg源码
if [ ! -d "ffmpeg" ]; then
git clone https://git.ffmpeg.org/ffmpeg.git
fi
cd ffmpeg
配置FFmpeg(启用libsrt支持)
# 配置FFmpeg编译选项
./configure \
--prefix=/c/ffmpeg_dev/output \
--enable-shared \
--enable-static \
--enable-gpl \
--enable-nonfree \
--enable-version3 \
--enable-runtime-cpudetect \
--enable-postproc \
--enable-avfilter \
--enable-pthreads \
--enable-network \
--enable-openssl \
--enable-libsrt \
--enable-protocol=srt,file,http,https,rtmp \
--enable-demuxer=srt,mpegts,h264,hevc \
--enable-muxer=mpegts \
--enable-parser=h264,hevc \
--arch=x86_64 \
--target-os=mingw32 \
--cross-prefix=x86_64-w64-mingw32- \
--extra-cflags="-I/c/ffmpeg_dev/build/srt/include -I/ucrt64/include" \
--extra-ldflags="-L/c/ffmpeg_dev/build/srt/lib -L/ucrt64/lib" \
--extra-libs="-lsrt -lssl -lcrypto -lws2_32 -lwsock32"
编译和安装
# 清理之前的构建
make clean
# 并行编译
make -j$(nproc)
# 安装到指定目录
make install
使用vcpkg编译(推荐方法)
安装vcpkg
# 在Windows命令提示符中执行
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
bootstrap-vcpkg.bat
使用vcpkg安装FFmpeg
# 安装带有libsrt支持的FFmpeg
vcpkg install ffmpeg[core,srt]:x64-windows
# 或者安装更多功能
vcpkg install ffmpeg[core,srt,openssl]:x64-windows
集成到Visual Studio
# 集成到系统
vcpkg integrate install
完整构建脚本
# 创建完整构建脚本
cat > build_ffmpeg_windows_srt.sh << 'EOF'
#!/bin/bash
# 设置环境变量
WORK_DIR=/c/ffmpeg_dev
SOURCES_DIR=$WORK_DIR/sources
BUILD_DIR=$WORK_DIR/build
OUTPUT_DIR=$WORK_DIR/output
# 创建目录结构
mkdir -p $SOURCES_DIR $BUILD_DIR $OUTPUT_DIR
echo "开始FFmpeg libsrt集成编译..."
# 安装依赖包
echo "安装依赖库..."
pacman -Syu --noconfirm
pacman -S --noconfirm \
mingw-w64-ucrt-x86_64-toolchain \
mingw-w64-ucrt-x86_64-pkg-config \
make \
mingw-w64-ucrt-x86_64-yasm \
mingw-w64-ucrt-x86_64-nasm \
git \
mingw-w64-ucrt-x86_64-cmake \
mingw-w64-ucrt-x86_64-srt \
mingw-w64-ucrt-x86_64-openssl
# 下载FFmpeg源码
cd $SOURCES_DIR
if [ ! -d "ffmpeg" ]; then
git clone https://git.ffmpeg.org/ffmpeg.git
fi
cd ffmpeg
# 配置FFmpeg
echo "配置FFmpeg..."
./configure \
--prefix=$OUTPUT_DIR \
--enable-shared \
--enable-static \
--enable-gpl \
--enable-nonfree \
--enable-version3 \
--enable-runtime-cpudetect \
--enable-postproc \
--enable-avfilter \
--enable-pthreads \
--enable-network \
--enable-openssl \
--enable-libsrt \
--enable-protocol=srt,file,http,https,rtmp,tcp,udp \
--enable-demuxer=srt,mpegts,h264,hevc,mp4,mov \
--enable-muxer=mpegts,mp4 \
--enable-parser=h264,hevc,aac \
--arch=x86_64 \
--target-os=mingw32 \
--cross-prefix=x86_64-w64-mingw32- \
--extra-libs="-lws2_32 -lwsock32"
# 编译和安装
echo "编译FFmpeg..."
make clean
make -j$(nproc)
make install
echo "FFmpeg编译完成!"
echo "输出目录: $OUTPUT_DIR"
echo "可执行文件: $OUTPUT_DIR/bin/ffmpeg.exe"
EOF
chmod +x build_ffmpeg_windows_srt.sh
验证安装
功能验证脚本
# 创建验证脚本
cat > verify_ffmpeg_srt.sh << 'EOF'
#!/bin/bash
OUTPUT_DIR=/c/ffmpeg_dev/output
FFMPEG_EXE=$OUTPUT_DIR/bin/ffmpeg.exe
echo "验证FFmpeg libsrt功能支持"
# 检查FFmpeg是否可执行
if [ ! -f "$FFMPEG_EXE" ]; then
echo "错误: FFmpeg未找到"
exit 1
fi
echo "FFmpeg可执行文件存在"
# 检查SRT支持
echo "检查SRT支持..."
$FFMPEG_EXE -protocols | grep srt > /dev/null && echo "✓ SRT协议支持正常" || echo "✗ SRT协议支持异常"
$FFMPEG_EXE -demuxers | grep srt > /dev/null && echo "✓ SRT解复用器支持正常" || echo "✗ SRT解复用器支持异常"
# 显示版本信息
echo "FFmpeg版本信息:"
$FFMPEG_EXE -version | head -5
# 显示编译配置
echo "SRT编译配置:"
$FFMPEG_EXE -buildconf | grep -i srt
echo "验证完成"
EOF
chmod +x verify_ffmpeg_srt.sh
测试SRT功能
# SRT接收测试(服务器模式)
test_srt_receiver() {
echo "测试SRT接收功能..."
# 启动SRT接收器(在后台)
/c/ffmpeg_dev/output/bin/ffmpeg.exe \
-i "srt://:9998?mode=listener" \
-c copy \
-f null - &
SRT_PID=$!
sleep 2
if kill -0 $SRT_PID 2>/dev/null; then
echo "SRT接收器启动成功"
# 停止接收器
kill $SRT_PID
wait $SRT_PID 2>/dev/null
else
echo "SRT接收器启动失败"
fi
}
# SRT发送测试(客户端模式)
test_srt_sender() {
echo "测试SRT发送功能..."
# 创建测试视频
/c/ffmpeg_dev/output/bin/ffmpeg.exe \
-f lavfi -i testsrc=duration=10:size=1280x720:rate=30 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-f mpegts "srt://127.0.0.1:9999?mode=caller" &
SENDER_PID=$!
sleep 2
if kill -0 $SENDER_PID 2>/dev/null; then
echo "SRT发送器启动成功"
# 停止发送器
kill $SENDER_PID
wait $SENDER_PID 2>/dev/null
else
echo "SRT发送器启动失败"
fi
}
# SRT回环测试
test_srt_loopback() {
echo "测试SRT回环功能..."
# 启动SRT服务器
/c/ffmpeg_dev/output/bin/ffmpeg.exe \
-i "srt://:9999?mode=listener&latency=120" \
-c copy \
-f mpegts test_output.ts &
SERVER_PID=$!
sleep 2
# 发送测试流
/c/ffmpeg_dev/output/bin/ffmpeg.exe \
-f lavfi -i testsrc=duration=5:size=1280x720:rate=25 \
-c:v libx264 -preset ultrafast -b:v 1000k \
-f mpegts "srt://127.0.0.1:9999?mode=caller" &
CLIENT_PID=$!
# 等待完成
wait $CLIENT_PID
kill $SERVER_PID 2>/dev/null
wait $SERVER_PID 2>/dev/null
if [ -f "test_output.ts" ]; then
echo "SRT回环测试成功"
ls -lh test_output.ts
rm test_output.ts
else
echo "SRT回环测试失败"
fi
}
Visual Studio开发集成
项目配置
// 在Visual Studio项目属性中设置:
// 包含目录:
// C:\vcpkg\installed\x64-windows\include
// 或
// C:\ffmpeg_dev\output\include
// C:\msys64\ucrt64\include
// 库目录:
// C:\vcpkg\installed\x64-windows\lib
// 或
// C:\ffmpeg_dev\output\lib
// C:\msys64\ucrt64\lib
// 附加依赖项:
// avformat.lib
// avcodec.lib
// avutil.lib
// swscale.lib
// swresample.lib
// avfilter.lib
// srt.lib
// ssl.lib
// crypto.lib
// ws2_32.lib
// wsock32.lib
CMake配置
# CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(FFmpegSRTTest)
set(CMAKE_CXX_STANDARD 17)
# 如果使用vcpkg
# set(FFMPEG_ROOT "C:/vcpkg/installed/x64-windows")
# 如果使用自编译版本
set(FFMPEG_ROOT "C:/ffmpeg_dev/output")
set(MSYS2_ROOT "C:/msys64/ucrt64")
# 包含目录
include_directories(
${FFMPEG_ROOT}/include
${MSYS2_ROOT}/include
)
# 库目录
link_directories(
${FFMPEG_ROOT}/lib
${MSYS2_ROOT}/lib
)
# 源文件
add_executable(${PROJECT_NAME} main.cpp)
# 链接库
target_link_libraries(${PROJECT_NAME}
avformat
avcodec
avutil
swscale
swresample
avfilter
srt
ssl
crypto
ws2_32
wsock32
)
# 复制DLL文件到输出目录
file(GLOB FFMPEG_DLLS "${FFMPEG_ROOT}/bin/*.dll")
file(GLOB MSYS2_DLLS "${MSYS2_ROOT}/bin/*.dll")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${FFMPEG_DLLS}
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${MSYS2_DLLS}
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
SRT处理示例代码
// srt_example.cpp - SRT处理示例
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
}
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
class SRTProcessor {
private:
AVFormatContext* format_ctx;
public:
SRTProcessor() : format_ctx(nullptr) {}
~SRTProcessor() {
cleanup();
}
bool checkSRTSupport() {
std::cout << "检查SRT支持..." << std::endl;
// 检查SRT协议支持
const AVInputFormat* srt_protocol = av_find_input_format("srt");
if (srt_protocol) {
std::cout << "SRT协议支持: " << srt_protocol->name << std::endl;
} else {
std::cout << "SRT协议不支持" << std::endl;
}
// 检查SRT解复用器
const AVInputFormat* srt_demuxer = av_find_input_format("srt");
if (srt_demuxer) {
std::cout << "SRT解复用器: " << srt_demuxer->name << std::endl;
} else {
std::cout << "SRT解复用器不支持" << std::endl;
}
// 列出支持的协议
std::cout << "支持的协议:" << std::endl;
void* opaque = nullptr;
const AVInputFormat* ifmt = nullptr;
while ((ifmt = av_demuxer_iterate(&opaque))) {
if (ifmt->name && strstr(ifmt->name, "srt")) {
std::cout << " " << ifmt->name << std::endl;
}
}
return (srt_protocol != nullptr);
}
bool openSRTStream(const std::string& srt_url) {
std::cout << "打开SRT流: " << srt_url << std::endl;
// 分配格式上下文
format_ctx = avformat_alloc_context();
if (!format_ctx) {
std::cerr << "无法分配格式上下文" << std::endl;
return false;
}
// 打开输入流
AVDictionary* options = nullptr;
// 设置SRT选项
av_dict_set(&options, "timeout", "3000000", 0); // 3秒超时
av_dict_set(&options, "latency", "120", 0); // 120ms延迟
int ret = avformat_open_input(&format_ctx, srt_url.c_str(), NULL, &options);
if (ret < 0) {
std::cerr << "无法打开SRT流: " << srt_url << std::endl;
av_dict_free(&options);
return false;
}
// 获取流信息
ret = avformat_find_stream_info(format_ctx, NULL);
if (ret < 0) {
std::cerr << "无法获取流信息" << std::endl;
av_dict_free(&options);
return false;
}
std::cout << "成功打开SRT流" << std::endl;
av_dict_free(&options);
return true;
}
void printStreamInfo() {
if (!format_ctx) return;
std::cout << "流信息:" << std::endl;
std::cout << " 格式: " << format_ctx->iformat->name << std::endl;
std::cout << " 流数: " << format_ctx->nb_streams << std::endl;
for (unsigned int i = 0; i < format_ctx->nb_streams; i++) {
AVStream* stream = format_ctx->streams[i];
if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
std::cout << " 视频流 " << i << ":" << std::endl;
std::cout << " 编解码器: " << avcodec_get_name(stream->codecpar->codec_id) << std::endl;
std::cout << " 分辨率: " << stream->codecpar->width << "x" << stream->codecpar->height << std::endl;
std::cout << " 帧率: " << av_q2d(stream->avg_frame_rate) << " fps" << std::endl;
} else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
std::cout << " 音频流 " << i << ":" << std::endl;
std::cout << " 编解码器: " << avcodec_get_name(stream->codecpar->codec_id) << std::endl;
std::cout << " 采样率: " << stream->codecpar->sample_rate << " Hz" << std::endl;
std::cout << " 声道数: " << stream->codecpar->channels << std::endl;
}
}
}
bool createSRTServer(const std::string& listen_url) {
std::cout << "创建SRT服务器: " << listen_url << std::endl;
AVFormatContext* ofmt_ctx = nullptr;
AVOutputFormat* ofmt = nullptr;
// 分配输出格式上下文
avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", nullptr);
if (!ofmt_ctx) {
std::cerr << "无法创建输出格式上下文" << std::endl;
return false;
}
ofmt = ofmt_ctx->oformat;
// 设置SRT选项
AVDictionary* options = nullptr;
av_dict_set(&options, "mode", "listener", 0);
av_dict_set(&options, "latency", "120", 0);
// 打开输出URL
int ret = avio_open2(&ofmt_ctx->pb, listen_url.c_str(), AVIO_FLAG_WRITE, nullptr, &options);
if (ret < 0) {
std::cerr << "无法打开SRT输出URL" << std::endl;
av_dict_free(&options);
avformat_free_context(ofmt_ctx);
return false;
}
std::cout << "SRT服务器创建成功" << std::endl;
// 清理
avio_closep(&ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
av_dict_free(&options);
return true;
}
void cleanup() {
if (format_ctx) {
avformat_close_input(&format_ctx);
format_ctx = nullptr;
}
}
};
int main() {
std::cout << "FFmpeg SRT处理示例" << std::endl;
SRTProcessor processor;
// 检查SRT支持
if (!processor.checkSRTSupport()) {
std::cout << "SRT支持检查失败" << std::endl;
return -1;
}
// 测试SRT服务器创建
std::string listen_url = "srt://:9998?mode=listener";
if (processor.createSRTServer(listen_url)) {
std::cout << "SRT服务器创建测试成功" << std::endl;
} else {
std::cout << "SRT服务器创建测试失败" << std::endl;
}
std::cout << "SRT支持测试完成" << std::endl;
return 0;
}
SRT使用示例
命令行示例
# SRT服务器模式(监听)
ffmpeg.exe -i "srt://:9998?mode=listener&latency=120" -c copy output.mp4
# SERT客户端模式(呼叫)
ffmpeg.exe -i "srt://192.168.1.100:9998?mode=caller" -c copy output.mp4
# SRT广播模式
ffmpeg.exe -i input.mp4 -c copy -f mpegts "srt://:9999?mode=listener&transtype=live"
# SRT推流
ffmpeg.exe -f lavfi -i testsrc=duration=30:size=1280x720:rate=30 \
-c:v libx264 -preset ultrafast -b:v 2000k \
-f mpegts "srt://127.0.0.1:9998?mode=caller&latency=120"
SRT参数说明
# SRT URL参数说明:
# mode=listener # 服务器模式,等待连接
# mode=caller # 客户端模式,主动连接
# mode=rendezvous # 对等模式,双方同时连接
# latency=120 # 延迟设置,单位ms
# passphrase=xxx # 加密密码
# pbkeylen=16 # 加密密钥长度 (16,24,32)
# transtype=live # 传输类型 (live,file)
# maxbw=1000000 # 最大带宽限制
# timeout=3000000 # 超时设置,单位微秒
环境变量配置
# 在Windows系统环境变量中添加:
# 系统PATH变量添加:
C:\ffmpeg_dev\output\bin
C:\msys64\ucrt64\bin
# 或如果使用vcpkg:
C:\vcpkg\installed\x64-windows\bin
# 创建批处理文件设置环境
@echo off
set PATH=C:\ffmpeg_dev\output\bin;C:\msys64\ucrt64\bin;%PATH%
set FFmpeg_HOME=C:\ffmpeg_dev\output
echo 环境变量已设置
常见问题解决
1. SRT库缺失
# 检查SRT库是否存在
ls /c/ffmpeg_dev/build/srt/lib/
ls /ucrt64/lib/ | grep srt
# 如果使用MSYS2包,检查安装
pacman -Q mingw-w64-ucrt-x86_64-srt
2. SSL依赖问题
# 检查SSL库
ls /ucrt64/lib/ | grep ssl
ls /ucrt64/lib/ | grep crypto
# 安装SSL依赖
pacman -S mingw-w64-ucrt-x86_64-openssl
3. 编译时链接错误
# 检查库文件
file /ucrt64/lib/libsrt.a
file /ucrt64/lib/libssl.a
# 确保包含正确的Windows网络库
# -lws2_32 -lwsock32
4. 运行时DLL错误
# 复制必要的DLL文件
copy C:\ffmpeg_dev\output\bin\*.dll .\
copy C:\msys64\ucrt64\bin\*.dll .\
copy C:\msys64\ucrt64\bin\libsrt-1.dll .\
copy C:\msys64\ucrt64\bin\libssl-1_1.dll .\
copy C:\msys64\ucrt64\bin\libcrypto-1_1.dll .\
5. 协议不支持
# 检查FFmpeg编译配置
/c/ffmpeg_dev/output/bin/ffmpeg.exe -buildconf | grep -i srt
/c/ffmpeg_dev/output/bin/ffmpeg.exe -protocols | grep srt
# 如果显示disable,则需要重新编译
6. 网络权限问题
# Windows防火墙设置
# 确保端口9998,9999等开放
# 以管理员权限运行程序
性能优化建议
编译优化选项
# 性能优化编译配置
./configure \
--prefix=/c/ffmpeg_dev/output \
--enable-shared \
--enable-static \
--enable-optimizations \
--disable-debug \
--enable-stripping \
--enable-small \
--extra-cflags="-O3 -ffast-math -march=native" \
--extra-ldflags="-s" \
--enable-libsrt \
--enable-openssl \
# 其他配置选项
SRT性能参数优化
# FFmpeg SRT优化参数
ffmpeg.exe -i input.mp4 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-c:a aac -b:a 128k \
-f mpegts "srt://127.0.0.1:9998?mode=caller&latency=100&transtype=live"
运行时优化
# 设置环境变量优化性能
set FFmpeg_THREADS=0 # 自动检测CPU核心数
SRT应用场景
实时流媒体传输
# 低延迟直播推流
ffmpeg.exe -f dshow -i video="摄像头" \
-c:v libx264 -preset ultrafast -tune zerolatency -b:v 2000k \
-c:a aac -b:a 128k \
-f mpegts "srt://server_ip:9998?mode=caller&latency=50"
# 接收端播放
ffplay.exe "srt://:9998?mode=listener"
点对点传输
# 发送端
ffmpeg.exe -i input.mp4 -c copy -f mpegts \
"srt://receiver_ip:9999?mode=rendezvous"
# 接收端
ffmpeg.exe -i "srt://sender_ip:9999?mode=rendezvous" -c copy output.mp4
完成这些配置后,你就可以在Windows环境下使用带有完整libsrt支持的FFmpeg进行开发了。推荐使用vcpkg方法,因为它最简单且维护性最好。