【音视频】FFmpeg 编码H265

一、概述

实现了读入本地yuv文件,通过libx265编码为H265格式,并存储到本地文件中

二、实现流程

准备文件

build路径下准备yuv文件

在这里插入图片描述

在项目中添加文件参数,输出为h265文件,使用libx265编码

在这里插入图片描述

初始化解码器
  • 通过传进来的libx265找到指定的编码器
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);
}
  • 绑定解码器和解码器上下文
ret = avcodec_open2(codec_ctx, codec, NULL);
if (ret < 0) {fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));exit(1);
}
  • 设置编码的视频参数,如分辨率,帧率,时间基、比特率等
#define ENCODE_TIME_BASE 1000   // 设置时间基数,编码需要根据时间来判断码率
#define ENCODE_FRAME_RATE 25   // 设置帧率
#define YUV_WIDTH 1280
#define YUV_HEIGH 720/* 设置分辨率*/
codec_ctx->width = YUV_WIDTH;        // 根据实际去写入
codec_ctx->height = YUV_HEIGH;
/* 设置time base */
codec_ctx->time_base = (AVRational){1, ENCODE_TIME_BASE};  // 1/1000
codec_ctx->framerate = (AVRational){ENCODE_FRAME_RATE, 1};
codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
  • 也可以设置编码的码率,可以设置一个码率的范围
  • 也可以设置编码的缓存大小,用于在码率波动的时候做缓存
codec_ctx->bit_rate = 3000000;codec_ctx->rc_max_rate = 3000000;
codec_ctx->rc_min_rate = 3000000;codec_ctx->rc_buffer_size = 2000000;
  • 配置编码器的高级参数,这里指的是而外的设置
  • 比如编码模式,GOP大小,B帧大小、I帧间隔、编码profile级别、画质等等
  • preset参数是影响编码速度的,比如ultrafast编码最快,但是画质最差
codec_ctx->gop_size = 25;
codec_ctx->max_b_frames = 0;
codec_ctx->keyint_min = 25;ret = av_opt_set(codec_ctx->priv_data, "preset", "medium", 0);
ret = av_opt_set(codec_ctx->priv_data, "profile", "main", 0);
ret = av_opt_set(codec_ctx->priv_data, "tune","film",0);
  • 也可以通过av_opt_set的方法,将修改的内容直接发送到libx265编码器内部进行修改
ret = av_opt_set(codec_ctx->priv_data, "x265-param", "--keyint=25, --bframes=2",0);
ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);
ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--bframes=2", 0);
ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);
  • 比如我们设置了B帧为0,并且关闭了多线程,此时的延迟就为0了,观察如下
  • 可以发现,一帧数据传入编码器,立马就编码出一帧数据

在这里插入图片描述

  • 初始之外,还可以通过设置零延迟的方法,当同时必须关闭多线程
ret = av_opt_set(codec_ctx->priv_data, "tune","zerolatency",0);
  • 如果开启多线程,就会存在编码延迟,不过可以提高编码速度
  • 打印发现,传入多帧数据后,才从编码器中取出编码后的帧
ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);
  • 也可以这样设置多线程
codec_ctx->thread_count = 4;  // 开了多线程后也会导致帧输出延迟, 需要缓存thread_count帧后再编程。     
codec_ctx->thread_type = FF_THREAD_FRAME; // 并 设置为FF_THREAD_FRAME            

在这里插入图片描述

  • 以下的设置,是将SPS、PPS、VPS放入扩展变量里面,即codec->extradata里面
  • 此时就不会而外编码一帧了,观察打印结果
codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; 

启动后,没发现SPS、PPS、VPS
在这里插入图片描述

关闭后,前几帧为SPS、PPS、VPS

在这里插入图片描述

更多的libx265的设置,可以使用对应的命令查询

ffmpeg -h encoder=libx265 > libx265.log

在这里插入图片描述

编码H265
  • 打开输入、输出文件
// 打开输入和输出文件
infile = fopen(in_yuv_file, "rb");
if (!infile) {fprintf(stderr, "Could not open %s\n", in_yuv_file);exit(1);
}
outfile = fopen(out_h264_h265_file, "wb");
if (!outfile) {fprintf(stderr, "Could not open %s\n", out_h264_h265_file);exit(1);
}
  • 分配对应的AVFrame和AVPacket的内存
// 分配pkt和frame
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的参数,如分辨率、像素
// 为frame分配buffer
frame->format = codec_ctx->pix_fmt;
frame->width  = codec_ctx->width;
frame->height = codec_ctx->height;ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {fprintf(stderr, "Could not allocate the video frame data\n");exit(1);
}
  • 通过分辨率和像素格式,计算出一帧数据对应的buffer大小,并且分配对应的缓冲区
int frame_bytes = av_image_get_buffer_size(frame->format, frame->width,frame->height, 1);
uint8_t *yuv_buf = (uint8_t *)malloc(frame_bytes);
  • 循环编码文件,直到读到文件结束
  • av_frame_make_writable确保帧可用,不开启的话可能会写入失败
for (;;) {memset(yuv_buf, 0, frame_bytes);size_t read_bytes = fread(yuv_buf, 1, frame_bytes, infile);if(read_bytes <= 0) {printf("read file finish\n");break;}/* 确保该frame可写, 如果编码器内部保持了内存参考计数,则需要重新拷贝一个备份目的是新写入的数据和编码器保存的数据不能产生冲突*/ret = av_frame_make_writable(frame);if(ret != 0) {printf("av_frame_make_writable failed, ret = %d\n", ret);break;}int need_size = av_image_fill_arrays(frame->data, frame->linesize, yuv_buf,frame->format,frame->width, frame->height, 1);if(need_size != frame_bytes) {printf("av_image_fill_arrays failed, need_size:%d, frame_bytes:%d\n",need_size, frame_bytes);break;}pts += (ENCODE_TIME_BASE/ENCODE_FRAME_RATE);// 设置ptsframe->pts = pts;       // 使用采样率作为pts的单位,具体换算成秒 pts*1/采样率begin_time = get_time();ret = encode(codec_ctx, frame, pkt, outfile);end_time = get_time();printf("encode time:%lldms\n", end_time - begin_time);if(ret < 0) {printf("encode failed\n");break;}
}
  • encode函数如下,主要是送入一帧数据,然后循环读取AVPacket,直到输出AVERROR_EOF表示当前帧编码完成
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 pts:%3"PRId64"\n", frame->pts);/* 通过查阅代码,使用x265进行编码时,具体缓存帧是在x265源码进行,* 不会增加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;}printf("avcodec_receive_packet:pts:%3"PRId64" dts:%3"PRId64" (size:%5d)\n", pkt->pts, pkt->dts, pkt->size);fwrite(pkt->data, 1, pkt->size, outfile); print_h265_nal_unit_type(pkt->data, pkt->size);  // 只针对H265}return 0;
}
  • print_h265_nal_unit_type函数主要是通过H265的结构,找到startcode,然后解析NALU的头部,用于输出调试
void print_h265_nal_unit_type(uint8_t *data, size_t size)
{int i = 0;while (i+3 < size ) {if(data[i] == 0 && data[i+1]==0 && data[i+2] == 0 && data[i+3] == 1 ) {i += 4;printf("%02x nal_type:%d, pos:%d\n", data[i],(data[i]&0x7e)>>1, i);continue;}if(data[i] == 0 && data[i+1]==0 && data[i+2] == 1) {i += 3;printf("%02x nal_type:%d, pos:%d\n",data[i], (data[i]&0x7e)>>1, i);continue;}i++;}
}
冲刷编码器
  • 编码结束后,编码器内部可能还缓存了部分帧,此时需要传入NULL,将编码器中剩余的帧冲刷出来
/* 冲刷编码器 */
encode(codec_ctx, NULL, pkt, outfile);
关闭文件
  • 关闭文件、并且释放相关内存,确保正确结束程序
// 关闭文件
fclose(infile);
fclose(outfile);// 释放内存
if(yuv_buf) {free(yuv_buf);
}av_frame_free(&frame);
av_packet_free(&pkt);
avcodec_free_context(&codec_ctx);

完整代码

/**
* @projectName   02-encode_h265
* @brief         视频编码,从本地读取YUV数据进行H265编码
* @author        Liao Qingfu
* @date          2022-09-16
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <libavcodec/avcodec.h>
#include <libavutil/time.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#define ENCODE_TIME_BASE 1000   // 设置时间基数,编码需要根据时间来判断码率
#define ENCODE_FRAME_RATE 25   // 设置帧率
#define YUV_WIDTH 1280
#define YUV_HEIGH 720void print_h265_nal_unit_type(uint8_t *data, size_t size);
int64_t get_time()
{return av_gettime_relative() / 1000;  // 换算成毫秒
}
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 pts:%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;}printf("avcodec_receive_packet:pts:%3"PRId64" dts:%3"PRId64" (size:%5d)\n", pkt->pts, pkt->dts, pkt->size);fwrite(pkt->data, 1, pkt->size, outfile); print_h265_nal_unit_type(pkt->data, pkt->size);  // 只针对H265}return 0;
}
/*** @brief 提取测试文件:ffmpeg -i test_1280x720.flv -t 5 -r 25 -pix_fmt yuv420p yuv420p_1280x720.yuv*           参数输入: yuv420p_1280x720.yuv yuv420p_1280x720.h265 libx265* @param argc* @param argv* @return*/
int main(int argc, char **argv)
{char *in_yuv_file = NULL;char *out_h264_h265_file = NULL;FILE *infile = NULL;FILE *outfile = NULL;const char *codec_name = NULL;const AVCodec *codec = NULL;AVCodecContext *codec_ctx= NULL;AVFrame *frame = NULL;AVPacket *pkt = NULL;int ret = 0;if (argc < 4) {fprintf(stderr, "Usage: %s <input_file out_file codec_name >, argc:%d\n",argv[0], argc);return 0;}in_yuv_file = argv[1];      // 输入YUV文件out_h264_h265_file = argv[2];codec_name = argv[3];/* 查找指定的编码器 */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 = YUV_WIDTH;        // 根据实际去写入codec_ctx->height = YUV_HEIGH;/* 设置time base */codec_ctx->time_base = (AVRational){1, ENCODE_TIME_BASE};  // 1/1000codec_ctx->framerate = (AVRational){ENCODE_FRAME_RATE, 1};/* 设置I帧间隔* 如果frame->pict_type设置为AV_PICTURE_TYPE_I, 则忽略gop_size的设置,一直当做I帧进行编码*/codec_ctx->gop_size = 25;   // I帧间隔, H265单独设置这里不起作用codec_ctx->keyint_min = 25;codec_ctx->max_b_frames = 0; // 如果不想包含B帧则设置为0codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;//if (codec->id == AV_CODEC_ID_H264) {// 相关的参数可以参考libx264.c的 AVOption options// ultrafast all encode time:2270ms// medium all encode time:5815ms// veryslow all encode time:19836msret = av_opt_set(codec_ctx->priv_data, "preset", "medium", 0);if(ret != 0) {printf("av_opt_set preset failed\n");}ret = av_opt_set(codec_ctx->priv_data, "profile", "main", 0); // 默认是highif(ret != 0) {printf("av_opt_set profile failed\n");}
//        ret = av_opt_set(codec_ctx->priv_data, "tune","zerolatency",0); // 直播是才使用该设置
//        ret = av_opt_set(codec_ctx->priv_data, "tune","film",0); //  画质filmif(ret != 0) {printf("av_opt_set tune failed\n");}}else if (codec->id == AV_CODEC_ID_H265) {// 相关的参数可以参考libx265.c的 AVOption options// ultrafast all encode time:// medium all encode time:// veryslow all encode time:ret = av_opt_set(codec_ctx->priv_data, "preset", "medium", 0);if(ret != 0) {printf("av_opt_set preset failed\n");}ret = av_opt_set(codec_ctx->priv_data, "profile", "main", 0); // 默认是highif(ret != 0) {printf("av_opt_set profile failed\n");}ret = av_opt_set(codec_ctx->priv_data, "tune","zerolatency",0); // 直播是才使用该设置
//        ret = av_opt_set(codec_ctx->priv_data, "tune","film",0); //  画质filmif(ret != 0) {printf("av_opt_set tune failed\n");}// libx265/source\common\param.cpp
//        ret = av_opt_set(codec_ctx->priv_data, "x265-param", "--keyint=25, --bframes=2",0);
//        ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);
//        ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--bframes=2", 0);
//        ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);if(ret != 0) {printf("av_opt_set x265-param failed\n");return -1;}} else {printf("no support the codec :%s\n", codec_name);return -1;}/** 设置编码器参数*//* 设置bitrate */codec_ctx->bit_rate = 3000000; //3000k
//    codec_ctx->rc_max_rate = 3000000;
//    codec_ctx->rc_min_rate = 3000000;
//    codec_ctx->rc_buffer_size = 2000000;
//    codec_ctx->thread_count = 4;  // 开了多线程后也会导致帧输出延迟, 需要缓存thread_count帧后再编程。
//    codec_ctx->thread_type = FF_THREAD_FRAME; // 并 设置为FF_THREAD_FRAME/* 对于H264 AV_CODEC_FLAG_GLOBAL_HEADER  设置则只包含I帧,此时sps pps需要从codec_ctx->extradata读取*  不设置则每个I帧都带 sps pps sei*/codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // 存本地文件时不要去设置/* 将codec_ctx和codec进行绑定 */ret = avcodec_open2(codec_ctx, codec, NULL);if (ret < 0) {fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));exit(1);}printf("thread_count: %d, thread_type:%d\n", codec_ctx->thread_count, codec_ctx->thread_type);// 打开输入和输出文件infile = fopen(in_yuv_file, "rb");if (!infile) {fprintf(stderr, "Could not open %s\n", in_yuv_file);exit(1);}outfile = fopen(out_h264_h265_file, "wb");if (!outfile) {fprintf(stderr, "Could not open %s\n", out_h264_h265_file);exit(1);}// 分配pkt和framepkt = 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);if (ret < 0) {fprintf(stderr, "Could not allocate the video frame data\n");exit(1);}// 计算出每一帧的数据 像素格式 * 宽 * 高// 1382400int frame_bytes = av_image_get_buffer_size(frame->format, frame->width,frame->height, 1);printf("frame_bytes %d\n", frame_bytes);uint8_t *yuv_buf = (uint8_t *)malloc(frame_bytes);if(!yuv_buf) {printf("yuv_buf malloc failed\n");return 1;}int64_t begin_time = get_time();int64_t end_time = begin_time;int64_t all_begin_time = get_time();int64_t all_end_time = all_begin_time;int64_t pts = 0;printf("start enode\n");for (;;) {memset(yuv_buf, 0, frame_bytes);size_t read_bytes = fread(yuv_buf, 1, frame_bytes, infile);if(read_bytes <= 0) {printf("read file finish\n");break;}/* 确保该frame可写, 如果编码器内部保持了内存参考计数,则需要重新拷贝一个备份目的是新写入的数据和编码器保存的数据不能产生冲突*/ret = av_frame_make_writable(frame);if(ret != 0) {printf("av_frame_make_writable failed, ret = %d\n", ret);break;}int need_size = av_image_fill_arrays(frame->data, frame->linesize, yuv_buf,frame->format,frame->width, frame->height, 1);if(need_size != frame_bytes) {printf("av_image_fill_arrays failed, need_size:%d, frame_bytes:%d\n",need_size, frame_bytes);break;}pts += (ENCODE_TIME_BASE/ENCODE_FRAME_RATE);// 设置ptsframe->pts = pts;       // 使用采样率作为pts的单位,具体换算成秒 pts*1/采样率begin_time = get_time();ret = encode(codec_ctx, frame, pkt, outfile);end_time = get_time();printf("encode time:%lldms\n", end_time - begin_time);if(ret < 0) {printf("encode failed\n");break;}}/* 冲刷编码器 */encode(codec_ctx, NULL, pkt, outfile);all_end_time = get_time();printf("all encode time:%lldms\n", all_end_time - all_begin_time);// 关闭文件fclose(infile);fclose(outfile);// 释放内存if(yuv_buf) {free(yuv_buf);}av_frame_free(&frame);av_packet_free(&pkt);avcodec_free_context(&codec_ctx);printf("main finish, please enter Enter and exit\n");getchar();return 0;
}void print_h265_nal_unit_type(uint8_t *data, size_t size)
{int i = 0;while (i+3 < size ) {if(data[i] == 0 && data[i+1]==0 && data[i+2] == 0 && data[i+3] == 1 ) {i += 4;printf("%02x nal_type:%d, pos:%d\n", data[i],(data[i]&0x7e)>>1, i);continue;}if(data[i] == 0 && data[i+1]==0 && data[i+2] == 1) {i += 3;printf("%02x nal_type:%d, pos:%d\n",data[i], (data[i]&0x7e)>>1, i);continue;}i++;}
}

更多资料:https://github.com/0voice

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

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

相关文章

ECreator低代码平台-文件管理器的使用说明

Ecreator是中山华拓信息技术公司旗下的一款低代码平台&#xff0c;主要功能包含&#xff1a;文件管理器&#xff0c;表单数据管理器&#xff0c;仪表盘设计界面&#xff0c;内容页面自定义等功能&#xff0c;可以用于快速低成本的构建网站和企业内部应用。 下面介绍一下文件管…

高考加油!UI界面生成器!

这个高考助力标语生成器具有以下特点&#xff1a; 视觉设计&#xff1a;采用了蓝色为主色调&#xff0c;搭配渐变背景和圆形装饰元素&#xff0c;营造出宁静而充满希望的氛围&#xff0c;非常适合高考主题。 标语生成&#xff1a;内置了超过 100 条精心挑选的高考加油标语&a…

阿姆达尔定律的演进:古斯塔夫森定律

前言 在上一篇文章《使用阿姆达尔定律来提升效率》中提到的阿姆达尔定律前提是假设问题的规模保持不变&#xff0c;并且给定一台速度更快的机器&#xff0c;目标是更快地解决问题。然而&#xff0c;在大多数情况下&#xff0c;这并不完全正确。当有一台更快的机器时&#xff0…

【RabbitMQ】- Channel和Delivery Tag机制

在 RabbitMQ 的消费者代码中&#xff0c;Channel 和 tag 参数的存在是为了实现消息确认机制&#xff08;Acknowledgment&#xff09;和精细化的消息控制。 Channel 参数 作用 Channel 是 AMQP 协议的核心操作接口&#xff0c;通过它可以直接与 RabbitMQ 交互&#xff1a; 手…

核心机制:流量控制

搭配滑动窗口使用的 窗口大小 窗口越大,传输速度就越快,但是也不能无限大,太大了,对于可靠性会有影响 比如发生方以非常快的速度,发送,接收方的处理速度跟不上,也就会导致有效数据被接受方丢弃(又得重传) 流量控制,就是根据接收方的处理能力(如何衡量?),干预到发送方的发送…

深度强化学习赋能城市消防优化,中科院团队提出DRL新方法破解设施配置难题

在城市建设与发展中&#xff0c;地理空间优化至关重要。从工业园区选址&#xff0c;到公共服务设施布局&#xff0c;它都发挥着关键作用。但传统求解方法存在诸多局限&#xff0c;如今&#xff0c;深度学习技术为其带来了新的转机。 近日&#xff0c;在中国地理学会地理模型与…

安科电动机保护器通过ModbusRTU转profinet网关与PLC通讯

安科电动机保护器通过ModbusRTU转profinet网关与PLC通讯 在工业自动化领域&#xff0c;设备间的通信和数据交互至关重要。Modbus作为一种常用的通讯协议&#xff0c;广泛应用于各种工业现场&#xff1b;而Profinet则凭借其高效、实时性&#xff0c;在工业以太网通讯中占据重要…

python直方图

在Python中&#xff0c;绘制直方图&#xff08;Histogram&#xff09;是一项非常常见的任务&#xff0c;通常用于数据可视化&#xff0c;以展示数据的分布情况。Python中有多种库可以绘制直方图&#xff0c;其中最常用的两个库是Matplotlib和Seaborn。此外&#xff0c;Pandas库…

在Oxygen编辑器中使用DeepSeek

罗马尼亚公司研制开发的Oxygen编辑器怎样与国产大模型结合&#xff0c;这是今年我在tcworld大会上给大家的分享&#xff0c;需要ppt的朋友请私信联系 - 1 - Oxygen编辑器中的人工智能助手 Oxygen编辑器是罗马尼亚的Syncro Soft公司开发的一款结构化文档编辑器。 它是用来编写…

neo4j 5.19.0安装、apoc csv导入导出 及相关问题处理

前言 突然有需求需要用apoc 导入 低版本的图谱数据&#xff0c;网上资料又比较少&#xff0c;所以就看官网资料并处理了apoc 导入的一些问题。 相关地址 apoc 官方安装网址 apoc 官方导出csv 教程地址 apoc 官方 导入 csv 地址 docker 安装 执行如下命令启动镜像 doc…

macos常见且应该避免被覆盖的系统环境变量(避免用 USERNAME 作为你的自定义变量名)

文章目录 macos避免用 USERNAME 作为你的自定义变量名macos常见且应该避免被覆盖的系统环境变量 macos避免用 USERNAME 作为你的自定义变量名 问题&#xff1a; 你执行了&#xff1a;export USERNAME“admin” 然后执行&#xff1a;echo ${USERNAME} 输出却是&#xff1a;xxx …

Python训练打卡Day41

简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 → Batch…

【亲测有效】Mybatis-Plus中更新字段为null

Mybatis-Plus中更新字段为null 遇到问题 Mybatis-Plus更新的默认行为如下: Mybatis-Plus默认如果某个字段为null, 默认不更新这个字段, 例如有个Double类型的字段, 当前数据库数据为10, 然后传参时当前字段为null, 实际上Mybatis-Plus是不会覆盖该字段为null的 在传参的时候如…

如何使用插件和子主题添加WordPress自定义CSS(附:常见错误)

您是否曾经想更改网站外观的某些方面&#xff0c;但不知道怎么做&#xff1f;有一个解决方案——您可以将自定义 CSS&#xff08;层叠样式表&#xff09;添加到您的WordPress网站&#xff01; 在本文中&#xff0c;我们将讨论您需要了解的有关CSS的所有知识以及如何使用它来修…

左值引用和右值引用

一、基本概念 左值&#xff08;lvalue&#xff09;和右值&#xff08;rvalue&#xff09; 左值指的是有确定存储位置&#xff08;地址&#xff09;的对象&#xff0c;通常可以出现在赋值语句左侧。例如&#xff1a;变量名、解引用指针得到的对象、数组元素等都属于左值。 右值…

django入门-orm数据库操作

一&#xff1a;下载数据库依赖项mysqlclient pip install mysqlclient 二&#xff1a;django配置文件配置数据库链接 路径&#xff1a;mysite2\mysite2\settings.py DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: data, # 数据库名称USER: root, …

国标GB28181设备管理软件EasyGBS视频平台筑牢文物保护安全防线创新方案

一、方案背景​ 文物作为人类文明的珍贵载体&#xff0c;具有不可再生性。当前&#xff0c;盗窃破坏、游客不文明行为及自然侵蚀威胁文物安全&#xff0c;传统保护手段存在响应滞后、覆盖不全等局限。随着5G与信息技术发展&#xff0c;基于GB28181协议的EasyGBS视频云平台&…

NetSuite Bundle - Dashboard Refresh

儿童节快乐&#xff01; 今朝发一个Bundle&#xff0c;解决一个NetSuite Dashboard的老问题。出于性能上的考虑&#xff0c;NetSuite的Dashboard中的Portlet&#xff0c;只能逐一手工刷新。有人基于浏览器做了插件&#xff0c;可以进行自动刷新。但是在我们做项目部署时&#…

<PLC><socket><西门子>基于西门子S7-1200PLC,实现手机与PLC通讯(通过websocket转接)

前言 本系列是关于PLC相关的博文,包括PLC编程、PLC与上位机通讯、PLC与下位驱动、仪器仪表等通讯、PLC指令解析等相关内容。 PLC品牌包括但不限于西门子、三菱等国外品牌,汇川、信捷等国内品牌。 除了PLC为主要内容外,PLC相关元器件如触摸屏(HMI)、交换机等工控产品,如…

【AI论文】推理语言模型的强化学习熵机制

摘要&#xff1a;本文旨在克服将强化学习扩展到使用 LLM 进行推理的主要障碍&#xff0c;即策略熵的崩溃。 这种现象在没有熵干预的RL运行中一直存在&#xff0c;其中策略熵在早期训练阶段急剧下降&#xff0c;这种探索能力的减弱总是伴随着策略性能的饱和。 在实践中&#xff…