嵌入式音视频开发(一)ffmpeg框架及内核解析

news2025/2/12 3:23:04

系列文章目录

嵌入式音视频开发(零)移植ffmpeg及推流测试
嵌入式音视频开发(一)ffmpeg框架及内核解析


文章目录

  • 系列文章目录
  • 前言
  • 一、ffmpeg的内核
    • 1.1 框架解析
    • 1.2 内核解析
    • 1.3 FFmpeg内部数据流
      • 1.3.1 典型的解码流程
      • 1.3.2 典型的编码与推流流程
      • 1.3.3 典型的滤镜处理流程
  • 二、常用命令行工具及语法
    • 2.1 基本语法
    • 2.2 视频/音频格式转换
    • 2.3 视频编辑
    • 2.3 音频处理
    • 2.4 录屏与推流


前言

  前节简单介绍了ffmpeg,本节进行FFmpeg的整体架构和内核解读,以及常用命令行的使用。

一、ffmpeg的内核

1.1 框架解析

在这里插入图片描述
  从图像中,我们可以看到FFmpeg 主要由以下核心库组成,每个库负责不同的功能:

  • libavformat —— 负责解析和封装多媒体文件(如 MP4、FLV、MKV)。
  • libavcodec —— 负责音视频编解码(支持 H.264、AAC、MP3 等)。
  • libavfilter —— 提供音视频滤镜功能(如添加水印、调整亮度)。

  除此之外还有附件库:

  • libavutil —— 提供通用工具函数(如内存管理、日志处理)。
  • libswscale —— 处理视频像素格式转换和缩放(如 RGB 转 YUV)。
  • libswresample —— 处理音频格式转换(如 44.1kHz 到 48kHz)。

1.2 内核解析

  FFmpeg 的底层由 C 语言实现,核心包含多个关键部分,如下图所示:
在这里插入图片描述

(1)AVFormatContext:利用封装格式处理

  • 创建输出格式上下文
    • avformat_alloc_output_context2() 初始化一个输出格式上下文
  • 文件 I/O:支持 avio_read()、avio_write() 操作
  • 流管理:音视频数据流以 AVStream 形式存在
  • 封装/解封装器:
    • avformat_find_stream_info() 解析格式
    • av_read_frame() 读取数据
    • av_write_frame() 写入数据

(2) AVCodecContext:音视频编解码

  • 编码器/解码器注册
    • avcodec_register_all() 负责注册所有编解码器
  • 帧处理
    • avcodec_send_packet() 发送数据包
    • avcodec_receive_frame() 获取解码数据
  • 优化
    • 采用 SIMD 指令集加速(x86 SSE、ARM NEON),内部使用 Threading API 进行多线程优化

(3) AVFilterContext :构建滤镜链

  • 创建和配置滤镜链
    • avfilter_graph_create_filter() 创建滤镜链
    • avfilter_graph_parse_ptr() 解析滤镜链字符串,并添加到滤镜图中
  • 编辑滤镜链
    • av_buffersrc_add_frame() 将数据帧添加到滤镜图的输入端。
    • av_buffersink_get_frame() 从滤镜图的输出端获取处理后的数据帧。

(4) libswscale:图像处理

  • 图像缩放
    • sws_getContext() 创建缩放上下文
    • sws_scale() 执行缩放
  • 颜色格式转换(如RGB->YUV)
    • swsContext() 色彩转换上下文
    • sws_getContext() 颜色空间转换
色彩格式说明
AV_PIX_FMT_YUV420PYUV 4:2:0,常见于 H.264 编码
AV_PIX_FMT_YUYV422YUV 4:2:2,部分摄像头格式
AV_PIX_FMT_RGB24每像素 24 位 RGB
AV_PIX_FMT_BGR24每像素 24 位 BGR
AV_PIX_FMT_NV12现代 GPU 常用的 YUV 4:2:0

(5) libswresample:音频格式转换

  • 采样率转换、通道数调整
    • swr_alloc_set_opts()(创建转换上下文)
    • swr_convert()(执行转换)

(6) libavutil:通用工具库,如:数据类型转换、时间基准处理(AVRational)、日志管理、哈希计算(MD5、SHA)

1.3 FFmpeg内部数据流

1.3.1 典型的解码流程

avformat_open_input()   // 打开媒体文件
avformat_find_stream_info()  // 解析流信息
avcodec_find_decoder()   // 查找解码器
avcodec_alloc_context3() // 分配解码上下文
avcodec_open2()  // 打开解码器
while (av_read_frame()) {
    avcodec_send_packet() // 送入解码器
    avcodec_receive_frame() // 获取解码后数据
}

1.3.2 典型的编码与推流流程

avformat_alloc_output_context2()  // 创建输出格式上下文
avcodec_find_encoder()  // 查找编码器
avcodec_alloc_context3()  // 分配编码上下文
avcodec_open2()  // 打开编码器
while (获取原始帧) {
    avcodec_send_frame()  // 送入编码器
    avcodec_receive_packet()  // 获取压缩数据
    av_interleaved_write_frame()  // 推流
}

1.3.3 典型的滤镜处理流程

avfilter_graph_alloc()  // 创建滤镜图
avfilter_graph_parse_ptr()  // 解析滤镜描述
avfilter_graph_config()  // 配置滤镜
while (处理帧) {
    av_buffersrc_add_frame()  // 送入滤镜
    av_buffersink_get_frame()  // 获取输出
}

二、常用命令行工具及语法

2.1 基本语法

ffmpeg <global-options> <input-options> -i <input> <output-options> <output>  
  • 全局参数(global-options):日志输出,文件覆盖等全局选项.
  • 输入文件参数(input-options):读取文件的输入选项
  • 输出文件参数(output-options):转换(编解码器,质量等)或过滤或流映射

  常用高频命令行参数如下所示:

参数说明
-c指定编码器
-c copy直接复制,不经过重新编码
-c:v指定视频编码器
-c:a指定音频编码器
-i指定输入文件
-an去除音频流
-vn去除视频流
-preset指定输出的视频质量,会影响文件的生成速度,有以下几个可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow
-y不经过确认,输出时直接覆盖同名文件

2.2 视频/音频格式转换

格式转换

// 将 input.mp4 转换为 output.avi(自动检测编解码器)
ffmpeg -i input.mp4 output.avi

// 将 MP3 转换为 WAV
ffmpeg -i input.mp3 output.wav

指定编码格式

// 使用 H.264 编码 和 AAC 音频编码 进行转换
ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mp4

2.3 视频编辑

裁剪视频

// 截取区间(截取 10-30 秒)
ffmpeg -i input.mp4 -ss 00:00:10 -to 00:00:30 -c copy output.mp4
-ss:起始时间(秒或 hh:mm:ss)
-to:结束时间

// 按时长裁剪(从 10 秒处开始,截取 20 秒)
ffmpeg -i input.mp4 -ss 10 -t 20 -c copy output.mp4
-t:截取的持续时间

// 裁剪视频画面(区域裁剪)
ffmpeg -i input.mp4 -vf "crop=640:480:100:50" output.mp4
- crop=width:height:x:y
	-(640, 480):裁剪后的宽高
	-(100, 50):裁剪起始位置(左上角坐标)

视频合并

// 直接合并多个相同格式的视频
ffmpeg -i "concat:input1.mp4|input2.mp4" -c copy output.mp4

// 不同格式视频合并(需要重新编码)
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v:0][0:a:0][1:v:0][1:a:0]concat=n=2:v=1:a=1[outv][outa]" 
	/-map "[outv]" -map "[outa]" output.mp4
- concat=n=2:v=1:a=1:合并 2 个视频,带视频流 v=1 和音频流 a=1

2.3 音频处理

提取音频

ffmpeg -i input.mp4 -q:a 0 -map a output.mp3

替换视频的音频

ffmpeg -i input.mp4 -i new_audio.mp3 -c:v copy -c:a aac -strict experimental output.mp4

调整音量

ffmpeg -i input.mp3 -af "volume=2.0" output.mp3
	- volume=2.0:音量变为原来的 2

2.4 录屏与推流

录屏

ffmpeg -f gdigrab -framerate 30 -i desktop output.mp4

录制摄像头

ffmpeg -f v4l2 -i /dev/video0 output.mp4
 - /dev/video0:摄像头设备

直播推流(RTMP)

ffmpeg -re -i input.mp4 -c:v libx264 -b:v 1000k -f flv rtmp://live_url
 - rtmp://live_url:推流服务器地址

免责声明:本文参考了网上公开的部分资料,仅供学习参考使用,若有侵权或勘误请联系笔者

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

javaEE-11.javaScript入门

目录 一.什么是javaScript 二.快速实现 三.JS引入方式 1.行内引入: 2.内部引入: 3.外部引入: 四.基础语法 1.变量 变量命名规则: 2.数据类型 3.运算符 五.JS对象 1.数组 创建数组: 2.操作数组 3.函数 函数注意事项: 函数参数: 4.对象 1.使用字面量 创建对象:…

畅游Diffusion数字人(16):由音乐驱动跳舞视频生成

畅游Diffusion数字人(0):专栏文章导航 前言:从Pose到跳舞视频生成的工作非常多,但是还没有直接从音乐驱动生成的工作。最近字节跳动提出了MuseDance,无需复杂的动作引导输入(如姿势或深度序列),从而使不同专业水平的用户都能轻松进行灵活且富有创意的视频生成。 目录 贡…

DeepSeek 助力 Vue 开发:打造丝滑的步骤条

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

领略算法真谛:差分

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…

【图片转换PDF】多个文件夹里图片逐个批量转换成多个pdf软件,子文件夹单独合并转换,子文件夹单独批量转换,基于Py的解决方案

建筑设计公司在项目执行过程中&#xff0c;会产生大量的设计图纸、效果图、实景照片等图片资料。这些资料按照项目名称、阶段、专业等维度存放在多个文件夹和子文件夹中。 操作需求&#xff1a;为了方便内部管理和向客户交付完整的设计方案&#xff0c;公司需要将每个项目文件…

在Linux上如何让ollama在GPU上运行模型

之前一直在 Mac 上使用 ollama 所以没注意&#xff0c;最近在 Ubuntu 上运行发现一直在 CPU 上跑。我一开始以为是超显存了&#xff0c;因为 Mac 上如果超内存的话&#xff0c;那么就只用 CPU&#xff0c;但是我发现 Llama3.2 3B 只占用 3GB&#xff0c;这远没有超。看了一下命…

程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<8>

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。 今天我们复习前面学习的指针知识 目录 关于指针数组和数组指针的区别指针数组&#xff08;Array of Poi…

快速集成DeepSeek到项目

DeepSeek API-KEY 获取 登录DeekSeek 官网&#xff0c;进入API 开放平台 2. 创建API-KEY 复制API-KEY进行保存&#xff0c;后期API调用使用 项目中集成DeepSeek 这里只展示部分核心代码&#xff0c;具体请查看源码orange-ai-deepseek-biz-starter Slf4j AllArgsConstructo…

DeepSeek做赛车游戏

赛车模型 2D生成图片 任意AI图片软件SD&#xff0c;MJ 图片生成3D模型 车身 车轮 场景 Rodin,Tripo和Meshy 询问deepSeek如何开发 拷贝代码 将汽车运行代码拖到汽车上 再让AI写个摄像头跟随代码 再去提问deepseek控制轮胎和一些处理细节

未来替代手机的产品,而非手机的本身

替代手机的产品包括以下几种&#xff1a; 可穿戴设备&#xff1a;智能手表、智能眼镜等可穿戴设备可以提供类似手机的功能&#xff0c;如通话、信息推送、浏览网页等。 虚拟现实&#xff08;VR&#xff09;技术&#xff1a;通过佩戴VR头显&#xff0c;用户可以进行语音通话、发…

uniapp开发微信小程序请求超时设置【亲测有效】

在Hbuilderx中 使用uniapp开发微信小程序时 封装请求方法 请求代码如下 function requestFun(app) {// get请求app.config.globalProperties._get function(path, data, success, fail, complete) {data data || {};data.token uni.getStorageSync(token) || ;uni.request…

deepseek本地部署-linux

1、官网推荐安装方法&#xff08;使用脚本&#xff0c;我绕不过github&#xff0c;未采用&#xff09; 登录ollama下载网站https://ollama.com/download/linux&#xff0c;linux下有下载脚本。 正常来说&#xff0c;在OS系统下直接执行脚本即可。 2、手动安装方法 2.1获取ol…

vite + axios 代理不起作用 404 无效

vite axios 代理不起作用 先看官方示例 export default defineConfig({server: {proxy: {// 字符串简写写法/foo: http://localhost:4567,// 选项写法/api: {target: http://jsonplaceholder.typicode.com,changeOrigin: true,rewrite: (path) > path.replace(/^\/api/, )…

【Linux】从零开始:编写你的第一个Linux进度条小程序

Linux相关知识点可以通过点击以下链接进行学习一起加油&#xff01;初识指令指令进阶权限管理yum包管理与vim编辑器GCC/G编译器make与Makefile自动化构建GDB调试器与Git版本控制工具 &#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言专栏&#xff1a;C语言 &am…

【办公类-53-04】20250209Python模仿制作2024学年第二学期校历

背景需求&#xff1a; 马上开学了&#xff0c;又要制作校历&#xff08;删划节假日&#xff09;。之前我都是用网络的图片&#xff0c;然后在PPT里修改。 存在问题&#xff1a; 网络校历是从周日开始的&#xff0c;但日常我们老师做教案&#xff0c;都是默认从周一到周五&…

11vue3实战-----封装缓存工具

11vue3实战-----封装缓存工具 1.背景2.pinia的持久化思路3.以localStorage为例解决问题4.封装缓存工具 1.背景 在上一章节&#xff0c;实现登录功能时候&#xff0c;当账号密码正确&#xff0c;身份验证成功之后&#xff0c;把用户信息保存起来&#xff0c;是用的pinia。然而p…

Unity 基础编程

在这个练习中将新建unity脚本&#xff0c;控制player的运动与转动&#xff0c;实现用代码检测碰撞与删除物体。 该练习将应用附件中的项目文件&#xff0c;该文件与Unity快速练习的文件是同一个项目文件。 一、构建Player运动脚本 该部分将构建一个在场景中由玩家控制游戏物…

Spring Boot接入Deep Seek的API

1&#xff0c;首先进入deepseek的官网&#xff1a;DeepSeek | 深度求索&#xff0c;单击右上角的API开放平台。 2&#xff0c;单击API keys&#xff0c;创建一个API&#xff0c;创建完成务必复制&#xff01;&#xff01;不然关掉之后会看不看api key&#xff01;&#xff01;&…

从Word里面用VBA调用NVIDIA的免费DeepSeekR1

看上去能用而已。 选中的文字作为输入&#xff0c;运行对应的宏即可&#xff1b;会先MSGBOX提示一下&#xff0c;然后相关内容追加到word文档中。 需要自己注册生成好用的apikey Option ExplicitSub DeepSeek()Dim selectedText As StringDim apiKey As StringDim response A…

C语言学习笔记:子函数的调用实现各个位的累加和

在C语言程序学习之初&#xff0c;我们都会学习如何打印 hello world&#xff0c;在学习时我们知道了int main&#xff08;&#xff09;是主函数&#xff0c;程序从main函数开始执行&#xff0c;这是流程控制的一部分内容。在主函数中我们想要实现一些功能&#xff0c;比如求各个…