ffmpeg把RTSP流分段录制成MP4,如果能把ffmpeg.exe改成ffmpeg.dll用,那音视频开发的难度直接就降一个维度啊

news/2024/7/10 19:27:15 标签: ffmpeg, EasyAVFilter, RTSP转MP4, RTSP转RTMP, RTSP转HLS

比如,原来我们要用ffmpeg录一段RTSP视频流转成MP4,我们有两种方案:

方案一:可以使用以下命令将rtsp流分段存储为mp4文件

ffmpeg -i rtsp://example.com/stream -vcodec copy -acodec aac -f segment -segment_time 3600 -reset_timestamps 1 -strftime 1 output_%Y-%m-%d_%H-%M-%S.mp4

<a class=ffmpeg将RTSP录像成mp4" />

方案二:可以直接调用ffmpeg库avcodec、avfilter代码,有门槛,要研究,用大模型生成一段代码看看:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <time.h>

extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
}

int main(int argc, char **argv) {
    AVFormatContext *pFormatCtx = NULL;
    int videoStream;
    AVCodecContext *pCodecCtx = NULL;
    AVCodec *pCodec = NULL;
    AVPacket packet;
    FILE *videoFile = NULL;
    struct SwsContext *img_convert_ctx;
    int64_t start_time, end_time, duration;
    double framerate = 25.0; // 帧率,需要根据实际情况调整
    int i, ret, got_output;
    uint8_t *outbuf[1024]; // 输出缓冲区大小,需要根据实际情况调整
    int outbuf_size; // 输出缓冲区大小,需要根据实际情况调整
    start_time = (int64_t)time(NULL); // 开始时间,单位为秒
    videoFile = fopen("output.ts", "wb"); // 输出文件名,需要根据实际情况调整
    if (!videoFile) {
        printf("Could not open output file for writing
");
        return -1;
    }
    outbuf_size = av_image_get_buffer_size((AVPixelFormat)AV_PIX_FMT_YUV420P, videoStream, 1920, 1080, 1); // 获取输出缓冲区大小,需要根据实际情况调整
    outbuf = (uint8_t*)av_malloc(outbuf_size); // 分配输出缓冲区,需要根据实际情况调整
    ret = avformat_new_stream(&pFormatCtx, NULL); // 创建视频流上下文,需要根据实际情况调整
    if (ret < 0) {
        printf("Error: could not create output format context
");
        exit(1);
    } else {
        ret = avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar); // 设置解码器参数,需要根据实际情况调整
        if (ret < 0) {
            printf("Error: could not initialize the codec context
");
            exit(1);
        } else {
            ret = avcodec_open2(pCodecCtx, pCodec, NULL); // 打开解码器,需要根据实际情况调整
            if (ret < 0) {
                printf("Error: Could not open codec
");
                exit(1);
            } else {
                while (1) { // 循环处理视频流数据,需要根据实际情况调整
                    ret = av_read_frame(pFormatCtx, &packet); // 读取视频帧数据,需要根据实际情况调整
                    if (ret == 0) { // 如果读取到数据包,则进行处理,需要根据实际情况调整
                        // ... 在这里添加你的代码来处理视频帧数据 ...
                    } else if (ret < 0 && ret != AVERROR(EAGAIN)) { // 如果发生错误,则打印错误信息并退出程序,需要根据实际情况调整
                        char errorbuf[1024];
                        av_strerror(ret, errorbuf, sizeof(errorbuf));
                        printf("%s
", errorbuf);
                        exit(1);
                    } else if (ret == AVERROR(EAGAIN)) { // 如果发生EAGAIN错误,则等待一段时间后继续读取数据包,需要根据实际情况调整
                        usleep(200000); // 等待200ms,单位为微秒,需要根据实际情况调整
                    } else if (ret == AVERROR_EOF) { // 如果发生EOF错误,则表示已经读取完所有数据包,需要根据实际情况调整
                        break; // 结束循环,需要根据实际情况调整
                    } else if (ret < 0 && ret != AVERROR(EAGAIN)) { // 如果发生其他错误,则打印错误信息并退出程序,需要根据实际情况调整
                        char errorbuf[1024];
                        av_strerror(ret, errorbuf, sizeof(errorbuf));
                        printf("%s
", errorbuf);
                        exit(1);
                    } else if (ret >= 0) { // 如果成功读取到数据包,则进行处理,需要根据实际情况调整
                        // ... 在这里添加你的代码来处理视频帧数据 ...
                    } else { // 如果发生未知错误,则打印错误信息并退出程序,需要根据实际情况调整
                        char errorbuf[1024];
                        av_strerror(ret, errorbuf, sizeof(errorbuf));
                        printf("%s
", errorbuf);
                        exit(1);
                    }
                } // while循环结束条件 ... 在这里添加你的代码 ... } } } } /* end of main() */
  • 方案一通过exec调用,但是有一个弊端就是不好控制,不能自动重连,进程管理需要不断自己维护;
  • 方案二就是开发成本较高,太复杂了,不同级别的开发写出来的效果参差不齐;

有没有一个能把方案一和方案二结合起来的方法?

有,他来了:EasyAVFilter!简单的几个接口,就能解决ffmpeg开发门槛的问题:

方法名称说明
EasyAVFilter_Create创建句柄,相当于创建了一个ffmpeg.exe
EasyAVFilter_Release释放句柄
EasyAVFilter_SetCallback设置回调函数和自定义指针,回调过程中的各种媒体信息/连接信息/转码进度
EasyAVFilter_AddInput添加输入参数(源地址)
EasyAVFilter_AddFilter添加中间参数,如:转码,兼容ffmpeg命令所有参数(例如-vcodec copy -acodec aac)
EasyAVFilter_SetOutput设置输出参数(目标地址)
EasyAVFilter_GetFilters获取所有参数(review参数输入是否正确)
EasyAVFilter_Start开始工作
EasyAVFilter_Stop停止工作

详细信息可以直接看https://www.easydarwin.org/tools/153.html,具体用法和场景,后续逐步介绍;


http://www.niftyadmin.cn/n/4988833.html

相关文章

设计师都去哪些网站找样机素材

在当今的设计领域&#xff0c;3D样机素材已经成为一个重要的领域。3D样机素材可以让设计师更好地展示他们的设计理念和概念&#xff0c;也可以帮助客户更好地理解设计。为了帮助设计师更容易地创建3D样机素材&#xff0c;以下是我推荐的10个易于使用的3D样机素材网站。 即时设…

C++中使用 switch-case 进行条件处理

C中使用 switch-case 进行条件处理 switch-case 让您能够将特定表达式与一系列常量进行比较&#xff0c;并根据表达式的值时执行不同的操作。在这种结构中&#xff0c;经常会使用 C新增的关键字 switch、 case、 default 和 break。 switch-case 结构的语法如下&#xff1a; …

MySQL— 基础语法大全及操作演示!!!(事务)

MySQL—— 基础语法大全及操作演示&#xff08;事务&#xff09; 六、事务6.1 事务简介6.2 事务操作6.2.1 未控制事务6.2.2 控制事务一6.2.3 控制事务二 6.3 事务四大特性6.4 并发事务问题6.5 事务隔离级别 MySQL— 基础语法大全及操作演示&#xff01;&#xff01;&#xff01…

语言基础篇3——学习第一步,Python环境搭建

环境搭建 基础环境搭建 https://www.python.org/downloads/&#xff0c;以Python3.11.5为例&#xff1a; Install for Windows 提供安装程序或者压缩包&#xff0c;安装程序点击下一步即可&#xff0c;压缩包解压即可&#xff0c;注意配置根目录到系统环境变量PATH。 Ins…

Metinfo6.0.0任意文件读取【漏洞复现】

文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现代码审计漏洞点 1.5、深度利用EXP编写 1.6、漏洞挖掘1.7修复建议 1.1、漏洞描述 漏洞名称&#xff1a;MetInfo任意文件读取 漏洞简介&#xff1a;MetInfo是一套使用PHP和MySQL开发的内容管理系统&#xff0c;其…

《Go 语言第一课》课程学习笔记(十四)

接口 认识接口类型 接口类型是由 type 和 interface 关键字定义的一组方法集合&#xff0c;其中&#xff0c;方法集合唯一确定了这个接口类型所表示的接口。type MyInterface interface {M1(int) errorM2(io.Writer, ...string) }我们在接口类型的方法集合中声明的方法&#…

MFC -- Date Time Picker 控件使用

当前环境&#xff1a;VS2015 Windows 10 //&#xff08;一&#xff09;使用普通函数&#xff0c; 获取当前时间CString strCurrentTime; COleDateTime m_time COleDateTime::GetCurrentTime(); strCurrentTime m_time.Format(_T("%Y-%m-%d %H:%M:%S")); SetDlgIt…

禁止VMware虚拟机与宿主机的时间同步

解决方法&#xff1a; 关闭虚拟机&#xff0c;编辑虚拟机的配置文件XXX.vmx&#xff0c;查找tools.syncTime&#xff0c;如果存在&#xff0c;且值为TRUE&#xff0c;则将值改为FALSE &#xff0c;如下所示。如果存在&#xff0c;且值为FALSE&#xff0c;则不必修改。如果不存…