近期工作业务需要实现接收rtmp流媒体并保存到本地的功能。要实现这个功能,就得用到librtmp这个库,综合了网上看到的好几种方法并进行实际操作,成功地对rtmpdump进行了编译和使用,由于参考的方法叙述会较为简略,因此在这里详细记录编译和使用的过程,也希望能给大家提供帮助。
rtmpdump的编译
1.下载librtmp的源代码,我下的是rtmpdump-2.3
下载地址
2.下载zlib的源代码,我下的是1.2.11
下载地址
3.打开vs2019,创建一个静态库工程,该工程默认保存在C:\Users\xxx\source\repos目录下【这个目录因人而异,记住保存在什么地方就好】
4.打开Git Bash,在命令行中键入,名为rtmpdump的文件夹就会出现在C:\Users\xxx目录下。
git clone git://git.ffmpeg.org/rtmpdump
5.打开rtmpdump/librtmp文件夹,将所有的.h文件和.c文件复制到vs2019静态库工程librtmp所在的目录下。打开vs,分别把.h文件和.c文件载入到工程的头文件和源文件目录下。
以下是载入头文件的步骤,源文件同理。
由于没有下载openssl,所以需要在项目→属性→C/C++预处理器中,添加宏定义 NO_CRYPTO
6.此时编译会报错,是否忘记了向源文件添加“#include “pch.h””?
打开项目→属性→预编译头,选择不使用预编译头。
7.编译通过,但生成仍然有很多错误,接下来打开rtmp_sys.h
文件进行修改。
原来的代码:
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#ifdef _MSC_VER /* MSVC */
#define snprintf _snprintf
#define strcasecmp stricmp
#define strncasecmp strnicmp
#define vsnprintf _vsnprintf
#endif
#define GetSockError() WSAGetLastError()
#define SetSockError(e) WSASetLastError(e)
#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
#define EWOULDBLOCK WSAETIMEDOUT /* we don't use nonblocking, but we do use timeouts */
#define sleep(n) Sleep(n*1000)
#define msleep(n) Sleep(n)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
改动后的代码:
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
/*改动部分*/
#if defined(_MSC_VER) && (_MSC_VER < 1900) /* MSVC */
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#endif
#define strncasecmp strnicmp
#define strcasecmp stricmp
typedef __int64 off_t;
/*改动部分*/
#define GetSockError() WSAGetLastError()
#define SetSockError(e) WSASetLastError(e)
#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
#define EWOULDBLOCK WSAETIMEDOUT /* we don't use nonblocking, but we do use timeouts */
#define sleep(n) Sleep(n*1000)
#define msleep(n) Sleep(n)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
接着打开rtmp.c
文件,将下列语句注释掉
#ifdef _DEBUG
extern FILE *netstackdump;
extern FILE *netstackdump_read;
#endif
#ifdef _DEBUG
fwrite(ptr, 1, nBytes, netstackdump_read);
#endif
#ifdef _DEBUG
fwrite(buf, 1, len, netstackdump);
#endif
在项目→属性→C/C++预处理器→预处理定义中添加
_CRT_NONSTDC_NO_DEPRECATE
_CRT_SECURE_NO_WARNINGS
_WINSOCK_DEPRECATED_NO_WARNINGS
8.清理项目,重新生成,成功在Debug目录下得到静态库文件。
rtmpdump的使用
1.建立一个testlibrtmp控制台工程,根据使用的编程语言进行选择,这里我选用的是C++控制台应用。
2.将rtmp.h
、amf.h
文件添加到当前工程目录下,并添加到项目的头文件中。
3.将librtmp.lib
文件添加到当前工程目录下,打开项目→属性→配置属性→链接器→常规,在附加库目录中添加librtmp.lib所在的路径。
打开项目→属性→配置属性→链接器→输入,在附加依赖项中添加librtmp.lib
的文件名。
4.在控制台工程main函数所在的源文件中,添加以下代码。
注意!下面的语句一定要加上!!
#include <Winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#include "rtmp.h"
#pragma comment(lib,"librtmp.lib")
testlibrtmp.cpp中的完整代码:
#include <iostream>
#include <Winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#include "rtmp.h"
#pragma comment(lib,"librtmp.lib")
int InitSockets()
{
WORD version;
WSADATA wsaData;
version = MAKEWORD(1, 1);
return (WSAStartup(version, &wsaData) == 0);
}
void CleanupSockets()
{
WSACleanup();
}
int main()
{
InitSockets();
RTMP rtmp = { 0 };
RTMP_Init(&rtmp);
rtmp.Link.timeout = 25;//超时设置
//由于crtmpserver是每个一段时间(默认8s)发送数据包,需大于发送间隔才行
bool bLiveStream = true;//是否直播
if (bLiveStream)
{
const char* str = "rtmp://58.200.131.2:1935/livetv/startv";
RTMP_SetupURL(&rtmp, (char*)str);
//设置直播标志
rtmp.Link.lFlags |= RTMP_LF_LIVE;
}
else
{
const char* str = "rtmp://127.0.0.1:1935/vod/test.flv";
RTMP_SetupURL(&rtmp, (char*)str);
}
RTMP_SetBufferMS(&rtmp, 3600 * 1000);//1hour
if (!RTMP_Connect(&rtmp, NULL))
{
printf("Connect Server Err\n");
WSACleanup();
return -1;
}
if (!RTMP_ConnectStream(&rtmp, 0))
{
printf("Connect stream Err\n");
RTMP_Close(&rtmp);
WSACleanup();
return -1;
}
int buffsize = 1024 * 1024 * 10;
char* buff = (char*)malloc(buffsize);
double duration = -1;
int nRead;
FILE* fp = fopen("aaa.flv", "wb");
long countbuffsize = 0;
//它直接输出的就是FLV文件,包括FLV头,可对流按照flv格式解析就可提前音频,视频数据
while (nRead = RTMP_Read(&rtmp, buff, buffsize))
{
fwrite(buff, 1, nRead, fp);
if (!bLiveStream && duration < 0)
{
duration = RTMP_GetDuration(&rtmp);
printf("duration:%f\n", duration);
}
countbuffsize += nRead;
printf("\rdownland...:%0.2fkB", countbuffsize * 1.0 / 1024);
}
fclose(fp);
free(buff);
buff = NULL;
RTMP_Close(&rtmp);
WSACleanup();
return 0;
}
5.运行程序,会得到下载并录制下来的flv文件。
6.点击播放,音画正常,成功。
【参考出处】
librtmp在windows下的编译和使用
使用VS2008 在windows环境 编译Rtmpdump
rtmpdump在vs2015下的编译
VS引用第三方静态库的方法总结
Visual Studio 2017 项目中引用lib静态库
librtmp windows编译提示“无法解析的外部符号 _netstackdump”错误
“error C4996: ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead” 解决方法
【源码下载】
rtmpdump【包含编译librtmp.lib所需的所有头文件和源文件】
librtmp【包含编译好的librtmp.lib以及通过编译头文件和源文件】
testlibrtmp【包含用于测试将rtmp流媒体保存到本地的可执行文件】
注意:要正确使用以上的代码,一定要记得在vs的预处理器中添加上文提到的宏定义,否则将会报错。