Linux驱动21 --- FFMPEG 音频 API

 目录

 一、FFMPEG 音频 API

1.1 解码步骤

        创建核心上下文指针

        打开输入流

        获取输入流

        获取解码器

        初始化解码器

        创建输入流指针

        创建输出流指针

        初始化 SDL

        配置音频参数

        打开音频设备

        获取一帧数据

        发送给解码器

        从解码器获取数据

        开辟数据空间

        初始化内存        

        音频重采样配置 --- 相当于视频的格式转换

        由通道数获取默认的通道布局

        初始化重采样核心结构体

        音频重采样

        播放

        延时

1.2 参数扩展

        SDL_AudioSpec

        AVFrame

二、FFMPEG 录制声音的过程

2.1 步骤

        FFMPEG 注册所有  

        FFMPEG 核心上下文申请

        查找音频设备

        注册音频设备

        SDL 初始化

        配置音频参数

        打开音频设备

        读取一帧数据

        写入到文件

三、如何在板子上实现


一、FFMPEG 音频 API

1.1 解码步骤

        创建核心上下文指针

                AVFormatContext * avfmtctx  = avformat_alloc_context();

        打开输入流

                avformat_open_input(&avfmtctx, argv[1], NULL, NULL);

        获取输入流

                avformat_find_stream_info(avfmtctx, NULL);

        获取解码器

                AVCodecContext * avcodectx = avfmtctx->streams[0]->codec;
                AVCodec *avcodec = avcodec_find_decoder(avcodectx->codec_id);

        初始化解码器

                avcodec_open2(avcodectx, avcodec, NULL); 

        创建输入流指针

                AVPacket * avpkt = av_packet_alloc();

        创建输出流指针

                AVFrame * avfrm = av_frame_alloc(); 

        初始化 SDL

        函数头文件

                #include <SDL2/SDL.h>

        函数原型

                int SDL_Init(Uint32 flags)

        函数参数

                常用参数

                        SDL_INIT_TIMER

                        SDL_INIT_AUDIO

                        SDL_INIT_VIDEO

        函数返回值

                成功时返回0,失败时返回负数错误码; 调用SDL_GetError()可以获得本次异常信息。

        配置音频参数

        函数原型

                int SDL_OpenAudioDevice(const char  *device,int iscapture,const SDL_AudioSpec *desired, SDL_AudioSpec *obtained,int allowed_changes);  

        函数参数

                device:音频设备的名称,NULL表示使用默认设备

                iscapture:设为0,非0的值在当前SDL2版本还不支持

                desired:期望得到的音频输出格式

                obtained:实际的输出格式

                allowed_changes:该参数用来指定 当期望和实际的不一样时,能不能够对某一些输出参数进行修改。 设为0,则不能修改。设为如下的值,则可对相应的参数修改:

                        SDL_AUDIO_ALLOW_FREQUENCY_CHANGE

                        SDL_AUDIO_ALLOW_FORMAT_CHANGE

                        SDL_AUDIO_ALLOW_CHANNELS_CHANGE

                        SDL_AUDIO_ALLOW_ANY_CHANGE

        函数返回值

                0失败;成功返回有效音频设备号 >= 2

        打开音频设备

        函数原型

                void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev, int pause_on)

        函数参数

                dev:SDL_OpenAudioDevice函数返回值

                pause_on:根据介绍,填0即可

        av_read_frame

        avcodec_send_packet

        avcodec_receive_frame

        获取一帧数据

                av_read_frame(avfmtctx, avpkt)

        发送给解码器

                avcodec_send_packet(avcodectx, avpkt);

        从解码器获取数据

                avcodec_receive_frame(avcodectx, avfrm);

        开辟数据空间

        函数原型

                int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align)

        函数参数

                linesize:计算的lineize,可能为NULL

                nb_channels:声道数

                SDL_AudioSpec结构体中channels成员变量

                nb_samples:单个通道中的样本数

                        采样频率(Hz) *当前帧的音频采样数/当前帧的音频数据的采样率

                sample_fmt:样本格式

                align:对齐缓冲区大小对齐(0 =默认,1 =无对齐)

        函数返回值

                需要的缓冲区大小,或失败时出现负错误代码

        初始化内存        

                调用av_malloc,然后再将内存内容清零

        函数原型

                void *av_mallocz(size_t size)

                申请数据存放空间

        音频重采样配置 --- 相当于视频的格式转换

        根据输入和输出参数,并设置相关选项

        函数头文件

                #include "libswresample/swresample.h"

        函数原型

        SwrContext *swr_alloc_set_opts(SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx)

        函数参数

s:可选的现有SwrContext,如果不为NULL,则会使用该现有上下文。out_ch_layout:输出声道布局(Channel Layout)通过函数av_get_default_channel_layout获取根据SDL_AudioSpec的channels获取out_sample_fmt:输出采样格式根据SDL_AudioSpec的format成员选取out_sample_rate:输出采样率SDL_AudioSpec的freq成员in_ch_layout:输入声道布局通过函数av_get_default_channel_layout获取输入流codecpar下的channelsin_sample_fmt:输入采样格式输入流codec下的sample_fmtin_sample_rate:输入采样率输入流codec下的sample_ratelog_offset:日志偏移量,填0即可log_ctx:日志上下文,填NULL即可
        由通道数获取默认的通道布局

        函数原型

                int64_t av_get_default_channel_layout(int nb_channels);    

        初始化重采样核心结构体

        函数原型

                int swr_init(struct SwrContext *s);

        函数参数

                s:swr_alloc_set_opts返回值

        音频重采样

                针对每一帧音频的处理。把一帧帧的音频作相应的重采样

        函数原型

                int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in, int in_count);

s:音频重采样的上下文out:输出的指针。传递的输出的数组out_count:输出的样本数量,不是字节数。单通道的样本数量。av_samples_get_buffer_size参数nb_samplesin:输入的数组,AVFrame解码出来的DATA(成员extended_data)in_count:输入的单通道的样本数量AVFrame结构体的nb_samples成员

        函数返回值

                每个通道输出的样本数,失败为负值

        播放

        函数功能

                使用此函数可以在回调设备(即使用了第一套API需要回调函数填充数据的设备)上缓存更多音频,而不必通过回调函数填充音频数据。

        函数原型

                int SDL_QueueAudio(SDL_AudioDeviceID dev, const void* data, Uint32 len)

        函数参数

                dev:设备ID

                data:需要被填充的数据指针

                len:数据buffer长度,byte为单位

                        通过函数av_samples_get_buffer_size获取

        函数返回值

                0表示成功,非零表示出现异常

        //av_samples_get_buffer_size

        延时

        SDL_Delay

        SDL_Delay((输出数据大小) * 1000.0 / (音频采样率 * av_get_bytes_per_sample(音频格式) * 通道数量) - 1);

1.2 参数扩展

        SDL_AudioSpec

int freq;		freq 每秒钟发送给音频设备的sample frame的个数,通常是11025,220502,44100和48000。(sample frame = 样本精度 * 通道数)//输入流codec中sample_rate成员
SDL_AudioFormat format;		fromat 每个样本占用的空间大小及格式,例如 AUDIO_S16SYS,样本是有符号的16位整数,字节顺序(大端还是小端)和系统一样。更多的格式可参考SDL_AudioFormat。// AUDIO_F32SYS
Uint8 channels; 		channels 通道数,在SDL2.0中支持1(mono),2(stereo),4(quad)和6(5.1)//输入流codecpar中channels成员
Uint8 silence;			silence 音频数据中表示静音的值是多少//填0即可
Uint16 samples;		这是每次读取的采样数量,‌决定了音频数据回调的频率。‌例如,‌设置为1024时,‌表示每次读取1024个样本数据,‌回调函数被调用一次。‌这个值不一定是2的幂指数次方,‌最好由AVFrame->nb_samples参数赋值。‌// 512Uint16 padding;		对于某些环境需要Uint32 size;			size 缓冲区的大小(字节为单位),当我们想要更多声音的时候,我们想让SDL给出来的声音缓冲区的尺寸。一个比较合适的值在512到8192之间;ffplay使用1024SDL_AudioCallback callback; /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */		callback用来音频设备缓冲区的回调函数
void *userdata;		userdata在回调函数中使用的数据指针

        AVFrame

typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8uint8_t *data[AV_NUM_DATA_POINTERS]; // 存放媒体数据的指针数组int linesize[AV_NUM_DATA_POINTERS]; // 视频或音频帧数据的行宽uint8_t **extended_data; // 音频或视频数据的指针数组。int width, height; // 视频帧的款和高/*** number of audio samples (per channel) described by this frame*/int nb_samples; // 当前帧的音频采样数(每个通道)int format; // 视频帧的像素格式,见enum AVPixelFormat,或音频的采样格式,见enum AVSampleFormaint key_frame; // 当前帧是否为关键帧,1表示是,0表示不是。AVRational sample_aspect_ratio; // 视频帧的样本宽高比int64_t pts; // 以time_base为单位的呈现时间戳(应向用户显示帧的时间)。int64_t pkt_dts; // 从AVPacket复制而来的dts时间,当没有pts时间是,pkt_dts可以替代pts。int coded_picture_number; // 按解码先后排序的,解码图像数int display_picture_number; // 按显示前后排序的,显示图像数。int quality; // 帧质量,从1~FF_LAMBDA_MAX之间取之,1表示最好,FF_LAMBDA_MAX之间取之表示最坏。void *opaque; // user的私有数据。int interlaced_frame; // 图片的内容是隔行扫描的(交错帧)。int top_field_first; // 如果内容是隔行扫描的,则首先显示顶部字段。int sample_rate; // 音频数据的采样率uint64_t channel_layout; // 音频数据的通道布局。/*** AVBuffer引用,当前帧数据。 如果所有的元素为NULL,则此帧不是引用计数。 必须连续填充此数组,* 即如果buf [i]为非NULL,j <i,buf[j]也必须为非NULL。** 每个数据平面最多可以有一个AVBuffer,因此对于视频,此数组始终包含所有引用。 * 对于具有多于AV_NUM_DATA_POINTERS个通道的平面音频,可能有多个缓冲区可以容纳在此阵列中。 * 然后额外的AVBufferRef指针存储在extended_buf数组中。*/AVBufferRef *buf[AV_NUM_DATA_POINTERS];AVBufferRef **extended_buf; // AVBufferRef的指针int        nb_extended_buf; // extended_buf的数量enum AVColorSpace colorspace; // YUV颜色空间类型。int64_t best_effort_timestamp; // 算法预测的timestampint64_t pkt_pos; // 记录上一个AVPacket输入解码器的位置。int64_t pkt_duration; // packet的durationAVDictionary *metadata;int channels; // 音频的通道数。int pkt_size; // 包含压缩帧的相应数据包的大小。} AVFrame;

二、FFMPEG 录制声音的过程

2.1 步骤

        FFMPEG 注册所有  

        头文件

                #include "libavdevice/avdevice.h"
        函数原型

                void avdevice_register_all(void)

        FFMPEG 核心上下文申请

                AVFormatContext * avfmtctx  = avformat_alloc_context();

        查找音频设备

        函数原型

                AVInputFormat *av_find_input_format(const char *short_name)

        函数参数

                直接填alsa即可

        函数返回值

                就是需要的输入设备的核心上下文指针

        注册音频设备

        函数原型

                int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)

        函数参数

                ps:FFMPEG的核心上下文指针

                url:在此需要使用声卡的名字

                "plughw:CARD=AudioPCI,DEV=0"

                fmt:av_find_input_format函数返回值

                options:填NULL

        SDL 初始化

                SDL_Init(SDL_INIT_AUDIO);

        配置音频参数

        函数原型

                int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)

                        desired:想要的配置

                        obtained:实际得到的配置,此处填NULL即可

        打开音频设备

                void SDL_PauseAudio(int pause_on)

        读取一帧数据

                int av_read_frame(AVFormatContext *s, AVPacket *pkt)

        写入到文件

                fwrite

三、如何在板子上实现

1、在 buildroot 中勾选 ffmpeg 选项、SDL 选项

2、编译文件系统 --- 生成新的文件系统

3、烧录新的文件系统

4、和之前 LVGL 相同 --- 修改 Makefile

        4.1 CC 换成 buildroot 的交叉编译工具

        4.2 把之前该删除的依赖库删除,把需要的库给加上

5、编译

        可能出现的问题

        buildroot 支持的 ffmpeg 和 SDL 版本和程序中使用的版本不符

6、运行

代码

dec_audio.c //音频

#include <stdio.h>
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
#include <SDL2/SDL.h>int main(int argc, char *argv[])
{if(argc < 2){printf("./play <name>\n");return 0;}//创建核心上下文指针AVFormatContext * avfmtctx  = avformat_alloc_context();//打开输入流avformat_open_input(&avfmtctx, argv[1], NULL, NULL);//获取输入流avformat_find_stream_info(avfmtctx, NULL); //到此会获取//输入流获取之后获取的是纯音频文件,只有一个流 ,所以还用 avfmt->streams[0]//有的音频,会带一个图片封面 --- 这种音频会报段错误//获取解码器AVCodecContext * avcodectx = avfmtctx->streams[0]->codec;AVCodec *avcodec = avcodec_find_decoder(avcodectx->codec_id);//初始化解码器avcodec_open2(avcodectx, avcodec, NULL); //创建输入流指针AVPacket * avpkt = av_packet_alloc();   //存放输入流中一帧图像//创建输出流指针AVFrame * avfrm = av_frame_alloc(); //初始化SDLSDL_Init(SDL_INIT_AUDIO);//配置音频参数SDL_AudioSpec desired, obtained;    //一个期望的,一个获得的desired.callback = NULL;desired.channels = 2;    //期望的通道数desired.format = AUDIO_S16SYS;  //音频的格式desired.freq = avcodectx->sample_rate;    //采样率 --- 需要注意desired.padding = 0;desired.samples = 1152; //采样数desired.silence = 0;desired.size = 0;       //desired.userdata = NULL;//打开音频设备SDL_AudioDeviceID aid = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);  //理论上ID会大于0//启动音频设备SDLCALL SDL_PauseAudioDevice(aid, 0);enum AVSampleFormat mysfmt;switch(obtained.format){case AUDIO_S16SYS: mysfmt = AV_SAMPLE_FMT_S16; break;case AUDIO_S32SYS: mysfmt = AV_SAMPLE_FMT_S32; break;case AUDIO_F32SYS: mysfmt = AV_SAMPLE_FMT_FLT; break;}int size;uint8_t *data = NULL;while(1){//获取一帧数据if(av_read_frame(avfmtctx, avpkt) != 0){printf("获取文件错误/到达文件结尾\n");break;}//发送给解码器avcodec_send_packet(avcodectx, avpkt);//从解码器获取数据avcodec_receive_frame(avcodectx, avfrm);    //第一帧和第二帧获取的大小不一样 --- 把开辟空间方在里面//开辟数据空间size = av_samples_get_buffer_size(NULL, obtained.channels, avfrm->nb_samples, mysfmt, 0);//初始化内存data = av_mallocz(size);//音频重采样配置 --- 相当于视频的格式转换struct SwrContext * swrctx = swr_alloc_set_opts(NULL, av_get_default_channel_layout(obtained.channels), mysfmt, obtained.freq, \av_get_default_channel_layout(avcodectx->channels), avcodectx->sample_fmt, avcodectx->sample_rate, 0, NULL);//初始化重采样核心结构体swr_init(swrctx);//音频重采样swr_convert(swrctx, &data, size, avfrm->extended_data, avfrm->nb_samples);//播放SDL_QueueAudio(aid, data, size);//延时//SDL_Delay((输出数据大小) * 1000.0 / (音频采样率 * av_get_bytes_per_sample(音频格式) * 通道数量) - 1);SDL_Delay((size) * 1000.0 / (obtained.freq * av_get_bytes_per_sample(mysfmt) * obtained.channels) - 1);    //网上有两种说法,1.当前的音频播放需要时间 2.音频帧不够,通过延时,补全av_free(data);}
}

get_audio.c //录音

#include <stdio.h>
#include "libavformat/avformat.h"
#include <SDL2/SDL.h>
#include <pthread.h>
#include <unistd.h>
#include "libavdevice/avdevice.h"int end_flag = 0;void *pthread_count_func(void *arg)
{int num = 0;while(num--){sleep(1);printf("录音剩余 %d 秒\n", num);}end_flag = 1;
}int main(void)
{//FFMPEG注册所有 --- 必须写avdevice_register_all();//FFMPEG核心上下文申请AVFormatContext * avfmtctx  = avformat_alloc_context();//查找音频设备AVInputFormat * avifmt = av_find_input_format("alsa");//注册音频设备avformat_open_input(&avfmtctx, "hw:CARD=AudioPCI,DEV=0", avifmt, NULL);//SDL初始化SDL_Init(SDL_INIT_AUDIO);//配置音频参数 --- 再此配置为期望的,得到的填NULL即可SDL_AudioSpec desired;    //一个期望的,一个获得的desired.callback = NULL;desired.channels = 2;    //期望的通道数desired.format = AUDIO_S16SYS;  //音频的格式desired.freq = 48000;    //采样率 --- 过低声音会很奇怪desired.padding = 0;desired.samples = 1152; //采样数desired.silence = 0;desired.size = 0;       //desired.userdata = NULL;SDL_OpenAudio(&desired, NULL);//打开音频设备SDL_PauseAudio(0);AVPacket * avpkt = av_packet_alloc();   //存放输入流中一帧数据FILE *file = fopen("./9203.pcm", "w");pthread_t pd = 0;pthread_create(&pd, NULL, pthread_count_func, NULL);while(1){if(end_flag){break;}//读取一帧数据av_read_frame(avfmtctx, avpkt);//写入到文件fwrite(avpkt->data, 1, avpkt->size, file);}fclose(file);return 0;
}

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

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

相关文章

《计算机“十万个为什么”》之 [特殊字符] 序列化与反序列化:数据打包的奇妙之旅 ✈️

《计算机“十万个为什么”》之 &#x1f4e6; 序列化与反序列化&#xff1a;数据打包的奇妙之旅 ✈️欢迎来到计算机“十万个为什么”系列&#xff01; 本文将以「序列化与反序列化」为主题&#xff0c;深入探讨计算机世界中数据的打包与解包过程。 让我们一起解开数据的神秘面…

机器学习与深度学习评价指标

机器学习与深度学习评价指标完全指南 📊 为什么需要评价指标? 想象你是一位医生,需要判断一个诊断模型的好坏。如果模型说"这个病人有癌症",你需要知道: 这个判断有多准确? 会不会漏掉真正的癌症患者? 会不会误诊健康的人? 评价指标就像是给AI模型打分的&…

Hugging Face-环境配置

打开anaconda promptconda activate pytorchpip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers datasets tokenizerspycharm找到pytorch下的python.exe#将模型下载到本地调用 from transformers import AutoModelForCausalLM,AutoTokenizer#将模型和分词工…

cnn中池化层作用

一、池化层概述 在卷积神经网络中&#xff0c;池化层是核心组件之一&#xff0c;主要作用是逐步降低特征图的空间尺寸即宽和高&#xff0c;从而减少计算量、控制过拟合并增强模型的鲁棒性。 核心作用 降维与减少计算量 压缩特征图的尺寸&#xff0c;显著减少后续层的参数数量和…

写一个音乐爬虫

今天我们写一个网易云音乐的爬虫&#xff0c;爬取网易云音乐热歌榜音乐链接并下载&#xff0c;这里用到了之前引用的BeautifulSoup和requests。 BeautifulSoup是一个Python库&#xff0c;用于从HTML和XML文件中提取数据。它提供了一种简单的方式来遍历文档树和搜索文档树中的元…

战斗公式和伤害走配置文件

故事背景&#xff0c;上次属性计算用的配置&#xff0c;这次伤害计算也走配置&#xff0c;下面是测试代码和测试数据local formulas {[100001]{id 100001,name "基础伤害",formula "function (self,tag,ishit,iscritial,counterratio)\n if ishit1 then\n …

线性代数 上

文章目录线性代数知识整理一、求行列式1、 套公式2、利用性质&#xff0c;化为可套公式3、抽象行列式4、抽象向量二、代数余子式的线性组合三、求AnA^nAn四、证明A可逆五、求A的逆1、定义法2、初等变换3、公式六、求秩七、线性表示的判定八、线性无关九、求极大线性无关组十、等…

红帽AI推理服务器三大特点

生成式人工智能&#xff08;Gen AI&#xff09;的迅猛发展&#xff0c;对大型语言模型&#xff08;LLM&#xff09;的部署提出了更高的性能、灵活性和效率要求。无论部署在何种环境中&#xff0c;红帽AI推理服务器都为用户提供经过强化并获得官方支持的vLLM发行版&#xff0c;配…

开始记录一步步学习pcl

安装参考&#xff0c;大神写的非常详细&#xff0c;一步到位 https://blog.csdn.net/qq_36812406/article/details/144307648?ops_request_misc%257B%2522request%255Fid%2522%253A%25220e215e6ac266b90ded12ed6b2eab1257%2522%252C%2522scm%2522%253A%252220140713.13010233…

Linux系统Centos7 安装mysql5.7教程 和mysql的简单指令

目录 一. 安装 MySQL 官方 Yum 仓库 二. 安装 MySQL 5.7 1.查看可用的mysql版本仓库 2.启用MySql5.7仓库 3.禁用更高版本的仓库&#xff08;可选&#xff09; 4.导入 MySQL GPG 公钥 5.安装MySql5.7 三. 启动 MySQL 服务 1.启动 MySQL 服务 2. 设置开机自启 3.查看服…

嵌入式——C语言:指针③

一、函数指针和指针函数&#xff08;一&#xff09;指针函数&#xff1a;是函数&#xff0c;函数的返回值是指针1.不能返回局部变量的值2.指针函数返回的地址可以作为下一个函数调用的参数&#xff08;二&#xff09;函数指针&#xff1a;是指针&#xff0c;指针指向一个函数in…

OpenCV(05)直方图均衡化,模板匹配,霍夫变换,图像亮度变换,形态学变换

【OpenCV&#xff08;01&#xff09;】基本图像操作、绘制&#xff0c;读取视频 【OpenCV&#xff08;02&#xff09;】图像颜色处理&#xff0c;灰度化&#xff0c;二值化&#xff0c;仿射变换 【OpenCV&#xff08;03&#xff09;】插值方法&#xff0c;边缘填充&#xff0…

常见的未授权访问漏洞靶场-练习教程

一.Redis未授权访问漏洞1.首先需要准备一个vps和vulhub靶场&#xff0c;然后进入目录。命令:进入靶场目录&#xff1a;cd /etc/vulhub-master/redis/4-unacc 启动靶场&#xff1a;docker-compose up -d2.然后启动我们kali,下载redis服务然后连接redis&#xff0c;并执行命令。…

EAP(基于事件的异步编程模式)

&#x1f4dc; 1. 核心思想 &#x1f4cc; 事件驱动解耦 异步操作通过事件通知结果&#xff0c;调用者无需阻塞线程&#xff0c;通过事件处理器响应操作完成、错误或取消。 &#x1f4cc; 线程池与UI线程协同 耗时操作在后台线程池执行&#xff0c;完成后通过 SynchronizationC…

【三桥君】如何解决后端Agent和前端UI之间的交互问题?——解析AG-UI协议的神奇作用

​你好&#xff0c;我是 ✨三桥君✨ &#x1f4cc;本文介绍&#x1f4cc; >> 一、引言 在智能体&#xff08;Agent&#xff09;领域&#xff0c;MCP、A2A、ANP等协议已经规范了Agent与工具、Agent与Agent之间的通信&#xff0c;但Agent与用户之间的交互一直缺乏标准化。…

面试官:详细说说Kafka rebalance 的策略以及具体过程

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天又来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 程序员各种工具大全 Kafka 的 Rebalance&#xff08;再平衡&#xff09; 是消费者组&#xff08;Consumer Group&#xff09;在消费者数量…

C++入门自学Day2-- c++类与对象(初识)

一、面向对象和面向过程1、什么是面向过程&#xff08;Process-Oriented Programming, POP&#xff09;&#x1f4cc; 定义面向过程强调的是 过程&#xff08;过程函数&#xff09;&#xff0c;即&#xff1a;按照步骤&#xff08;流程&#xff09;组织代码。程序结构 数据结构…

DAO组织智能合约开发:从理论到实践

目录 DAO组织智能合约开发:从理论到实践 1. DAO概述:去中心化自治组织 2. DAO核心组件设计 2.1 架构设计 2.2 关键智能合约 3. 治理代币实现 3.1 ERC20扩展合约 4. 提案管理系统实现 4.1 提案状态机 4.2 提案合约实现 5. DAO核心合约实现 5.1 DAO合约架构 5.2 提案类型扩展 6…

Ubuntu系统完整配置教程

Ubuntu系统完整配置教程 目录 配置镜像源安装网络服务虚拟机中安装CUDAPython开发环境配置Java开发环境配置 1. 配置镜像源 1.1 备份原始源文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup1.2 编辑源文件 sudo nano /etc/apt/sources.list1.3 各大镜像源…

【mysql慢查询】

mysql慢查询慢查询慢查询日志配置慢查询 慢查询是指执行时间超过指定阈值的SQL语句。在MySQL中&#xff0c;默认情况下执行时间超过10秒的查询会被认为是慢查询&#xff0c;但这个阈值可以根据需要进行调整。 慢查询日志配置 -- 查看当前慢查询配置 SHOW VARIABLES LIKE slo…