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

基于ffmpeg的音视频编码

1 音频编码

本质上是由pcm文件转到一个协议文件 比如说aac协议

1.1 音频基本知识回归

  • 比特率
    比特率是指单位时间内传输或处理的比特(bit)数量,通常用 bps(bits per second,比特每秒)来表示。它是衡量数据传输速度和通信系统能力的重要指标。
  • 码率
    一般为编码之后,单位时间内传输的字节数
  • 声道布局

声道布局是指在音频系统中,各个声道的扬声器在空间中的分布方式以及它们所承担的音频信息分配方式。以下是一些常见的声道布局简介:
单声道:只有一个声道,所有音频信息都通过一个扬声器播放,声音缺乏空间感和立体感,常用于一些简单的音频设备或对音频要求不高的场景。
立体声:有左声道和右声道两个声道,通过两个扬声器分别播放不同的音频信号,模拟人耳听到声音的立体感,能让听众感受到声音的左右位置差异,营造出一定的空间感,是音乐播放、电影音频等常见的声道布局。
5.1 声道:由左前、中置、右前、左环绕、右环绕五个扬声器以及一个重低音扬声器(.1 表示)组成。左前、中置和右前扬声器主要负责前方的声音,包括人物对话、主要乐器声等;左环绕和右环绕扬声器用于营造环境音效和后方声音,增强沉浸感;重低音扬声器专门负责低频音效,如爆炸声、雷声等,能提升声音的震撼力,常用于家庭影院系统。
7.1 声道:在 5.1 声道的基础上,增加了左后环绕和右后环绕两个声道,进一步增强了后方的声音细节和空间感,使听众能更清晰地感受到来自后方各个方向的声音,提供更逼真的环绕音效,常用于高端影院和一些专业音频制作环境。

  • 采样率
    采样率是指在单位时间内对模拟信号进行采样的次数,通常用赫兹(Hz)来表示
  • 采样格式
    即一个样本点多少位存放

packed格式:交错
1 AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
2 AV_SAMPLE_FMT_S16, ///< signed 16 bits
3 AV_SAMPLE_FMT_S32, ///< signed 32 bits
4 AV_SAMPLE_FMT_FLT, ///< float
5 AV_SAMPLE_FMT_DBL, ///< double

planar格式 左右分别存放
1 AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
2 AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
3 AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
4 AV_SAMPLE_FMT_FLTP, ///< float, planar
5 AV_SAMPLE_FMT_DBLP, ///< double, planar
6 AV_SAMPLE_FMT_S64, ///< signed 64 bits
7 AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar

  • 一帧大小
    计算出每一帧的数据 单个采样点的字节 * 通道数目 * 每帧采样点数量
  • aac协议
    aac协议由一个adts头和一个音频数据包组成 一般希望planar格式
  • 编码器选择
    ffmpeg默认的aac编码器,默认编译出来的每帧数据都不带adts,但lib_fdk aac默认是带了adts header,而且此时codec_ctx->flags的值都为0.
    这样我们没法判断是否需要自己额外写入adts,因此我们在设置编码的时候可以直接将codec_ctx->flags = AV_CODEC_FLAG_GLOBAL_HEADER; 大家都不带adts

2.2 编码流程

在这里插入图片描述


const AVCodec *codec = NULL;//编码器
AVCodecContext *codec_ctx= NULL;//编码器设置codec = avcodec_find_encoder(codec_id)
codec_ctx = avcodec_alloc_context3(codec)codec_ctx->codec_id = codec_id;//idcodec_ctx->codec_type = AVMEDIA_TYPE_AUDIO;//typecodec_ctx->bit_rate = 128*1024;//码率codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;//立体声音codec_ctx->sample_rate    = 48000; //48000 采样率codec_ctx->channels       = av_get_channel_layout_nb_channels(codec_ctx->channel_layout);codec_ctx->profile = FF_PROFILE_AAC_LOW;    //低水平if(strcmp(codec->name, "aac") == 0) {codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;} else if(strcmp(codec->name, "libfdk_aac") == 0) {codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16;} else {codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;}//采样格式/* 检测支持采样格式支持情况 */if (!check_sample_fmt(codec, codec_ctx->sample_fmt)) {fprintf(stderr, "Encoder does not support sample format %s",av_get_sample_fmt_name(codec_ctx->sample_fmt));exit(1);}if (!check_sample_rate(codec, codec_ctx->sample_rate)) {fprintf(stderr, "Encoder does not support sample rate %d", codec_ctx->sample_rate);exit(1);}if (!check_channel_layout(codec, codec_ctx->channel_layout)) {fprintf(stderr, "Encoder does not support channel layout %lu", codec_ctx->channel_layout);exit(1);}codec_ctx->flags = AV_CODEC_FLAG_GLOBAL_HEADER;
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {fprintf(stderr, "Could not open codec\n");exit(1);}

这一部分 无疑完成编码器的初始化
先找编码器->再初始化上下文->再连接再一起

note:不同的编码器对采样格式有性能限制,aac编码器倾向于planar格式编码,libfdk_aac倾向于packed格式编码


AVFrame *frame = NULL;//为原始数据
AVPacket *pkt = NULL;//编码数据
pkt = av_packet_alloc();
frame = av_frame_alloc();frame->nb_samples     = codec_ctx->frame_size;//一帧多少采样点frame->format         = codec_ctx->sample_fmt;//音频深度frame->channel_layout = codec_ctx->channel_layout;frame->channels = av_get_channel_layout_nb_channels(frame->channel_layout);ret = av_frame_get_buffer(frame, 0);int frame_bytes = av_get_bytes_per_sample(frame->format) * frame->channels * frame->nb_samples;uint8_t *pcm_buf = (uint8_t *)malloc(frame_bytes);
size_t read_bytes = fread(pcm_buf, 1, frame_bytes, infile);ret = av_frame_make_writable(frame);ret = av_samples_fill_arrays(frame->data, frame->linesize,pcm_buf, frame->channels,frame->nb_samples, frame->format, 0);

分配帧和数据包->初始化帧(给帧分配大小)->填充帧

ret = av_frame_get_buffer(frame, 0);0为让ffmpeg选择 是否对齐
av_samples_fill_arrays

uint8_t **audio_data
作用:这是一个指向指针数组的指针,用于存储每个声道的音频数据指针。AVFrame 中的 data 成员通常就是这样一个指针数组,用于存储不同声道的数据。例如,对于立体声(2 个声道),audio_data[0] 指向左声道数据,audio_data[1] 指向右声道数据。
示例:在 AVFrame 中使用时,通常传入 frame->data。
2. int *linesize
作用:这是一个指向整数数组的指针,用于存储每个声道数据的每行字节数(在音频数据中,“行” 可以理解为一个样本块)。这个值对于音频数据的正确处理非常重要,因为它表示了每个声道数据在内存中的布局信息。AVFrame 中的 linesize 成员就是用于存储这些信息的。
示例:在 AVFrame 中使用时,通常传入 frame->linesize。
3. const uint8_t *buf
作用:这是一个指向包含原始音频样本数据的缓冲区的指针。该缓冲区包含了要填充到 AVFrame 中的音频数据。
示例:在你的代码中,pcm_temp_buf 就是存储原始 PCM 音频数据的缓冲区,所以这里传入 pcm_temp_buf。
4. int nb_channels
作用:表示音频数据的声道数。例如,单声道音频的 nb_channels 为 1,立体声音频的 nb_channels 为 2。
示例:在 AVFrame 中使用时,通常传入 frame->channels。
?5. int nb_samples
作用:表示每个声道的样本数量。样本是音频数据的基本单位,nb_samples 决定了音频数据的时长和大小。
示例:在 AVFrame 中使用时,通常传入 frame->nb_samples。
6. enum AVSampleFormat sample_fmt
作用:表示音频样本的格式,它指定了每个样本的位深度、存储方式等信息。常见的样本格式有 AV_SAMPLE_FMT_S16(16 位有符号整数)、AV_SAMPLE_FMT_FLTP(浮点型平面格式)等。
示例:在 AVFrame 中使用时,通常传入 frame->format。
7. int align
作用:指定内存对齐方式。内存对齐可以提高内存访问效率,通常传入 0 让 FFmpeg 自动选择合适的对齐方式。


static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *output)
{int ret;/* send the frame for encoding */ret = avcodec_send_frame(ctx, frame);if (ret < 0) {fprintf(stderr, "Error sending the frame to the encoder\n");return -1;}/* read all the available output packets (in general there may be any number of them */// 编码和解码都是一样的,都是send 1次,然后receive多次, 直到AVERROR(EAGAIN)或者AVERROR_EOFwhile (ret >= 0) {ret = avcodec_receive_packet(ctx, pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if (ret < 0) {fprintf(stderr, "Error encoding audio frame\n");return -1;}size_t len = 0;printf("ctx->flags:0x%x & AV_CODEC_FLAG_GLOBAL_HEADER:0x%x, name:%s\n",ctx->flags, ctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER, ctx->codec->name);if((ctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {// 需要额外的adts header写入uint8_t aac_header[7];get_adts_header(ctx, aac_header, pkt->size);len = fwrite(aac_header, 1, 7, output);if(len != 7) {fprintf(stderr, "fwrite aac_header failed\n");return -1;}}len = fwrite(pkt->data, 1, pkt->size, output);if(len != pkt->size) {fprintf(stderr, "fwrite aac data failed\n");return -1;}
}return -1;
}

发送帧->接受帧->写入文件

引入一个函数


2 视频编码

本质上是将一个yuv 变成一个h264文件

2.1 h264编码细节推荐

1 什么是视频码率
视频码率是视频数据(包含视频⾊彩量、亮度量、像素量)每秒输出的位数。⼀般⽤的单位是kbps。
2 设置视频码率的必要性
在⽹络视频应⽤中,视频质量和⽹络带宽占⽤是相⽭盾的。通常情况下,视频流占⽤的带宽越⾼则视频
质量也越⾼,需要的⽹络带宽也越⼤,解决这⼀⽭盾的钥匙当然是视频编解码技术。评判⼀种视频编解码技术的优劣,是⽐较在相同的带宽条件下,哪个视频质量更好;在相同的视频质量条件下,哪个占⽤的⽹络带宽更少(⽂件体积⼩)。
是不是视频码率越⾼,质量越好呢?理论上是这样的。然⽽在我们⾁眼分辨的范围内,当码率⾼到⼀定程度时,就没有什么差别了。所以码率设置有它的最优值,H.264(也叫AVC或X264)的⽂件中,视频的建议码率如下
在这里插入图片描述
3 –preset的参数主要调节编码速度和质量的平衡,有ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo这10个选项,从快到慢。

4 –tune的参数主要配合视频类型和视觉优化的参数,或特别的情况。如果视频的内容符合其中一个可用的调整值又或者有其中需要,则可以使用此选项,否则建议不使用(如tune grain是为高比特率的编码而设计的)。tune的值有:
film: 电影、真人类型;
animation: 动画;
grain: 需要保留大量的grain时用;
stillimage: 静态图像编码时使用;
psnr: 为提高psnr做了优化的参数;
ssim: 为提高ssim做了优化的参数;
fastdecode: 可以快速解码的参数;
zerolatency:零延迟,用在需要非常低的延迟的情况下,比如电视电话会议的编码。
5 在 H.264 编码中,profile(配置文件)用于指定编码视频流的特性和功能集合,不同的profile适用于不同的应用场景和设备。常见的 H.264 profile值及其特点如下:

  • Baseline Profile(基线配置文件)
    支持 I 帧(关键帧)和 P 帧(预测帧),不支持 B 帧(双向预测帧)。
    主要用于低延迟、低复杂度的应用,如视频会议、实时监控等。
    能够在相对较低的码率下提供较好的视频质量,适用于带宽有限的情况。
  • Main Profile(主配置文件)
    支持 I 帧、P 帧和 B 帧,提供了更高效的压缩性能。
    适用于大多数传统的视频应用,如视频存储、视频广播等。
    在相同的视频质量下,Main Profile 通常比 Baseline Profile 需要更高的码率,但能实现更好的压缩效果。
  • High Profile(高配置文件)
    进一步提高了压缩效率,支持更多的编码工具和特性,如更多的量化矩阵、自适应环路滤波等。
    主要用于高清和蓝光视频等对视频质量要求较高的应用。
    能够在高分辨率和高帧率的情况下提供出色的视频质量,但编码和解码的复杂度也相对较高。

baseline profile多应⽤于实时通信领域;
main profile多应⽤于流媒体领域;
high profile则多应⽤于⼴电和存储领域

6 bframes: I帧和P帧或者两个P帧之间可⽤的最⼤连续B帧数量,默认值为3。B帧可使⽤双向预测,从⽽显著提⾼压缩率,但由于需要缓存更多的帧数以及重排序的原因,会降低编码速度,增加编码延迟,因此在实时编码时也建议将该值设置为0。
在这里插入图片描述


const AVCodec *codec = NULL;
AVCodecContext *codec_ctx= NULL;codec = avcodec_find_encoder_by_name(codec_name);if (!codec) {fprintf(stderr, "Codec '%s' not found\n", codec_name);exit(1);}codec_ctx = avcodec_alloc_context3(codec);if (!codec_ctx) {fprintf(stderr, "Could not allocate video codec context\n");exit(1);}
codec_ctx->width = 1280;
codec_ctx->height = 720;
codec_ctx->time_base = (AVRational){1, 25};
codec_ctx->framerate = (AVRational){25, 1};
codec_ctx->gop_size = 25;   // I帧间隔
codec_ctx->max_b_frames = 2; // 如果不想包含B帧则设置为0
codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;* // ultrafast all encode time:2270ms// medium all encode time:5815ms// veryslow all encode time:19836ms*/ret = av_opt_set(codec_ctx->priv_data, "preset", "medium", 0);if(ret != 0) {printf("av_opt_set preset failed\n");}/*profile 参数:profile 表示 H.264 编码的配置文件,这里设置为 main。* 不同的 profile 支持不同的编码特性和功能,main 配置文件提供了基本的编码功能,适用于大多数视频应用场景。*/ret = av_opt_set(codec_ctx->priv_data, "profile", "main", 0); // 默认是highif(ret != 0) {printf("av_opt_set profile failed\n");}/*tune 参数:tune 表示针对特定应用场景进行优化,* 这里设置为 zerolatency,表示进行零延迟编码,适用于直播等对延迟要求较高的场景。*/ret = av_opt_set(codec_ctx->priv_data, "tune","zerolatency",0);codec_ctx->bit_rate = 3000000;ret = avcodec_open2(codec_ctx, codec, NULL);if (ret < 0) {fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));exit(1);}

同理 先找编码器->初始化上下文->再绑定


AVFrame *frame = NULL;
AVPacket *pkt = NULL;pkt = av_packet_alloc();if (!pkt) {fprintf(stderr, "Could not allocate video frame\n");exit(1);}frame = av_frame_alloc();if (!frame) {fprintf(stderr, "Could not allocate video frame\n");exit(1);}// 为frame分配bufferframe->format = codec_ctx->pix_fmt;frame->width  = codec_ctx->width;frame->height = codec_ctx->height;ret = av_frame_get_buffer(frame, 0);int frame_bytes = av_image_get_buffer_size(frame->format, frame->width,frame->height, 1);
int8_t *yuv_buf = (uint8_t *)malloc(frame_bytes);ret = av_frame_make_writable(frame);int need_size = av_image_fill_arrays(frame->data, frame->linesize, yuv_buf,frame->format,frame->width, frame->height, 1);

同理 设置帧参数


static int encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,FILE *outfile)
{int ret;/* send the frame to the encoder */if (frame)printf("Send frame %3"PRId64"\n", frame->pts);/* 通过查阅代码,使用x264进行编码时,具体缓存帧是在x264源码进行,* 不会增加avframe对应buffer的reference*/ret = avcodec_send_frame(enc_ctx, frame);if (ret < 0){fprintf(stderr, "Error sending a frame for encoding\n");return -1;}while (ret >= 0){ret = avcodec_receive_packet(enc_ctx, pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if (ret < 0) {fprintf(stderr, "Error encoding audio frame\n");return -1;}if(pkt->flags & AV_PKT_FLAG_KEY)//该数据包是否为关键帧printf("Write packet flags:%d pts:%3"PRId64" dts:%3"PRId64" (size:%5d)\n",pkt->flags, pkt->pts, pkt->dts, pkt->size);if(!pkt->flags)printf("Write packet flags:%d pts:%3"PRId64" dts:%3"PRId64" (size:%5d)\n",pkt->flags, pkt->pts, pkt->dts, pkt->size);fwrite(pkt->data, 1, pkt->size, outfile);}return 0

int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr);
此函数把输入的 AVFrame 编码成一个或多个 AVPacket,使用单个函数调用完成编码过程。got_packet_ptr 用于指示是否生成了有效的数据包。
avcodec_encode_video2:是一个同步接口,在一次调用里完成帧的发送和编码后数据包的接收。若编码器有缓存帧,可能需要多次调用该函数才能处理完所有缓存帧。


3 共同点

1.为什么要冲刷编码器

  • 清空缓存:编码器通常会有内部缓存来存储尚未输出的编码数据。在编码结束时或某些特定情况下,如切换编码参数、结束编码流程等,需要冲刷编码器,以确保这些缓存中的数据被完整地输出,避免数据丢失。
  • 保证数据完整性:冲刷操作可以使编码器将所有已处理但未发送的编码数据包发送出来,从而保证编码后的数据在文件或流中的完整性,使得后续的解码和播放等操作能够顺利进行。
  • 避免延迟:如果不进行冲刷,缓存中的数据可能会一直滞留在编码器中,导致输出延迟。冲刷编码器能够及时将数据输出,降低整体的编码延迟,特别是在实时性要求较高的场景,如直播、视频会议等中,这一点尤为重要。
  • 资源释放与重置:冲刷编码器有时也与资源的释放和重置相关。在完成一次编码任务后,通过冲刷可以清理编码器内部的临时资源,为下一次编码任务做好准备,确保编码器处于正确的初始状态,避免残留数据或状态对新的编码过程产生干扰。

2 为什么不要取消计数引用
avcodec_receive_packet 函数内部第一个调用的就是 av_packet_unref,它会对 AVPacket 进行引用计数的递减操作,并在引用计数为 0 时释放相关的资源。如果在外部再次手动调用 av_packet_unref,就会导致对同一个 AVPacket 的引用计数错误地多减一次,可能会造成资源过早释放,后续如果再使用该 AVPacket 相关的指针或数据,就会引发错误,比如出现野指针访问、程序崩溃等问题。

3 如何放入队列
由于编码器会释放数据,不能直接将原始的 pkt 插入到队列中。正确的做法是新分配一个 AVPacket,然后使用 av_packet_move_ref 函数将原始 pkt 对应的缓冲区转移到新分配的 AVPacket 中,再将新的 AVPacket 放入队列。这样做可以保证队列中的 AVPacket 拥有独立的缓冲区,不会因为编码器释放原始 pkt 的数据而导致队列中的数据被破坏。在放入队列时,还需要确保队列的操作是线程安全的,以避免多线程环境下的竞争条件和数据不一致问题。

4 流程不同
即aac要加头文件,以及编码器设置参数不一样 ,以及由两个api av_image_fill_arrays和av_samples_fill_arrays 不同

相关文章:

基于ffmpeg的音视频编码

1 音频编码 本质上是由pcm文件转到一个协议文件 比如说aac协议 1.1 音频基本知识回归 比特率 比特率是指单位时间内传输或处理的比特&#xff08;bit&#xff09;数量&#xff0c;通常用 bps&#xff08;bits per second&#xff0c;比特每秒&#xff09;来表示。它是衡量数…...

Android wifi开发调试总结

Android wifi开发调试简单总结 文章目录 Android wifi开发调试简单总结一、前言二、wifi demo开发1、开关和连接2、wifi开启主要流程3 、wifi主要广播4、相关日志5、demo示例 三、其他1、Wifi开发小结2、其他wifi知识小结&#xff08;1&#xff09;Android无线Wifi开发&#xf…...

LLVIP、KAIST、M3FD数据集

LLVIP、KAIST、M3FD数据集 &#xff08;可见光红外&#xff0c;双模态数据集&#xff0c;已配准已对齐已清洗&#xff0c;已处理为txt格式&#xff0c;YOLO可直接训练&#xff09; 电子产品&#xff0c;一经出售&#xff0c;概不退换 算法设计、毕业设计、期刊专利&#xff01;…...

datasets 数据处理封装后,统一处理流程以避免Dataset Map顺序依赖问题

文章目录 处理流程说明小结 在实际项目中&#xff0c;我们常常需要对数据集进行预处理。为了规范操作&#xff0c;我封装了一个基础数据集处理类&#xff1a; class DatasetAbstract:"""所有数据集都应包含以下几个字段&#xff1a;* question&#xff1a;用户…...

【学习笔记】机器学习(Machine Learning) | 第四章(3)| 多变量线性回归

机器学习&#xff08;Machine Learning&#xff09; 简要声明 基于吴恩达教授(Andrew Ng)课程视频 BiliBili课程资源 文章目录 机器学习&#xff08;Machine Learning&#xff09;简要声明 三、特征工程与多项式回归&#xff08;一&#xff09;特征工程&#xff1a;从数据中发…...

将本地Springboot项目部署到Linux服务器

1、打包后端项目 在IDEA的终端上执行命令 mvn clean package "-Dmaven.test.skiptrue" 在target目录下查看jar包是否存在 2、idea运行jar包&#xff08;可选&#xff09; 在IDEA的终端上执行命令 # 进入jar包所在目录 E:\LzpWorkspaces\lzp-records> cd .\tar…...

无人设备遥控器之实时数据保护技术篇

无人设备遥控器的实时数据保护技术是保障设备安全运行、避免信息泄露或恶意干扰的核心手段&#xff0c;其核心目标是在复杂电磁环境和网络攻击威胁下&#xff0c;确保指令传输的完整性、保密性和抗干扰性。 一、技术实现路径 链路层加密与认证 动态密钥协商&#xff1a;采用…...

【优秀三方库研读】【性能优化点滴】odygrd/quill 解决伪共享

一、伪共享&#xff08;False Sharing&#xff09;问题本质 当不同CPU核心频繁修改**同一缓存行&#xff08;Cache Line&#xff09;**中的不同变量时&#xff0c;会导致严重的性能下降。现代CPU的缓存系统以缓存行&#xff08;通常64字节&#xff09;为单位操作内存&#xff…...

JavaScript性能优化实战(6):网络请求与资源加载优化

引言 在现代Web应用开发中,网络性能已成为影响用户体验的关键因素。据统计,用户等待页面加载的耐心通常不超过3秒,超过这个时间,约40%的用户会选择离开。此外,Google的研究表明,页面加载时间每增加0.5秒,流量就会下降约20%。因此,优化网络请求和资源加载不仅关乎用户体…...

re题(49)BUUCTF-crackMe

BUUCTF在线评测 int wmain() {FILE *v0; // eaxFILE *v1; // eaxchar v3; // [esp3h] [ebp-405h]char v4[256]; // [esp4h] [ebp-404h] BYREFchar Format[256]; // [esp104h] [ebp-304h] BYREFchar v6[256]; // [esp204h] [ebp-204h] BYREFchar v7[256]; // [esp304h] [ebp-10…...

Python中的单例模式:深入探索元类与装饰器实现

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 单例模式(Singleton Pattern)是设计模式中的一种重要模式,确保一个类在整个应用中只有一个实例,并且提供全局访问点。Python语言作为一…...

深入解析 Babylon.js 中的 TransformNode.lookAt 方法

在 3D 开发中&#xff0c;控制对象朝向是一个基础但关键的需求。Babylon.js 作为一款强大的 Web3D 引擎&#xff0c;提供了 TransformNode.lookAt 方法来实现这一功能。本文将全面解析这个方法的使用技巧、参数含义以及常见应用场景。 方法基础 TransformNode.lookAt 的基本签…...

SpringCloud组件——Gateway

一.网关 1.问题提出 我们通过Eureka&#xff0c;Nacos解决了服务注册&#xff0c;服务发现的问题&#xff0c;使用SpringCloud LoadBalance解决了负载均衡的问题&#xff0c;使用OpenFeign解决了远程调用的问题。 但是当前所有微服务的接口都是直接对外暴露的&#xff0c;可…...

Boost 库安装 (windows 11)

Boost 库安装 (windows 11 1 下载2 生成3 使用 1 下载 下载地址&#xff1a;https://www.boost.org/ 有的时候会需要历史版本下载&#xff1a; https://www.boost.org/users/history/ 2 生成 1、解压后点击 bootstrap.bat&#xff0c;会生成可执行程序b2.exe 2、双击运行b2.…...

lmms-eval--微调实战笔记

lmms-eval--大模型调用平台&#xff0c;方便新手上手大模型微调 lmms-eval的更多用法,没有mathversehttps://github.com/EleutherAI/lm-evaluation-harness.git 单卡运行&#xff0c;模型gpt-j-6B&#xff0c;数据集hellaswag git clone --depth 1 https://github.com/Eleuthe…...

序列密码算法ShanLooog512设计原理详解

序列密码算法ShanLooog512设计原理详解 ShanLooog512(闪龙512)为序列密码算法&#xff0c;内部状态为512比特&#xff0c;密钥长度为128或256比特&#xff0c;轮函数为FFFFFFFF&#xff0c;循环轮数为24轮&#xff0c;输出密钥流为512比特的状态。与Salsa20类似&#xff0c;内…...

Matplotlib可视化基础

1. 折线图 matplotlib.pyplot.plot() # 主要参数&#xff1a; x,y -- 接收array&#xff0c;表示X轴和Y轴对应的数据&#xff0c;无默认 color -- 接收特定string&#xff0c;指定线条的颜色&#xff0c;默认为None linestyle -- 接收特定string&#xff0c;指定线条的类型…...

Linux 内核网络协议栈中的关键数据结构:inet_skb_parm 与 ip_options

在 Linux 内核的网络协议栈中,数据包的高效处理依赖于一系列精心设计的数据结构。这些结构体不仅需要存储网络数据的元信息,还需支持复杂的协议逻辑(如路由、分片、安全策略等)。本文聚焦两个核心结构体 struct inet_skb_parm 和 struct ip_options,解析它们的设计原理、功…...

oracle 数据库查询指定用户下每个表占用空间的大小,倒序显示

oracle 查询指定用户下每个表占用空间的大小&#xff0c;倒序显示 使用场景&#xff1a;数据分析&#xff1b;导出医院正式库到开发环境时&#xff0c;查询出占用表空间高的业务表、导出时排除该表 在Oracle数据库中&#xff0c;要查询指定用户下每个表占用空间的大小并以倒序…...

Missashe考研日记-day29

Missashe考研日记-day29 1 专业课408 学习时间&#xff1a;3h学习内容&#xff1a; 今天先是把虚拟存储剩余的课听完了&#xff0c;然后就是做课后选择题&#xff0c;57道&#xff0c;已经接受了OS课后题尤其多的事实了。解决并且理解完习题之后就开始预习文件管理的内容&…...

【AI】【MCP】搭建私人王炸MCP自动化工作流

目录 一、什么是MCP 二、MCP大集合 三、准备工作 3.1 安装node.js 3.2 安装vscode 3.3 安装cline插件 3.3.1 安装 3.3.2 配置Cline 四、配置MCP服务 4.1 Search-mcp服务 4.2 playwright-mcp 服务 前言&#xff1a;梦想组合&#xff0c;轻松办公&#xff0c;告别手动&a…...

多元函数微分之传统方法和全微分法

一、传统方法 使用链式法则&#xff0c;先对中间变量&#xff08;如 u,v&#xff09;求偏导&#xff0c;再乘以中间变量对最终变量&#xff08;如 x,y&#xff09;的偏导。 二、全微分法 基于全微分形式不变性&#xff0c;直接对 zf(u,v) 求全微分 dz&#xff0c;再代入 du 和…...

新手SEO基础优化全解析

内容概要 对于刚接触SEO的新手而言&#xff0c;系统化理解优化逻辑是避免无效操作的关键。本文将从基础概念入手&#xff0c;逐步拆解搜索引擎排名的影响要素&#xff0c;围绕关键词分析、技术优化、内容策略三大核心模块&#xff0c;提供可落地的操作框架。通过结合工具使用说…...

MATLAB退火算法和遗传算法解决旅行商问题

模拟退火算法和遗传算法都是常用于解决旅行商问题&#xff08;TSP&#xff09;的优化算法&#xff0c;它们在原理、搜索方式、收敛速度和适用场景等方面存在一些区别&#xff1a; 原理 模拟退火算法&#xff1a;模拟退火算法的灵感来源于固体退火原理。固体在加热后缓慢冷却时…...

喜马拉雅卖身腾讯音乐:在线音频独立时代的终结

坦白说,这条消息一出来,喜马拉雅被卖掉不太奇怪,但是腾讯音乐会收购,还是有点意外。 喜马拉雅之前一度被称为中国版Audible平台,在过去几年里,活生生地把一手好牌打得稀烂。如今走到“卖身”这一步,既是无奈,也是必然。 简单回顾一下背景: 2012年,喜马拉雅成立,一…...

简单理解https与http

都是超文本传输协议&#xff0c;一个安全一个不安全&#xff0c;名字长的安全&#xff0c;名字短的不安全。 安全与不安全是居于什么分别的&#xff1f; 通过加密 http无加密。 httpshttp SSL/TSL&#xff08;加密&#xff09;来保障数据安全。加密传输 身份验证 SSL/TLS…...

打造即插即用的企业级云原生平台——KubeSphere 4.1 扩展组件在生产环境的价值全解

目录 打造即插即用的企业级云原生平台——KubeSphere 4.1 扩展组件在生产环境的价值全解 1. 可观测体系&#xff1a;WhizardTelemetry 全家桶 2. 平台与多集群治理 3. CI/CD 与交付效率 4. 网络与流量入口 5. 安全与合规 6. 存储与数据保护 7. 平台集成优势 结语 打造…...

配置扩展ACL

1.扩展ACL简介&#xff1a; 扩展ACL可以更精确地控制基于源IP地址、目标IP地址、协议类型和端口号的流量。 2.配置背景&#xff1a; 为了实现公司内部只能使用FTP服务器传输文件并关闭其他所有服务和端口的需求&#xff0c;可以通过配置访问控制列表&#xff08;ACL&#xf…...

根据用户出生日期计算年龄

public static int calculateAgeFromDate(Date birthDate) { // 将 Date 转换为 LocalDate&#xff08;默认时区&#xff09; LocalDate birthLocalDate birthDate.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDate(); // 获取当前日期LocalDate currentDate Local…...

测试基础笔记第十五天

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、集合1.集合的定义二、使用集合列表去重 导包二、函数1.函数介绍2.定义函数3.调用函数4.函数实现登录案例5.函数的返回值 三、模块和包1.模块的概念(Module)2.模…...

【专题四】前缀和(3)

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录&#xff0c;按专题划分每题主要记录&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代码&#xff1b;&#xff08;2&#xff09;优质解法 优质代码&#xff1b;&#xff…...

STM32 USB配置详解

STM32 USB配置详解 一、USB基础概念 1.1 USB简介 USB (Universal Serial Bus) 是一种用于计算机与外部设备连接的串行总线标准&#xff0c;具有热插拔、即插即用等特点。STM32微控制器内置了多种USB接口&#xff0c;可实现各类USB应用。 1.2 USB速度等级 Low Speed (LS): …...

2025年Mapbox零基础入门教程(1)地图初始化

什么是mapbox&#xff1f; mapbox是一个地图框架&#xff0c;不仅提供前端渲染能力&#xff0c;还具备后端服务接口能力。 相较于openlayers&#xff0c;它可构建二维和三维地图&#xff0c;并支持优化导航路线和位置查询等功能。 开发中使用mapbox需引入库文件并设置token&…...

课外知识:你需要了解的Python类对象里面的__getattr__方法

你需要了解的Python类对象中的__getattr__方法 一、__getattr__基础概念 1. 方法定义 def __getattr__(self, name: str) -> Any:"""当访问不存在的属性时触发"""2. 核心特性 动态属性处理&#xff1a;拦截未定义的属性访问按需触发&…...

openGauss新特性 | DataKit支持PostgreSQL到openGauss的迁移能力

Postgresql-\>openGauss迁移工具debezium-connector-postgres 可获得性 本特性自openGauss 7.0.0-RC1版本开始引入。 特性简介 debezium-connector-postgres工具是一个基于Java语言的Postgresql到openGauss的复制工具。该工具提供了初始全量数据及对象&#xff08;视图、…...

【前端】跟进新趋势- PWA WebAssembly

不定期更新及补充实战。建议关注收藏点赞。 目录 PWA&#xff08;渐进式 Web 应用&#xff0c;Progressive Web App&#xff09;WebAssembly&#xff08;WASM&#xff09; PWA&#xff08;渐进式 Web 应用&#xff0c;Progressive Web App&#xff09; PWA 是一种提升 Web 应用…...

C++学习:六个月从基础到就业——模板编程:SFINAE原则

C学习&#xff1a;六个月从基础到就业——模板编程&#xff1a;SFINAE原则 本文是我C学习之旅系列的第三十六篇技术文章&#xff0c;也是第二阶段"C进阶特性"的第十四篇&#xff0c;主要介绍C模板编程中的SFINAE原则。查看完整系列目录了解更多内容。 目录 C学习之…...

完美解决.NET Framework 4.0 中 System.Drawing 库不支持 WebP 格式的图像处理

如果你想在 .NET Framework 4.0 中使用 ImageMagick 处理图片&#xff0c;可以通过 Magick.NET 库来实现。Magick.NET 是 ImageMagick 的 .NET 封装&#xff0c;可以用来读取、写入、编辑图像。 以下是如何使用 Magick.NET 来处理图像并提取图像的宽度和高度。 步骤&#xff…...

网络基础概念:从菜鸟到入门

前言&#xff1a;快递小哥的故事 想象一下你要给朋友寄个礼物&#xff0c;这个过程其实和网络通信非常相似&#xff1a; 1. 你需要知道朋友的”地址“&#xff08;IP地址&#xff09; 2. 要注明是送到他家大门还是物业代收&#xff08;端口号&#xff09; 3. 要选择快递公司并…...

优先队列和单调队列(双端队列实现的)

这里写自定义目录标题 一、优先队列与单调队列二、优先队列2.1 概念2.2 增删查 判空2.3 示例代码 三、双端队列四、单调队列4.1 单调递增队列4.2 单调递减队列 一、优先队列与单调队列 二、优先队列 2.1 概念 一种特殊的队列&#xff0c;它与普通队列的主要区别在于元素的出…...

设计模式(状态模式)

概述 在实际的软件开发中&#xff0c;状态模式并不是很常用&#xff0c;但是在能够用到的场景里&#xff0c;它可以发挥很大的作用。从这一点上来看&#xff0c;它有点像我们之前讲到的组合模式。 状态模式一般用来实现状态机&#xff0c;而状态机常用在游戏、工作流引擎等系统…...

安卓基础(get和set)

在 Java 中&#xff0c;​​get 和 set​​ 方法是面向对象编程中 ​​封装&#xff08;Encapsulation&#xff09;​​ 的核心实现&#xff0c;用于安全地访问和修改类的私有字段&#xff08;private 成员变量&#xff09;。它们的核心作用是 ​​控制对数据的访问&#xff0c…...

机器人灵巧操作新突破,力感知技术让机械手更精准

在机器人的发展历程中&#xff0c;让机器人实现灵活操作一直是科研人员努力攻克的难题。 我们这篇文章给大家带来一份新的工作&#xff1a;DexForce 链接&#xff1a;[2501.10356] DexForce: Extracting Force-informed Actions from Kinesthetic Demonstrations for Dextero…...

八大排序——直接插入排序/希尔排序

八大排序——直接插入排序/希尔排序 目录 一、直接插入排序 二、希尔排序 一、直接插入排序 每一趟从待排序序列中取第一个值&#xff0c;将其插入到已排序好的序列中&#xff0c;对已排序好的序列&#xff0c;从右到左依次和待插入值比较&#xff0c;如果大于则向后挪&…...

8、HTTPD服务--ab压力测试

一、ab压力测试 # ab ‐c 100 ‐n 1000 http://vedio.linux.com/index.html 2 This is ApacheBench, Version 2.3 <$Revision: 1430300 $> 3 Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 4 Licensed to The Apache Software Foundation,…...

node.js 实战——mongoDB

MongoDB MongoDB 简介 MongoDB 是一种基于文档型 (document-oriented) 的 NoSQL 数据库&#xff0c;使用类 JSON 的 BSON 格式存储数据&#xff0c;自然支持复杂数据结构。它特别适合需要快速变化、大量数据处理和高应用扩展性的场景。 MongoDB 特性&#xff1a; 无法表、无…...

C语言学习路线

以下是一份综合多个优质资源的C语言学习路线规划&#xff0c;结合2025年最新技术趋势和工程实践需求&#xff0c;分为三个阶段系统推进&#xff1a; ​一、入门阶段&#xff08;1-2个月&#xff09;​​ ​目标​&#xff1a;掌握基础语法&#xff0c;能编写简单程序&#xff…...

飞凌嵌入式T527核心板获得【OpenHarmony生态产品兼容性证书】

近日&#xff0c;飞凌嵌入式FET527-C核心板通过OpenHarmony 4.1 Release版本兼容测评&#xff0c;获得【OpenHarmony生态产品兼容性证书】。 飞凌嵌入式FET527-C核心板搭载全志T527系列全国产高性能处理器&#xff0c;集成8个ARM Cortex-A55核心&#xff0c;并内置RISC-V核和DS…...

Mioty|采用报文分割(Telegram Splitting)以提高抗干扰能力的无线通信技术

1、什么是Mioty 在物联网&#xff08;IoT&#xff09;快速发展的背景下&#xff0c;低功耗广域网&#xff08;LPWAN&#xff09;技术成为连接海量设备的关键。LPWAN具有低功耗、低成本、广覆盖和强抗干扰能力等特点&#xff0c;使其特别适用于大规模、远距离、低数据速率的IoT…...

WPF 程序监控硬件设备状态变化的实现方案

以下是一个完整的 C# WPF 程序实现方案&#xff0c;用于监控硬件设备状态变化&#xff08;基于设备 SDK API&#xff09;。我们将分步骤实现&#xff0c;包含状态轮询、事件通知、UI 绑定和错误处理。 1. 项目结构设计 HardwareMonitor/ ├── Models/ # 数据模…...