当前位置: 首页 > news >正文

FFmpeg之三 录制音频并保存, API编解码从理论到实战

在学习FFmpeg的时候,想拿demo来练习,官方虽有示例,但更像是工具演示,新手不好掌握,在网上找不到有文章,能给出完整的示例和关键点的分析说明,一步一个错误,慢慢啃过来的,本文就把重要经验和完整代码全部分享出来。

文章目录

  • 音频的基本概念
    • 1. 采样率 (Sample Rate)
      • 解释
      • 单位
      • 示例
    • 2. 声道数 (Channel Count)
      • 解释
      • 示例
    • 3. 采样位数 / 位深度 (Bit Depth)
      • 解释
      • 单位
      • 示例
    • 4、音频帧
      • 解释
      • 为什么需要知道 frame_size?
  • 分片(plane)和打包(packed)
  • 重采样
  • AVAudioFifo
  • PTS
  • 代码实现:

音频的基本概念

1. 采样率 (Sample Rate)

解释

采样率是指在将连续的模拟音频信号转换为数字信号时,每秒钟对其幅度进行测量的次数(样本数)。可以将其想象为给连续的声音波形拍摄快照,采样率就是每秒拍摄快照的数量。采样率越高,意味着捕捉到的声音信息越精细,尤其是在高频部分,能够还原的声音频率上限也越高(根据奈奎斯特理论,最高可还原频率约为采样率的一半)。

单位

赫兹 (Hz) 或千赫兹 (kHz)。

示例

  • 8000 Hz (8 kHz): 电话音质,足以识别人声,但听起来比较模糊。
  • 16000 Hz (16 kHz): 广泛用于 VoIP(网络电话)和一些语音识别应用,比电话音质好。
  • 44100 Hz (44.1 kHz): CD 音质标准。可以很好地覆盖人耳能听到的绝大部分频率范围(约 20 Hz - 20 kHz)。
  • 48000 Hz (48 kHz): 专业音频、DVD 和蓝光视频、数字电视广播中常用的标准。
  • 96000 Hz (96 kHz) / 192000 Hz (192 kHz): 高解析度音频(Hi-Res Audio)标准,理论上能提供超越 CD 的音质细节和频率响应,但文件体积也更大。

2. 声道数 (Channel Count)

解释

声道数是指音频信号中包含的独立声轨的数量。它决定了声音的空间感和来源方向。

示例

  • 1 (Mono / 单声道): 所有声音混合在一个声道中,没有方向感。适用于语音录制、一些老式录音或 AM 广播。
  • 2 (Stereo / 立体声 / 双声道): 包含左、右两个声道,可以营造出声音从不同方向传来的空间感。
  • 5.1 声道: 包含 5 个全频带声道(前左、前中、前右、后左、后右)和 1 个低频效果声道(LFE,即 “.1”),用于家庭影院环绕声。
  • 7.1 声道: 在 5.1 的基础上增加了两个侧环绕声道。

3. 采样位数 / 位深度 (Bit Depth)

解释

位深度(Bit Depth)描述了用来表示每个音频样本(采样点)的振幅(响度)的二进制位数(bits)。它决定了音频信号的动态范围(最响和最轻声音之间的范围)和量化噪声的大小。位数越多,表示振幅的精度就越高,动态范围越大,声音细节越丰富

单位

比特 (bit)。

示例

  • 8 bit: 动态范围较小,量化噪声明显。常见于早期的游戏、一些电话系统或特定效果。
  • 16 bit: CD 音质标准。提供了约 96 dB 的动态范围,对大多数听音环境和音乐类型来说已经足够好。
  • 24 bit: 专业音频录制和处理中广泛使用。提供了约 144 dB 的巨大动态范围,可以记录非常细微的声音细节,并在后期处理中有更大裕量。
  • 32 bit float (浮点): 主要在音频制作和处理软件内部使用。它提供了极大的动态范围,并且可以避免在处理过程中因信号过载而产生削波失真(clipping)。最终成品通常会转换回 16 bit 或 24 bit 整数。

4、音频帧

解释

“音频帧”(Audio Frame)是指编码器处理和输出的一个基本单元。它包含了一定数量的连续音频样本(每个声道)。

与前面提到的单个“样本”(Sample)不同,编码器(如 AAC, MP3, Opus 等)为了提高压缩效率和利用心理声学模型,通常会把一小段时间的音频样本打包在一起进行处理和压缩。这个“包”就是一个编码后的音频帧。

在 FFmpeg 的 AVCodecContext 结构中,有一个名为 frame_size 的成员。对于大多数有损压缩编码器,这个 frame_size 指的是该编码器每个输出帧所包含的单个声道的样本数量。对于特定编码器(或其特定配置)来说这个值是固定的

为什么需要知道 frame_size?

  • 缓冲管理: 在使用 libavcodec 进行编码时,你需要确保提供给编码器的 PCM 样本数量通常是 frame_size 的整数倍(或者至少满足编码器的最小输入要求)。

  • 时间戳计算: 音频帧的持续时间可以通过 frame_size / sample_rate 计算得出,这对于精确控制播放时间和同步至关重要。

  • 理解编码器行为: 知道帧大小有助于理解编码器的内部工作方式和潜在的延迟(通常至少是一个帧的长度)。

  • 重要区别: 对于未压缩的 PCM 数据,"帧"的概念不那么严格,你可以按任意数量的样本进行处理。但一旦涉及压缩编码器,它们通常强制要求以特定的 frame_size 来组织数据。

FFmpeg 中常见编码器的 frame_size 示例,frame_size 的具体值取决于所使用的编码器:

  • AAC (Advanced Audio Coding):
    常见的 FFmpeg 内置 aac 编码器或 libfdk_aac 编码器,其 frame_size 通常是 1024 个样本/声道。
    某些 AAC 变种,如 AAC-LD (Low Delay),frame_size 可能是 512 或 480。

  • MP3 (MPEG-1 Audio Layer III):
    使用 libmp3lame 编码器时,frame_size 通常是 1152 个样本/声道。

  • Opus:
    Opus 编码器比较灵活,它工作在不同的帧持续时间上(如 2.5ms, 5ms, 10ms, 20ms, 40ms, 60ms)。其 frame_size(样本数)等于 sample_rate * frame_duration_in_seconds。
    例如,在 48 kHz 采样率下,一个 20ms 的 Opus 帧包含 48000 * 0.020 = 960 个样本/声道。FFmpeg 的 frame_size 常常报告这个常用的 960 值。

  • PCM (Pulse Code Modulation - 未压缩):
    对于 PCM 这种未压缩格式,frame_size 的概念不那么适用。FFmpeg 可能会报告 frame_size 为 1,表示可以按样本处理,或者在某些封装上下文中可能有不同的表示。但编码意义上的固定帧大小通常不存在。

分片(plane)和打包(packed)

在ffmepeg 的AVCodecContext 有成员变量 sample_fmt,表示采样格式, 可选择位深度和存储样式。 位深度,例如:8bit、16bit,float 等等, 每种位深度都有两种类型,例如float型的有: AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP

  • 带P(plane)的数据格式在存储时,其左声道和右声道的数据是分开存储的,左声道的数据存储在data[0],右声道的数据存储在data[1],每个声道的所占用的字节数为linesize[0]和linesize[1],frame.data[i]或者frame.extended_data[i]表示第i个声道的数据;

  • 不带P(packed)的音频数据在存储时,是按照LRLRLR…的格式交替存储在data[0]中,linesize[0]表示总的数据量,frame.data[0]或frame.extended_data[0]包含所有的音频数据中。

重采样

在这篇文章 FFmpeg之一——常用命令 ,有提到数据处理流程, 那里并没有说重采样。重采样流程是:decoder解析 得到frame -> 对frame重采样 得到frame1 -> 对frame1 进行encoder。 为什么还要经过重采样?

在理想情况下是可行的。不用重采样也是可以的,例如这种情况:

  1. 音频源(录音设备)输出的音频参数(采样率、位深度/样本格式、声道布局)与
  2. 你选择的编码器所支持(或你希望最终文件拥有)的音频参数完全一致。

在实际应用中,这种情况并不总是发生,因此需要进行重采样 (Resampling) 或其他格式转换。以下是主要原因:

  1. 采样率不匹配 (Sample Rate Mismatch):

来源: 你的录音设备(如麦克风)可能以一个特定的采样率工作,比如 44100 Hz 或 16000 Hz。

目标: 保存的文件是标准的 48000 Hz,或者你选用的编码器在 48000 Hz 时效果最好/效率最高

解决: 重采样,将音频数据的采样率从来源(如 44.1k)转换到目标(如 48k)。FFmpeg 的 libavresample 或 libswresample 库就是做这个的(通常通过 -ar 参数或 aresample filter 隐式或显式调用)。

  1. 样本格式不匹配 (Sample Format Mismatch):

来源: 音频设备或解码器可能输出一种特定的样本格式,例如 16 位有符号整数 (s16)、32 位浮点数 (flt)、或者平面格式的 32 位浮点数 (fltp)。

目标: 但你选择的编码器可能只接受(或优化于)特定的样本格式。例如,很多 AAC 编码器内部处理或接受 fltp 格式效率更高。有些旧编码器可能只接受 s16。

解决: 这就需要进行样本格式转换,将音频数据的表示方式从一种格式转为另一种。FFmpeg 通过 -sample_fmt 参数或 aformat filter 来处理。这严格来说不叫“重采样”,但属于格式转换,通常和重采样一起讨论,因为都是预处理步骤。

  1. 声道布局不匹配 (Channel Layout Mismatch):

来源: 你可能从单声道麦克风录音 (mono)。

目标: 但你想保存为标准的双声道文件 (stereo),即使两个声道内容一样。或者反过来,从立体声源录制但只想保存单声道。

解决: 这就需要进行声道布局转换,比如将单声道复制成双声道,或将双声道混合为单声道。FFmpeg 通过 -ac 参数或 channelmap/pan 等 filter 来处理。
编码器要求/优化:

某些编码器对特定的输入参数组合有优化,或者干脆不支持某些组合。为了获得最佳压缩效率或兼容性,开发者可能会选择将输入音频转换到编码器最适合的格式。

AVAudioFifo

每个AVCodecContext (编解码器)都有对应的frame_size,在编码时,需要读取到frame_size 个sample后,才能编码一个音频帧。但是在音频转换过程中, 解码器对应的音频帧的采样数量 和 编码器对样的音频帧的采样数量可能不一样, 此时就需要累计音频采样数据到一定量后(编码器的音频帧大小)后,再写入一帧数据。否则会报错。

这个累计可以自己手动实现,也可以直接使用AVAudioFifo,它是一个缓存队列,可以把音频的采样先存入(av_audio_fifo_write),到底目标数量后(av_audio_fifo_size), 取出数据(av_audio_fifo_read)

PTS

一个音频帧的AVFrame有nb_samples个sample (和AVCodecContext 的frame_size值对应),

一个AVFrame 时长= nb_samples / sample_rate 秒

用frameIndex 表示当前帧的索引,PTS = frameIndex * 一个AVFrame 时长

代码实现:

实现步骤:
1、打开设备并初始化解码器
2、打开音频编码器
3、创建输出上下文并初始化 流、写入头文件
4、初始化重采样上下文
5、创建重采样上下文
6、使用av_read_frame 循环读取音频PCM数据,重复以下步骤:
6.1、音频解码 avcodec_send_packet-> avcodec_receive_frame, 得到解码帧decoded_frame
6.2、swr_convert_frame音频帧重采样 ,得到重采样后的音频帧 swr_frame
6.3、av_audio_fifo_write写入 FIFO队列
6.4、判断FIFO队列中的数据大小 av_audio_fifo_size,是否满足编码器帧大小
6.5、av_audio_fifo_read 读取FIFO中音频sample数据
6.6、对音频sample数据 进行编码
6.7、对编码后的音频帧 写文件

完整代码在 Github,下面贴出两个段的代码,

获取到音频帧的循环处理过程:

static void process_frame_use_decode(AVPacket* pkt, AVFrame* decoded_frame, AVFrame* swr_frame, AVAudioFifo* fifo,AVCodecContext* decoder_ctx, AVCodecContext* encoder_ctx,AVFormatContext* ofmtCtx, struct SwrContext* swr_ctx, AVPacket* out_packet, int* frameIndex)
{int ret = avcodec_send_packet(decoder_ctx, pkt);if (ret < 0){char error[1024] = {0};av_strerror(ret, error, 1024);fprintf(stderr, "Decode error: %s\n", error);return;}int received_frame = 0;while (avcodec_receive_frame(decoder_ctx, decoded_frame) == 0){received_frame++;// swr_frame->ch_layout = encoder_ctx->ch_layout;//// swr_frame->format = encoder_ctx->sample_fmt;// swr_frame->sample_rate = 48000;// swr_frame->nb_samples = encoder_ctx->frame_size; //与编码器帧大小保持一致ret = swr_convert_frame(swr_ctx, swr_frame, decoded_frame);// 打印pts,dtsprintf("decoded_frame pts: %ld, dts: %ld\n", decoded_frame->pts, decoded_frame->pkt_dts);printf("swr_frame pts: %ld, dts: %ld\n", swr_frame->pts, swr_frame->pkt_dts);if (ret < 0){char error[1024] = {0};av_strerror(ret, error, 1024);fprintf(stderr, "Error while resampling: %s\n", error);return;}// Add resampled samples to FIFOret = av_audio_fifo_write(fifo, (void**)swr_frame->data, swr_frame->nb_samples);if (ret < swr_frame->nb_samples){fprintf(stderr, "Failed to write all samples to FIFO\n");return;}printf(" frame received this time num: %d, Added %d samples to FIFO, current size: %d\n", received_frame, swr_frame->nb_samples, av_audio_fifo_size(fifo));// Encode when enough samples are availablewhile (av_audio_fifo_size(fifo) >= encoder_ctx->frame_size){printf("FIFO size: %d, frame size: %d\n", av_audio_fifo_size(fifo), encoder_ctx->frame_size);swr_frame->nb_samples = encoder_ctx->frame_size;ret = av_audio_fifo_read(fifo, (void**)swr_frame->data, encoder_ctx->frame_size);if (ret < encoder_ctx->frame_size){fprintf(stderr, "Failed to read enough samples from FIFO\n");return;}swr_frame->pts = *frameIndex * encoder_ctx->frame_size;printf("in fifo swr_frame pts: %ld, dts: %ld\n", swr_frame->pts, swr_frame->pkt_dts);encode_and_write_frame(encoder_ctx, swr_frame, ofmtCtx, out_packet, *frameIndex);(*frameIndex)++;}}
}

对重采样的音频sample进行编码、写文件:


static void encode_and_write_frame(AVCodecContext* encoder_ctx, AVFrame* swr_frame, AVFormatContext* ofmtCtx, AVPacket* out_packet, int frameIndex)
{int ret = avcodec_send_frame(encoder_ctx, swr_frame);if (ret < 0){// 获取错误信息char error[1024] = {0};av_strerror(ret, error, 1024);}// 将重采样后的帧发送给编码器if (ret == 0){while (avcodec_receive_packet(encoder_ctx, out_packet) == 0){// 正确设置数据包中的流索引out_packet->stream_index = ofmtCtx->streams[0]->index;// 调整时间戳,使其基于输出流的时间基av_packet_rescale_ts(out_packet, encoder_ctx->time_base, ofmtCtx->streams[0]->time_base);// 写入一个编码的数据包到输出文件if (av_interleaved_write_frame(ofmtCtx, out_packet) < 0){fprintf(stderr, "Error while writing output packet\n");break;}av_packet_unref(out_packet);}}
}

相关文章:

FFmpeg之三 录制音频并保存, API编解码从理论到实战

在学习FFmpeg的时候&#xff0c;想拿demo来练习&#xff0c;官方虽有示例&#xff0c;但更像是工具演示&#xff0c;新手不好掌握&#xff0c;在网上找不到有文章&#xff0c;能给出完整的示例和关键点的分析说明&#xff0c;一步一个错误&#xff0c;慢慢啃过来的&#xff0c;…...

幂等性处理解决方案实战示例

幂等性处理解决方案实战示例 幂等性是指对同一个操作执行一次或多次&#xff0c;产生的结果是相同的。在分布式系统、网络请求和金融交易等场景中&#xff0c;幂等性设计至关重要。下面我将介绍几种常见的幂等性处理方案及其实战示例。 1. 唯一标识符方案 原理&#xff1a;为…...

华为仓颉编程语言的实际用法与使用领域详解

华为仓颉编程语言的实际用法与使用领域详解 一、语言概述与核心特性 华为仓颉编程语言是面向万物智联时代的系统级编程语言,其核心特性包括: 三重内存安全机制:所有权系统 + 引用检查 + 硬件辅助防护零成本抽象:高级语法不牺牲底层性能全场景支持:从嵌入式设备到量子计算…...

JavaEE-多线程实战01

Java 多线程入门&#xff1a;第一个多线程程序 在 Java 中&#xff0c;多线程编程是非常重要的一部分。本篇文章将通过示例&#xff0c;带你快速了解如何创建第一个多线程程序&#xff0c;并深入分析其运行机制。 1. 创建一个线程类并继承 Thread 在 Java 中&#xff0c;我们…...

当AI浏览器和AI搜索替代掉传统搜索份额时,老牌的搜索引擎市场何去何从。

AI搜索与传统搜索优劣势分析 AI搜索优势 理解和处理查询方式更智能&#xff1a;利用自然语言处理&#xff08;NLP&#xff09;和机器学习技术&#xff0c;能够更好地理解用户的意图和上下文&#xff0c;处理复杂的问答、长尾问题以及多轮对话&#xff0c;提供更为精准和相关的…...

大模型——Spring.new快速构建AI驱动的定制化商业应用

大模型——Spring.new快速构建AI驱动的定制化商业应用 Spring.new 是一个基于人工智能的在线平台,专注于帮助营销经理和产品经理快速构建定制化工作流和小型应用。它通过自然语言输入,让用户描述需求,自动生成连接 Notion、Airtable、Slack 等工具的工作流或应用,例如将 F…...

django admin 中更新表数据 之后再将数据返回管理界面

在Django中&#xff0c;更新数据库中的数据并将其重新显示在Django Admin界面上通常涉及到几个步骤。这里我将详细说明如何在Django Admin中更新表数据&#xff0c;并确保更新后的数据能够立即在管理界面上显示。 定义模型 首先&#xff0c;确保你的模型&#xff08;Model&…...

深度理解linux系统—— 进程概念

一、进程 进程&#xff0c;什么是进程&#xff1f; 在课本&#xff0c;教材中是这样描述的&#xff1a;程序的一个执行示例&#xff0c;正在执行的程序&#xff1b; 从内核角度来说&#xff0c;进程就是担当分配系统资源&#xff08;CPU时间&#xff0c;内存&#xff09;的实体…...

【如何使用solidwork编辑结构导入到simscope】

这里写自定义目录标题 欢迎使用Markdown编辑器 欢迎使用Markdown编辑器 To use Simscape Multibody Link, you must install MATLAB and the CAD applications on the same computer. To ensure the successful installation of Simscape Multibody Link, before launching yo…...

Flink 时态维度表 Join 与缓存机制实战

一、引言&#xff1a;为什么需要时态维度表&#xff1f; 在实时数仓建设中&#xff0c;维度表是不可或缺的一环&#xff0c;例如&#xff1a; 风控系统中&#xff0c;用户的风险等级在不同时间可能变化&#xff1b; 营销体系中&#xff0c;商品的促销标签会动态调整&#xff…...

Apache Tomcat 漏洞(CVE-2025-24813)导致服务器面临 RCE 风险

CVE-2025-24813Apache Tomcat 中发现了一个严重安全漏洞,标识为,该漏洞可能导致服务器面临远程代码执行 (RCE)、信息泄露和数据损坏的风险。 此缺陷影响以下版本: Apache Tomcat11.0.0-M1通过11.0.2Apache Tomcat10.1.0-M1通过10.1.34Apache Tomcat9.0.0-M1通过9.0.98了解 …...

来自B站-AI匠的“RAG的prompt设计指南“的部分截图

来自B站-AI匠的“RAG的prompt设计指南“的部分截图 0. 引言1. RAG提示词 - 部分视频截图2. 总结 - 部分视频截图3. 举例 - 部分视频截图 0. 引言 这个文章记录的是B站Up主AI匠关于RAG的prompt设计指南的视频截图。 1. RAG提示词 - 部分视频截图 笔记&#xff1a; Up主推荐Fa…...

【Linux】Centos7 在 Docker 上安装 Redis7.0(最新详细教程)

一、拉取 Redis 镜像 1. 从 阿里云加速器&#xff08;docker hub&#xff09;拉取 redis镜像&#xff0c;选择镜像标签为 7.2.4 docker pull redis:7.2.4 2. 准备 Redis 的配置文件&#xff08;便于后期对配置文件进行修改&#xff09; 3.在服务器上创建需要挂载的文件夹 mk…...

Java使用微信云服务HTTP API操作微信云开发数据库

可以直接用的工具类代码 package com.kstc.qgy.util;import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.kstc.qgy.model.exception.WxException; import com.kstc.qgy.model.service.Limit; imp…...

Linux的权限

目录 1、用户分类 1.1 超级用户(root)和普通用户 1.2 普通<->超级 1.3 sudo 2、文件和目录的权限 2.1 chown&&chgrp 2.1.1 chown 2.1.2 chgrp 2.2 chmod 总结一下&#xff1a; 3、文件和目录的默认权限 4、共享文件 4.1 理解多用户隔离 4.2 /tmp/ 1…...

ACT游戏和MMORPG经济形态区别以及对经济循环的思考

对于原神的明日之后经济形态的不同解析 对于MMORPG游戏来说&#xff0c;如果采用开放市场经济的设计&#xff0c;以明日之后为例&#xff0c;系统产出端为采集、运营活动投放&#xff1b;玩家产出端为交易&#xff1b;消耗端为武器耐久的减少。但我好奇&#xff0c;在ACT游戏里…...

zynq7035的arm一秒钟最多可以支持触发多少次中断

一、概述 1.关于zynq7035的ARM处理器一秒能够支持多少次中断触发&#xff0c;需要综合来考虑。需要确定ARM处理器的参数&#xff0c;目前zynq7000系列&#xff0c;使用的双核Cortex-A9处理器。其中主频大概在500MHZ~1GHZ左右&#xff0c;不同的用户配置的主频可能稍微有差别。 …...

Spring MVC 拦截器教程

一、拦截器核心概念 1.1 拦截器 vs 过滤器 特性过滤器 (Filter)拦截器 (Interceptor)依赖关系Servlet容器Spring MVC框架作用范围所有Web请求Controller请求实现机制Java EE标准Java反射AOP生命周期服务器启动时初始化随Spring容器初始化功能场景字符编码、安全过滤权限校验、…...

【HPC存储性能测试】02-ior带宽性能测试

文章目录 一、前言二、软件安装1、安装依赖2、安装软件 三、参数说明1、mpirun参数2、ior参数 四、测试说明 一、前言 ior introduction | github hpc ior IOR 测试工具使用 POSIX、 MPIIO 或 HDF5接口对并行文件系统进行基准测试 通常使用IOR测试工具时&#xff0c;一般会配合…...

【RabbitMQ】保证消息不丢失

要确保 RabbitMQ 在消费者&#xff08;Python 服务&#xff09;重启或挂掉时消息不丢失&#xff0c;需结合 消息持久化、确认机制&#xff08;ACK&#xff09; 和 死信队列&#xff08;DLX&#xff09; 实现高可靠性&#xff1a; 1. 消息持久化&#xff08;Durability&#xff…...

算法效率的钥匙:从大O看复杂度计算 —— C语言数据结构第一讲

目录 1.数据结构与算法 1.1数据结构介绍 1.2算法介绍 2.算法效率 2.1复杂度 2.1.1时间复杂度 2.1.1.1时间复杂度计算示例1 2.1.1.2时间复杂度计算示例2 2.1.1.3时间复杂度计算示例3 2.1.1.4时间复杂度计算示例4 2.1.1.5时间复杂度计算示例5 2.1.1.6时间复杂度计算示例6…...

AI赋能守护行车安全新防线,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建驾驶车辆场景下驾驶员疲劳分心驾驶行为智能检测预警系统

在当今社会&#xff0c;随着科技生产力的飞速发展&#xff0c;汽车早已成为人们日常出行不可或缺的交通工具。它不仅极大地提高了人们的出行效率&#xff0c;也为生活带来了诸多便利。然而&#xff0c;随着汽车保有量的不断增加&#xff0c;交通安全问题也日益凸显。疲劳驾驶和…...

HNUST湖南科技大学-嵌入式考试选择题题库(109道纠正详解版)

HNUST嵌入式选择题题库 1.下面哪点不是嵌入式操作系统的特点。(B) A.内核精简 B.功能强大 C.专用性强 D.高实时性 解析&#xff1a; 嵌入式操作系统特点是内核精简、专用性强、高实时性&#xff0c;而"功能强大"通常指的是通用操作系统&#x…...

【音视频】SDL事件

SDL 事件 函数 SDL_WaitEvent()&#xff1a; 等待一个事件SDL_PushEvent()&#xff1a; 发送一个事件SDL_PumpEvents()&#xff1a; 将硬件设备产生的事件放入事件队列&#xff0c;用于读取事件&#xff0c;在调用该函数之前&#xff0c;必须调用SDL_PumpEvents搜集键盘等事件…...

[特殊字符]实战:使用 Canal + MQ + ES + Redis + XXL-Job 打造高性能地理抢单系统

&#x1f4da;目录 项目背景 技术栈总览 详细流程分析 3.1 Canal监听MySQL Binlog 3.2 MQ中转传递订单变化 3.3 Elasticsearch存储并查询附近订单 3.4 Redis高性能抢单Lua防止抢单冲突 3.5 XXL-Job定时任务处理 完整系统流程图 总结 一、项目背景 针对类似外卖、跑…...

FPGA基础之基础语法

一、基本模块结构 Verilog 代码以 模块&#xff08;Module&#xff09; 为单位&#xff0c;每个模块对应一个硬件功能单元&#xff08;如逻辑门、寄存器等&#xff09;。 基本格式&#xff1a; module 模块名 (// 输入输出端口声明input 端口1,input 端口2,output 端口3 );…...

影楼精修-皮肤瑕疵祛除算法解析

注意&#xff1a;本文样例图片为了避免侵权&#xff0c;均使用AIGC生成&#xff1b; 顾名思义&#xff0c;皮肤瑕疵祛除旨在祛除人像照片皮肤区域的痘痘/斑点/痣/胎记等瑕疵&#xff1b;当前主流算法方案可分为传统图像处理方法和基于深度学习的方法&#xff0c;本文重点介绍基…...

2025蓝桥杯省赛网络安全组wp

文章目录 黑客密室逃脱ezEvtxflowzipEnigma星际xml解析器EBC-TrainAES-CBC 黑客密室逃脱 提示猜文件名&#xff0c;猜几个常见的&#xff0c;app.py读到源码 这里也是脑抽了一下&#xff0c;把密钥看成1236了。。。卡了五分钟左右&#xff0c;解出来的时候已经降到300多分了&a…...

【数据结构】·励志大厂版(复习+刷题):二叉树

前引&#xff1a;哈喽小伙伴们&#xff01;经过几个月的间隔&#xff0c;还是逃脱不了再次复习的命运&#xff01;&#xff01;&#xff01;本篇文章没有冗杂的闲话&#xff0c;全是干货教学&#xff0c;带你横扫二叉树的几种遍历&#xff0c;怎么前序、、中序、后续&#xff1…...

Spark-Streaming2

一&#xff0e;有状态转化操作 1. UpdateStateByKey UpdateStateByKey 原语用于记录历史记录&#xff0c;有时&#xff0c;我们需要在 DStream 中跨批次维护状态(例如流计算中累加 wordcount)。针对这种情况&#xff0c;updateStateByKey()为我们提供了对一个状态变量的访问&…...

《深入浅出Git:从版本控制原理到高效协作实战》​

Git的原理和使用 1、Git初识与安装2、Git基本操作2.1、创建Git本地仓库2.2、配置Git2.3、认识工作区、暂存区、版本库2.4、修改文件2.5、版本回退2.6、撤销修改2.7、删除文件 3、Git分支管理3.1、理解分支3.2、创建、切换、合并分支3.3、删除分支3.4、合并冲突3.5、合并模式3.6…...

内耗型选手如何能做到不内耗?

以下是针对「内耗型选手」的系统性解决方案&#xff0c;结合认知神经科学、行为心理学和效能管理理论&#xff0c;提供可落地的策略框架&#xff1a; 一、建立「内耗熵值」监测系统 1. 绘制内耗热力图 用时间轴记录每日内耗触发点&#xff1a; 时间段内耗场景能量损耗值&…...

pyspark将hive数据写入Excel文件中

不多解释直接上代码&#xff0c;少python包的自己直接下载 #!/usr/bin/env python # -*- encoding: utf-8 -*- from pyspark.sql import SparkSession import pandas as pd import os# 初始化 SparkSession 并启用 Hive 支持 spark SparkSession.builder \.appName("sel…...

Java大师成长计划之第5天:Java中的集合框架

&#x1f4e2; 友情提示&#xff1a; 本文由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;平台gpt-4o-mini模型辅助创作完成&#xff0c;旨在提供灵感参考与技术分享&#xff0c;文中关键数据、代码与结论建议通过官方渠道验证。 在 Java 编程中&#xff0c;集合框架…...

rt-linux下的D状态的堆栈抓取及TASK_RTLOCK_WAIT状态

一、背景 在之前的博客 缺页异常导致的iowait打印出相关文件的绝对路径-CSDN博客 里的 2.1 一节里的代码&#xff0c;我们已经有了一个比较强大的抓取D状态和等IO状态超过阈值的waker和wakee的堆栈状态的内核模块。在之前的博客 增加等IO状态的唤醒堆栈打印及缺页异常导致iowa…...

数据结构【堆和链式结构】

堆和链式结构 1.堆的概念和定义1.1堆1.2二叉树的性质 2.堆的实现3.实现链式二叉树3.1链式二叉树的概念3.2前中后遍历3.3遍历&#xff08;举例&#xff09; 1.堆的概念和定义 1.1堆 定义&#xff1a;是特殊的二叉树 #mermaid-svg-vWPNPMGSLe0nGNcd {font-family:"trebuch…...

聊一聊自动化测试

目录 一、自动化测试的定义与核心价值 &#xff08;一&#xff09;什么是自动化测试 &#xff08;二&#xff09;核心价值&#xff1a;从人工到智能的跨越 二、自动化测试的发展阶段 &#xff08;一&#xff09;萌芽阶段&#xff08;早期&#xff09; &#xff08;二&…...

vue2 开发一个实习管理系统电脑端-前端静态网站练习

为了快速的掌握vue2的所学习到的知识点&#xff0c;最近又使用vue2和element-ui 做了一个实习管理系统来巩固自己的前端技术&#xff0c;我觉得对于新手来说&#xff0c;多写代码&#xff0c;多找一些项目练习&#xff0c;是提供自己编程能力的一个很好的办法&#xff0c;这也是…...

【Hive入门】Hive基础操作与SQL语法:DML操作全面解析

目录 1 Hive DML操作概述 2 数据加载操作 2.1 LOAD DATA语句 2.2 INSERT语句 3 数据导出操作 3.1 INSERT OVERWRITE DIRECTORY 3.2 使用HDFS命令导出 4 数据更新与删除 4.1 UPDATE语句 4.2 DELETE语句 5 MERGE操作&#xff08;Hive 2.2&#xff09; 6 性能优化建议…...

C++类和对象(上)

目录 类的定义类定义格式访问限定符类域 实例化实例化概念对象大小 this指针C和C语言实现Stack对比 类的定义 类定义格式 在下面的代码中&#xff0c;class为定义类的关键字&#xff0c;Stack为类的名字&#xff0c;{}中为类的主体&#xff0c; 注意类定义结束时后面分号不能省…...

LS2K0300龙芯开发板——智能车竞赛

开启 LS2K0300 调车之旅&#xff08;自己写的自己慢慢更&#xff0c;可能写的不好欢迎指教&#xff09; 欢迎大家一起讨论共同进步&#xff01;逐飞科技针对 LS2K0300 MCU 开发的开源库&#xff0c;涵盖多种实用功能&#xff0c;助力竞赛与产品开发。以下是快速上手指南&#…...

电子病历高质量语料库构建方法与架构项目(智能质控体系建设篇)

引言 随着人工智能技术的迅猛发展,医疗信息化建设正经历着前所未有的变革。电子病历作为医疗机构的核心数据资产,其质量直接关系到临床决策的准确性和医疗安全。传统的病历质控工作主要依赖人工审核,存在效率低下、主观性强、覆盖面有限等问题。近年来,基于人工智能技术的…...

超级创新思路:基于CBAM-Transformer的强化学习时间序列预测模型(Python\matlab实现)

首先声明,该模型为原创!原创!原创!且该思路还未有成果发表,感兴趣的小伙伴可以借鉴!需要完整代码可私信或评论! 本方案可用于医疗、金融、交通、零售、光伏功率预测、估计预测、天气预测、流量预测、故障检测等领域! 目录 首先声明,该模型为原创!原创!原创!且该思…...

JVM——垃圾收集策略

GC的基本问题 什么是GC&#xff1f; GC 是 garbage collection 的缩写&#xff0c;意思是垃圾回收——把内存&#xff08;特别是堆内存&#xff09;中不再使用的空间释放掉&#xff1b;清理不再使用的对象。 为什么要GC&#xff1f; 堆内存是各个线程共享的空间&#xff0c…...

从基础到实战的量化交易全流程学习:1.3 数学与统计学基础——概率与统计基础 | 数字特征

从基础到实战的量化交易全流程学习&#xff1a;1.3 数学与统计学基础——概率与统计基础 | 数字特征 第一部分&#xff1a;概率与统计基础 第2节&#xff1a;数字特征&#xff1a;期望值、方差、协方差与相关系数 一、期望值&#xff08;Expected Value&#xff09;&#xff1a…...

【MySQL】数据类型和表的操作

目录 一. 常用的数据类型 1.数值类型 1.1 整形类型 1.2 浮点型类型 2.字符串类型 char和varchar的区别 如何选择char和varchar 3.日期类型 4.二进制类型 二. 表的操作 1.查看所有表 2.表的创建 3.查看表的结构 4.表的修改 4.1 添加新的列 4.2 修改表中现有的列 4…...

Tauri打包时出现WixTools以及NSIS报错

前言 Tauri构建时会通过github下载Wix和NSIS&#xff0c;由于国内网络限制&#xff0c;所以这个过程基本都会失败&#xff0c;而且你无法使用挂代理的方式解决此问题&#xff0c;唯一的办法就是先下载对于的库&#xff0c;然后把库丢到对应的文件夹内来解决此问题。。。 文章目…...

Linux操作系统学习---进程地址空间

前言: 在学习c,c这些偏底层的语言时,我们常常会对一个变量取地址,一遍对他进行一系列的操作 . 可是 , 这真的是真实的物理地址吗 ? 其实并非如此 , 通过了解进程地址空间,我们就能解开这个困惑. 一、虚拟地址空间的概念: 同地址,不同值的代码示例: 下面通过创建子进程来看一个…...

docker compose -p的踩坑经验

刚才启动ragflow解析了几百个文件&#xff0c;再次启动登录时报错 没有这个账户&#xff0c;心疼token几秒。。。 再次回顾之前的启动方式和当前的启动方式&#xff0c;才发现有出入。 问题&#xff1a; 第一次启动sudo docker compose up -d 第二次启动sudo docker compose -…...

深入理解 Linux 用户管理:从基础到实践

在 Linux 操作系统中&#xff0c;用户管理是确保系统安全、合理分配资源的核心环节。无论是个人开发者搭建本地开发环境&#xff0c;还是运维人员管理企业级服务器集群&#xff0c;熟练掌握 Linux 用户管理都是一项必备技能。本文将从用户管理的基础概念出发&#xff0c;结合实…...