FFmpeg学习记录(二)—— ffmpeg多媒体文件处理

1.日志系统

常用的日志级别:

  • AV_LOG_ERROR
  • AV_LOG_WARNING
  • AV_LOG_INFO
  • AV_LOG_DEBUG
#include <stdio.h>
#include <libavutil/log.h>

int main(int argc, char *argv[])
{
    av_log_set_level(AV_LOG_DEBUG);

    av_log(NULL, AV_LOG_DEBUG, "hello world!\n");

    return 0;
}

2.文件的删除与重命名

文件删除与重命名的API:

  • avpriv_io_delete()
  • avpriv_io_move()
	int ret;
    // 重命名
    ret = avpriv_io_move("111.txt", "222.txt");
    if(ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "Failed to rename\n");
        return -1;
    }
    av_log(NULL, AV_LOG_INFO, "Success to renmae\n");


    // 删除
    ret = avpriv_io_delete("./test.txt");
    if(ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "Failed to delete\n");
        return -1;
    }
    av_log(NULL, AV_LOG_INFO, "Success to delete\n");

3.目录操作

操作目录重要函数:

  • avio_open_dir()
  • avio_read_dir()
  • avio_close_dir()

操作目录重要结构体:

  • AVIODirContext
  • AVIODirEntry
    avdevice_register_all();

    int ret;
    AVIODirContext *ctx = NULL;
    AVIODirEntry *entry = NULL;
    av_log_set_level(AV_LOG_INFO);

    ret = avio_open_dir(&ctx, "./", NULL);
    if(ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "Can't open dir: %s\n", av_err2str(ret));
        return -1;
    }

    while(1) {
        avio_read_dir(ctx, &entry);
        if(ret < 0)
        {
            av_log(NULL, AV_LOG_ERROR, "Can't read dir: %s\n", av_err2str(ret));
            goto __fail;
        }

        if(!entry) {
            break;
        }

        av_log(NULL, AV_LOG_INFO,"%-9s %12"PRId64"  %s\n", entry->size, entry->name);

        avio_free_directory_entry(&entry);
    }


__fail:
    avio_close_dir(&ctx);

4.抽取音频数据

  • 1.处理一些参数
  • 2.打开多媒体文件
  • 3.从多媒体文件中找到音频流
  • 4.打开目的文件的上下文
  • 5.为目的文件,创建一个新的音频流
  • 6.设置输出音频参数
  • 7.写多媒体文件头到目的文件
  • 8…从源多媒体文件中读音频数据到目的文件中
  • 9.写多媒体文件尾到文件中
  • 10.将申请的资源释放掉

步骤比较多,一点一点来实现:

 // 1.处理一些参数
    if(argc < 3) {
        av_log(NULL, AV_LOG_INFO, "argument must be 3");
        exit(-1);
    }

    src = argv[1];
    dst = argv[2];

    // 2.打开多媒体文件
    ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);
    if(ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));
        exit(-1);
    }
// 3.从多媒体文件中找到音频流
    idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if(idx < 0) {
        av_log(pFmtCtx, AV_LOG_ERROR, "Does not include audio\n");
        goto _ERROR;
    }

    // 4.打开目的文件的上下文
    oFmtCtx = avformat_alloc_context();
    if(!oFmtCtx) {
        av_log(NULL, AV_LOG_ERROR, "No Memory\n");
        goto _ERROR;
    }
    outFmt = av_guess_format(NULL, dst, NULL);
    oFmtCtx->oformat = outFmt;

    // 5.为目的文件,创建一个新的音频流
    outStream = av_format_new_stream(oFmtCtx, NULL);

    // 6.设置输出音频参数
    inStream = pFmtCtx->stream[idx];
    avcodec_parameters_copy(outStream->codecpar, inStream->codecpar);
    outStream->codecpar->codec_tag = 0;
    // 7.写多媒体文件头到目的文件
    ret = avformat_write_header(oFmtCtx, NULL);
    if(ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));
        goto _ERROR;
    }

    // 8.聪源多媒体文件中读到音频数据到目的文件中
    while(av_read_frame(pFmtCtx, &pkt) >= 0) {
        if(pkt.stream_index == idx) {
            pkt.pts = av_rescale_q_rnd(pkt.pts, inStream->time_base, outStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
            pkt.dts = pkt.dts;
            pkt.duration = av_rescale_q(pkt.duration, inStream->time_base, outStream->time_base);
            pkt.stream_index = 0;
            pkt.pos = -1;
            av_interleaved_write_frame(oFmtCtx, &pkt);
            av_packet_unref(&pkt);
        }
    }
    // 9.写多媒体文件尾到文件中
    av_write_trailer(oFmtCtx);

    // 10.将申请的资源释放掉
_ERROR:
    if(pFmtCtx) {
        avformat_close_input(&pFmtCtx);
        pFmtCtx = NULL;
    }

    if(oFmtCtx->pb) {
        avio_close(oFmtCtx->pb);
    }

    if(oFmtCtx) {
        avformat_free_context(oFmtCtx);
        oFmtCtx = NULL;
    }

6.抽取视频数据

与处理音频流程相同,简单修改即可

 // 3.从多媒体文件中找到视频流
    idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if(idx < 0) {
        av_log(pFmtCtx, AV_LOG_ERROR, "Does not include VIDEO\n");
        goto _ERROR;
    }

... ...
  // 8.从源多媒体文件中读到视频数据到目的文件中
  while(av_read_frame(pFmtCtx, &pkt) >= 0) {
        if(pkt.stream_index == idx) {
            pkt.pts = av_rescale_q_rnd(pkt.pts, inStream->time_base, outStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
            pkt.dts = av_rescale_q_rnd(pkt.dts, inStream->time_base, outStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
            // pkt.dts = pkt.dts;
            pkt.duration = av_rescale_q(pkt.duration, inStream->time_base, outStream->time_base);
            pkt.stream_index = 0;
            pkt.pos = -1;
            av_interleaved_write_frame(oFmtCtx, &pkt);
            av_packet_unref(&pkt);
        }
    }

6.多媒体格式转封装

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

7.视频裁剪

在这里插入图片描述

程序是在上面的程序基础上修改的,这里就把核心修改地方贴出来。

有两个注意点:(对应下面的修改2和修改3)

第一个是音视频时间的问题。

针对音频:从第5秒钟截取,那他就是第5秒。针对视频:因为有IPB 帧,如果刚好第5秒是P帧或者B帧,没有了I帧,那么就不能解码成功,播放的时候就会花屏。

解决:告诉ffmpeg如果不是I帧,就要向前或者向后找最近的I帧

第二个是时间的问题。

由于是裁剪,所以需要计算相对时间。 使用后面的时间减去第一个时间基的时间,这样子才能保证时间的正确性。音频的dts和pts是相同的,而视频可能是不同的,所以这里需要多加一步判断。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/592709.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Cisco Nexus Dashboard 3.1(1k) - 云和数据中心网络管理软件

Cisco Nexus Dashboard 3.1(1k) - 云和数据中心网络管理软件 跨数据中心和云实现集中配置、运行和分析。 请访问原文链接&#xff1a;https://sysin.org/blog/cisco-nexus-dashboard/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sys…

根据docker部署nginx并且实现https

目录 一、Docker中启用HTTPS有几个重要的原因 二、https介绍 三、https过程 四、安装docker-20.10.18 五、如何获取证书 通过阿里云获取证书 六、docker部署nginx并且实现https 6.1准备证书 6.2准备nginx.conf 和 index.html文件 6.3生成容器 6.4浏览器验证证书 一、…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑碳捕集和电转气的综合能源系统优化调度》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

STM32标准库控制一盏LED闪烁

实物连接&#xff1a; ## 软件编程&#xff1a;默认已经有一个工程模板&#xff0c;代码实现逻辑&#xff1a; 1、使用RCC开启GPIO的时钟&#xff1b; 2、使用GPIO初始化函数实现初始化GPIO 3、使用输入或输出的函数控制GPIO口 #include "stm32f10x.h" …

JavaEE 多线程详细讲解(1)

1.线程是什么 &#xff08;shift F6&#xff09;改类名 1.1.并发编程是什么 &#xff08;1&#xff09;当前的CPU&#xff0c;都是多核心CPU &#xff08;2&#xff09;需要一些特定的编程技巧&#xff0c;把要完成的仍无&#xff0c;拆解成多个部分&#xff0c;并且分别让…

【Java】面向对象核心知识点(三),文章层次分明,内容精益求精,代码简单易懂

目录 一、对象类型转换 1.1 情况 1.2 语法 1.3 代码 1.4 结论 二、static关键字 2.1 作用 2.2 代码 三、final关键字 3.1 作用 3.2 代码 四、instanceof关键字 4.1 作用 4.2 代码 &#xff08;原创文章&#xff0c;转载请注明出处&#xff09; 博主是计算机专业…

StableDiffusion 文生视频教程,从Mov2mov到AnimateDiff

文章目录 0. 前言1. 简介2. 文生视频2.1 Mov2mov2.1.1 插件安装2.1.2 视频生成 2.2 ffmpeg Ebsynth2.2.1 ffmpeg 安装2.2.2 Ebsynth安装2.2.3 Ebsynth 插件安装2.2.4 视频生成2.2.4.1 Step 1 蒙版裁剪2.2.4.2 Step2 识别关键帧2.2.4.3 Step3~4 关键帧重绘2.2.4.3 Step5~6 生成…

n-Track Studio Suite for Mac激活版:打造您的专属音频工作室

n-Track Studio Suite for Mac是一款功能强大的数字音频工作站软件&#xff0c;让您在家中就能享受到专业录音棚的待遇。无论是录制人声、乐器还是MIDI序列&#xff0c;都能轻松应对。 n-Track Studio Suite for Mac激活版下载 这款软件拥有实时音高校准、时间拉伸和自动补足功…

18 内核开发-内核重点数据结构学习

课程简介&#xff1a; Linux内核开发入门是一门旨在帮助学习者从最基本的知识开始学习Linux内核开发的入门课程。该课程旨在为对Linux内核开发感兴趣的初学者提供一个扎实的基础&#xff0c;让他们能够理解和参与到Linux内核的开发过程中。 课程特点&#xff1a; 1. 入门级别&…

9.4.k8s的控制器资源(job控制器,cronjob控制器)

目录 一、job控制器 二、cronjob控制器 一、job控制器 job控制器就是一次性任务的pod控制器&#xff0c;pod完成作业后不会重启&#xff0c;其重启策略是&#xff1a;Never&#xff1b; 简单案例 启动一个pod&#xff0c;执行完成一个事件&#xff0c;然后pod关闭&#xff1b;…

破解keil uvision4 4.12时遇到:*** TOOLS.INI: TOOLCHAIN NOT INSTALLED **

1 使用管理员权限打开keil和注册机。 2 将注册机中的target改为ARM。

免费开源,无需 GPU,本地化部署大语言模型的对话系统

免费开源&#xff0c;无需 GPU&#xff0c;本地化部署大语言模型的对话系统 分类 编程技术 项目名: FreeAskInternet -- 本地化部署大语言模型的对话系统 Github 开源地址&#xff1a; https://github.com/nashsu/FreeAskInternet FreeAskInternet 是一个免费开源的工具&am…

ZOC8 for Mac v8.08.1激活版:卓越性能的SSH客户端

在远程连接和管理的世界中&#xff0c;ZOC8 for Mac以其卓越的性能和丰富的功能&#xff0c;成为了众多专业人士的首选SSH客户端。它支持SSH1、SSH2、Telnet、Rlogin、Serial等多种协议&#xff0c;让您轻松连接到远程服务器。ZOC8拥有简洁直观的界面和强大的功能设置&#xff…

STM32 F103C8T6学习笔记16:1.3寸OLED的驱动显示日历

今天尝试使用STM32 F103C8T6驱动显示 1.3寸的OLED&#xff0c;显示数字、字符串、汉字、图片等 本质与0.96寸的OLED是完全相同的原理&#xff1a; 而且经过我的研究发现: 1.3寸大小的OLED并未比0.96寸的有更多的显示像素点数来显示&#xff0c;也是128*64的像素点数显示: 也…

【设计模式】函数式编程范式工厂模式(Factory Method Pattern)

目录标题 定义函数式接口函数式接口实现类工厂类封装实际应用总结 定义函数式接口 ISellIPad.java /*** 定义一个函数式接口* param <T>*/ FunctionalInterface public interface ISellIPad<T> {T getSellIPadInfo();}函数式接口实现类 HuaWeiSellIPad.java pu…

头歌实践教学平台:三维图形观察OpenGL1.0

第1关&#xff1a;模型变换 一.任务描述 根据提示&#xff0c;在右侧修改代码&#xff0c;并自己绘制出图形。平台会对你编写的代码进行测试。 1.本关任务 学习了解三维图形几何变换原理。 理解掌握OpenGL三维图形几何变换的方法。 理解掌握OpenGL程序的模型视图变换。 掌握…

【机器视觉】C# .NET 8 部署yolov9 onnx对象检测

这段代码展示了一个使用YOLOv9进行对象检测的简单测试框架。代码主体以及其功能分为以下几个关键部分&#xff1a; 创建测试图片数组 _testImages&#xff0c;它包含了图片文件名和对应的标签。使用 buildTests 方法来从给定的文件名中加载图片并调整尺寸&#xff0c;准备测试数…

【每日力扣】141. 环形链表与142. 环形链表 II

&#x1f525; 个人主页: 黑洞晓威 &#x1f600;你不必等到非常厉害&#xff0c;才敢开始&#xff0c;你需要开始&#xff0c;才会变的非常厉害 141. 环形链表 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟…

利用策略模式+模板方法实现项目中运维功能

前段时间项目中有个需求&#xff1a;实现某业务的运维功能&#xff0c;主要是对10张数据库表的增删改查&#xff0c;没有复杂的业务逻辑&#xff0c;只是满足运维人员的基本需要&#xff0c;方便他们快速分析定位问题。这里简单记录分享下实现方案&#xff0c;仅供参考。 一、…

学习Rust的第27天:Rust中的pwd

过去几天我们一直在重新创建 GNU 核心实用程序的基本功能&#xff0c;而今天&#xff0c;我们将做一些有点太简单的事情&#xff0c; pwd 这个实用程序是用于打印Linux终端中的工作目录。 Understanding the utility 了解实用程序 Running the pwd command, we get an output l…
最新文章