音视频(二)ffmpeg编译及推流
FFmpeg 大名鼎鼎,就不多介绍了
1:环境
win11_amd64
ffpmeg download:https://git.ffmpeg.org/ffmpeg.git ffmpeg
msys2 download:https://www.msys2.org/
vs2022 (c++ 写demo用) 用别的也行
usb2.0 摄像头(有点老)
opencv 看上传的流 download:https://github.com/opencv/opencv/tags
cmake (没用到)
2:msys2 更新下载
1> 在开始菜单打开MSYS2 MSYS,使用命令pacman -Syu升级所有库
pacman -S --needed base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-nasm mingw-w64-x86_64-yasm
2> msys64\etc\pacman.d 目录下 有多个文件 这里以mirrorlist.mingw64 为例配置国内源
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/x86_64/
Server = https://mirrors.aliyun.com/msys2/msys/x86_64/
3>再安装
pacman -S mingw-w64-x86_64-x264 mingw-w64-x86_64-x265 mingw-w64-x86_64-fdk-aac
2:ffpmeg 配置编译选项
1> 打开MSYS2 mingw64 注意环境是 amd64位 所以用这个
cd ffpmeg 目录
/usr/path eg(D盘下目录): /d/ffpmep/FFmpegn4 linux 格式的反斜杠 不是windows 的 斜杠
./configure --prefix=/usr/path --enable-shared --disable-static --enable-gpl --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-nonfree --disable-postproc
建议在ffpmeg 同级创建 build ,install 假如 ffpmegcode(下载的代码) 在 d://ffpmeg/ffpmegcode
那么就有 d://ffpmeg/build d://ffpmeg/install 2个目录
cd 到 build (执行configure 也有点慢,慢慢等几分种0
../ffpmegcode/configure --prefix=/d/ffpmeg/install --enable-shared --disable-static --enable-gpl --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-nonfree --disable-postprocmake -jN (N为电脑有几核)直接make 也可以,就是慢点
make install 会安装到 /d/ffpmeg/install
``
opencv 自行安装 网上太多了,这里就不介绍了
3 demo 测试
1》先把上章的 MediaServer 开起来,这个我装到ubbuntu22上了
2》上代码
#include <iostream>
#include <opencv2/opencv.hpp>
extern "C" {
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavfilter/avfilter.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
}
#include <memory>
#include <thread>
#include <queue>
#include <condition_variable>
#include <chrono>// 添加 OpenCV 库的链接指令
#pragma comment(lib, "opencv_core4110d.lib") //opencv_core4110d.lib
#pragma comment(lib, "opencv_imgcodecs4110d.lib")
#pragma comment(lib, "opencv_highgui4110d.lib")
#pragma comment(lib, "opencv_imgcodecs4110d.lib")
// 添加 FFmpeg 库的链接指令
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "swscale.lib")
#pragma comment(lib, "avfilter.lib")
#pragma comment(lib, "swresample.lib")// 自定义删除器
struct AVFormatContextDeleter {void operator()(AVFormatContext* ctx) const {if (ctx) {if (!(ctx->oformat && (ctx->oformat->flags & AVFMT_NOFILE))) {avio_closep(&ctx->pb);}avformat_free_context(ctx);}}
};struct AVCodecContextDeleter {void operator()(AVCodecContext* ctx) const {if (ctx) {avcodec_free_context(&ctx);}}
};struct AVFrameDeleter {void operator()(AVFrame* frame) const {if (frame) {av_frame_free(&frame);}}
};struct AVPacketDeleter {void operator()(AVPacket* packet) const {if (packet) {av_packet_free(&packet);}}
};struct SwsContextDeleter {void operator()(SwsContext* swsCtx) const {if (swsCtx) {sws_freeContext(swsCtx);}}
};struct AVFilterGraphDeleter {void operator()(AVFilterGraph* graph) const {if (graph) {avfilter_graph_free(&graph);}}
};struct AVFilterContextDeleter {void operator()(AVFilterContext* ctx) const {if (ctx) {avfilter_free(ctx);}}
};// 帧队列
std::queue<std::shared_ptr<AVFrame>> frameQueue;
std::condition_variable frameQueueCond;
std::mutex frameQueueMutex;
const size_t MAX_QUEUE_SIZE = 20; // 增大队列大小,增加缓冲
bool stopFlag = false;// 上传线程函数
void uploadThread(const std::shared_ptr<AVFormatContext>& inputFormatContext, int videoStreamIndex,const std::shared_ptr<AVCodecContext>& decoderContext, const std::string& outputUrl) {// 输出格式上下文AVFormatContext* outputFormatContextRaw = nullptr;avformat_alloc_output_context2(&outputFormatContextRaw, nullptr, "rtsp", outputUrl.c_str());if (!outputFormatContextRaw) {std::cerr << "无法分配输出格式上下文。" << std::endl;return;}std::shared_ptr<AVFormatContext> outputFormatContext(outputFormatContextRaw, AVFormatContextDeleter());// 查找编码器AVCodec* videoEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);if (!videoEncoder) {std::cerr << "未找到 H.264 编码器。" << std::endl;return;}// 创建视频输出流AVStream* videoOutputStream = avformat_new_stream(outputFormatContext.get(), videoEncoder);if (!videoOutputStream) {std::cerr << "无法创建视频输出流。" << std::endl;return;}// 分配视频编码器上下文AVCodecContext* videoEncoderContextRaw = avcodec_alloc_context3(videoEncoder);if (!videoEncoderContextRaw) {std::cerr << "无法分配视频编码器上下文。" << std::endl;return;}std::shared_ptr<AVCodecContext> videoEncoderContext(videoEncoderContextRaw, AVCodecContextDeleter());videoEncoderContext->codec_id = AV_CODEC_ID_H264;videoEncoderContext->codec_type = AVMEDIA_TYPE_VIDEO;videoEncoderContext->pix_fmt = AV_PIX_FMT_YUV420P;videoEncoderContext->width = decoderContext->width;videoEncoderContext->height = decoderContext->height;videoEncoderContext->time_base = { 1, 25 };videoEncoderContext->framerate = { 25, 1 };// 优化编码器参数,降低比特率videoEncoderContext->bit_rate = 2000000; // 降低比特率到 2MbpsvideoEncoderContext->gop_size = 25;videoEncoderContext->max_b_frames = 1;// 打开视频编码器if (avcodec_open2(videoEncoderContext.get(), videoEncoder, nullptr) < 0) {std::cerr << "无法打开视频编码器。" << std::endl;return;}// 复制视频编码器参数到输出流if (avcodec_parameters_from_context(videoOutputStream->codecpar, videoEncoderContext.get()) < 0) {std::cerr << "无法复制视频编码器参数到输出流。" << std::endl;return;}// 打开输出 URLif (!(outputFormatContext->oformat->flags & AVFMT_NOFILE)) {if (avio_open(&outputFormatContext->pb, outputUrl.c_str(), AVIO_FLAG_WRITE) < 0) {std::cerr << "无法打开输出 URL。" << std::endl;return;}}// 写入文件头if (avformat_write_header(outputFormatContext.get(), nullptr) < 0) {std::cerr << "无法写入输出文件头。" << std::endl;return;}// 视频比特流过滤器AVBSFContext* videoBsfContextRaw = nullptr;const AVBitStreamFilter* videoBsf = av_bsf_get_by_name("h264_mp4toannexb");if (!videoBsf) {std::cerr << "未找到 h264_mp4toannexb 比特流过滤器。" << std::endl;return;}if (av_bsf_alloc(videoBsf, &videoBsfContextRaw) < 0) {std::cerr << "无法分配视频比特流过滤器上下文。" << std::endl;return;}std::shared_ptr<AVBSFContext> videoBsfContext(videoBsfContextRaw);if (avcodec_parameters_copy(videoBsfContext->par_in, videoOutputStream->codecpar) < 0) {std::cerr << "无法复制视频参数到比特流过滤器。" << std::endl;return;}if (av_bsf_init(videoBsfContext.get()) < 0) {std::cerr << "无法初始化视频比特流过滤器。" << std::endl;return;}std::shared_ptr<AVFrame> uploadFrame(av_frame_alloc(), AVFrameDeleter());uploadFrame->format = AV_PIX_FMT_YUV420P;uploadFrame->width = decoderContext->width;uploadFrame->height = decoderContext->height;if (av_frame_get_buffer(uploadFrame.get(), 0) < 0) {std::cerr << "无法分配上传帧缓冲区。" << std::endl;return;}std::shared_ptr<AVPacket> uploadPacket(av_packet_alloc(), AVPacketDeleter());std::shared_ptr<SwsContext> swsContext(sws_getContext(decoderContext->width, decoderContext->height,decoderContext->pix_fmt, decoderContext->width, decoderContext->height,AV_PIX_FMT_YUV420P, SWS_BILINEAR, nullptr, nullptr, nullptr),SwsContextDeleter());if (!swsContext) {std::cerr << "无法初始化 SwsContext。" << std::endl;return;}std::shared_ptr<AVFilterGraph> filterGraph(avfilter_graph_alloc(), AVFilterGraphDeleter());if (!filterGraph) {std::cerr << "无法分配过滤器图。" << std::endl;return;}const AVFilter* buffersrc = avfilter_get_by_name("buffer");const AVFilter* buffersink = avfilter_get_by_name("buffersink");AVFilterInOut* outputs = avfilter_inout_alloc();AVFilterInOut* inputs = avfilter_inout_alloc();AVRational time_base = decoderContext->time_base;if (time_base.num == 0 || time_base.den == 0) {time_base = { 1, 25 }; // 设置默认值}AVRational pixel_aspect = decoderContext->sample_aspect_ratio;if (pixel_aspect.num == 0 || pixel_aspect.den == 0) {pixel_aspect = { 1, 1 }; // 设置默认值}char args[512];snprintf(args, sizeof(args),"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",decoderContext->width, decoderContext->height, decoderContext->pix_fmt,time_base.num, time_base.den,pixel_aspect.num, pixel_aspect.den);std::shared_ptr<AVFilterContext> buffersrc_ctx(avfilter_graph_alloc_filter(filterGraph.get(), buffersrc, "in"), AVFilterContextDeleter());if (!buffersrc_ctx) {std::cerr << "无法分配缓冲源过滤器上下文。" << std::endl;return;}int ret = avfilter_init_str(buffersrc_ctx.get(), args);if (ret < 0) {std::cerr << "无法初始化缓冲源过滤器,错误码: " << ret << std::endl;// 打印参数以调试std::cerr << "传递的参数: " << args << std::endl;return;}std::shared_ptr<AVFilterContext> buffersink_ctx(avfilter_graph_alloc_filter(filterGraph.get(), buffersink, "out"), AVFilterContextDeleter());if (!buffersink_ctx) {std::cerr << "无法分配缓冲宿过滤器上下文。" << std::endl;return;}enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };if (av_opt_set_int_list(buffersink_ctx.get(), "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN) < 0) {std::cerr << "无法设置缓冲宿过滤器像素格式。" << std::endl;return;}if (avfilter_init_str(buffersink_ctx.get(), nullptr) < 0) {std::cerr << "无法初始化缓冲宿过滤器。" << std::endl;return;}outputs->name = av_strdup("in");outputs->filter_ctx = buffersrc_ctx.get();outputs->pad_idx = 0;outputs->next = nullptr;inputs->name = av_strdup("out");inputs->filter_ctx = buffersink_ctx.get();inputs->pad_idx = 0;inputs->next = nullptr;if (avfilter_graph_parse_ptr(filterGraph.get(), "null", &inputs, &outputs, nullptr) < 0) {std::cerr << "无法解析过滤器图。" << std::endl;return;}if (avfilter_graph_config(filterGraph.get(), nullptr) < 0) {std::cerr << "无法配置过滤器图。" << std::endl;return;}int64_t nextPts = 0;while (true) {std::unique_lock<std::mutex> lock(frameQueueMutex);if (frameQueueCond.wait_for(lock, std::chrono::milliseconds(100), [&] { return!frameQueue.empty() || stopFlag; })) {if (stopFlag && frameQueue.empty()) {break;}if (!frameQueue.empty()) {auto frame = frameQueue.front();frameQueue.pop();lock.unlock();if (av_buffersrc_add_frame_flags(buffersrc_ctx.get(), frame.get(), AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {std::cerr << "无法将帧添加到过滤器图。" << std::endl;continue;}while (av_buffersink_get_frame(buffersink_ctx.get(), uploadFrame.get()) == 0) {uploadFrame->pts = nextPts++;// 发送帧到视频编码器if (avcodec_send_frame(videoEncoderContext.get(), uploadFrame.get()) < 0) {std::cerr << "发送帧到视频编码器失败。" << std::endl;continue;}// 从视频编码器接收数据包while (avcodec_receive_packet(videoEncoderContext.get(), uploadPacket.get()) == 0) {// 通过视频比特流过滤器if (av_bsf_send_packet(videoBsfContext.get(), uploadPacket.get()) < 0) {std::cerr << "发送数据包到视频比特流过滤器失败。" << std::endl;continue;}while (av_bsf_receive_packet(videoBsfContext.get(), uploadPacket.get()) == 0) {// 调整时间戳av_packet_rescale_ts(uploadPacket.get(), videoEncoderContext->time_base, videoOutputStream->time_base);uploadPacket->stream_index = videoOutputStream->index;// 写入数据包int writeResult = av_interleaved_write_frame(outputFormatContext.get(), uploadPacket.get());if (writeResult < 0) {char errbuf[AV_ERROR_MAX_STRING_SIZE];av_strerror(writeResult, errbuf, AV_ERROR_MAX_STRING_SIZE);std::cerr << "写入视频数据包失败,错误码: " << errbuf << std::endl;break;}}}}}}}// 写入文件尾av_write_trailer(outputFormatContext.get());
}// 显示线程函数
void displayThread(const std::shared_ptr<AVFormatContext>& inputFormatContext, int videoStreamIndex,const std::shared_ptr<AVCodecContext>& decoderContext) {std::shared_ptr<AVFrame> frame(av_frame_alloc(), AVFrameDeleter());std::shared_ptr<AVPacket> packet(av_packet_alloc(), AVPacketDeleter());cv::namedWindow("Camera Feed", cv::WINDOW_NORMAL);while (av_read_frame(inputFormatContext.get(), packet.get()) >= 0) {if (packet->stream_index == videoStreamIndex) {// 发送数据包到解码器if (avcodec_send_packet(decoderContext.get(), packet.get()) < 0) {std::cerr << "发送数据包到解码器失败。" << std::endl;continue;}// 从解码器接收帧while (avcodec_receive_frame(decoderContext.get(), frame.get()) == 0) {// 分配 OpenCV 图像cv::Mat cvFrame(frame->height, frame->width, CV_8UC3);// 转换帧格式uint8_t* dstData[1] = { cvFrame.data };int dstLinesize[1] = { cvFrame.step };SwsContext* swsCtx = sws_getContext(decoderContext->width, decoderContext->height,decoderContext->pix_fmt, decoderContext->width, decoderContext->height,AV_PIX_FMT_BGR24, SWS_BILINEAR, nullptr, nullptr, nullptr);if (swsCtx) {sws_scale(swsCtx, frame->data, frame->linesize, 0, frame->height, dstData, dstLinesize);sws_freeContext(swsCtx);}// 显示帧cv::imshow("Camera Feed", cvFrame);// 按 'q' 键退出if (cv::waitKey(1) == 'q') {stopFlag = true;frameQueueCond.notify_one();return;}// 将帧加入队列{std::unique_lock<std::mutex> lock(frameQueueMutex);if (frameQueue.size() < MAX_QUEUE_SIZE) {auto newFrame = std::shared_ptr<AVFrame>(av_frame_clone(frame.get()), AVFrameDeleter());frameQueue.push(newFrame);frameQueueCond.notify_one();}}}}av_packet_unref(packet.get());}stopFlag = true;frameQueueCond.notify_one();
}int main() {// 初始化 FFmpeg 库avformat_network_init();avdevice_register_all();// 查找 dshow 输入格式const AVInputFormat* iformat = av_find_input_format("dshow");if (!iformat) {std::cerr << "未找到 dshow 输入格式。" << std::endl;return -1;}// 分配格式上下文AVFormatContext* inputFormatContextRaw = nullptr;const char* deviceName = "video=USB2.0 PC CAMERA";// "video=@device_pnp_\\?\\usb#vid_1908&pid_2310&mi_00#7&2892be33&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\global";AVDictionary* options = nullptr;// 设置 rtbufsize 参数,增加缓冲区大小av_dict_set(&options, "rtbufsize", "100000000", 0); // 设置为 100MBif (avformat_open_input(&inputFormatContextRaw, deviceName, const_cast<AVInputFormat*>(iformat), &options) != 0) {std::cerr << "无法打开输入设备。" << std::endl;return -1;}std::shared_ptr<AVFormatContext> inputFormatContext(inputFormatContextRaw, AVFormatContextDeleter());// 查找流信息if (avformat_find_stream_info(inputFormatContext.get(), nullptr) < 0) {std::cerr << "无法找到流信息。" << std::endl;return -1;}// 查找视频流int videoStreamIndex = -1;for (unsigned int i = 0; i < inputFormatContext->nb_streams; i++) {if (inputFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {videoStreamIndex = i;break;}}if (videoStreamIndex == -1) {std::cerr << "未找到视频流。" << std::endl;return -1;}// 查找解码器AVCodecParameters* codecParameters = inputFormatContext->streams[videoStreamIndex]->codecpar;AVCodec* decoder = avcodec_find_decoder(codecParameters->codec_id);if (!decoder) {std::cerr << "未找到合适的解码器。" << std::endl;return -1;}// 分配解码器上下文AVCodecContext* decoderContextRaw = avcodec_alloc_context3(decoder);if (!decoderContextRaw) {std::cerr << "无法分配解码器上下文。" << std::endl;return -1;}std::shared_ptr<AVCodecContext> decoderContext(decoderContextRaw, AVCodecContextDeleter());// 将参数复制到解码器上下文if (avcodec_parameters_to_context(decoderContext.get(), codecParameters) < 0) {std::cerr << "无法复制编解码器参数到上下文。" << std::endl;return -1;}// 打开解码器if (avcodec_open2(decoderContext.get(), decoder, nullptr) < 0) {std::cerr << "无法打开解码器。" << std::endl;return -1;}const std::string outputUrl = "rtsp://192.168.1.100:554/live/test1";std::thread uploader(uploadThread, inputFormatContext, videoStreamIndex, decoderContext, outputUrl);std::thread displayer(displayThread, inputFormatContext, videoStreamIndex, decoderContext);displayer.join();uploader.join();return 0;
}
配置好 ffpmeg opencv 目录
把相关的 DLL 放在运行目录 在 ffpmeg opencv 目录 还有到 msys64\mingw64\bin 目录下找
运行测试 左边的opencv 窗口 右边的 是VLC media player 拉流播放的窗口
4:如果对你又帮助,麻烦点个赞,加个关注
用的 usb摄像头不支持265 ,
下章 做下转化 把 264 转 265 上传 再拉流下来播放
相关文章:
音视频(二)ffmpeg编译及推流
FFmpeg 大名鼎鼎,就不多介绍了 1:环境 win11_amd64 ffpmeg download:https://git.ffmpeg.org/ffmpeg.git ffmpeg msys2 download:https://www.msys2.org/ vs2022 (c 写demo用) 用别的也行 usb2.0 摄像头(有点老) opencv 看上传的…...
syslog 与 Linux 内核日志系统全面解析
在 Linux 系统中,日志是进行系统调试、故障排查和系统安全分析的重要手段。syslog 和内核日志是 Linux 日志组成的核心组件。本文将从原理、实现、配置、常见问题分析等综合解析,全面解读 Linux 下的日志机制。 一、syslog 系统概述 1.1 什么是 syslog …...
SQL问题分析与诊断(8)——关键信息(2)
8.2. 关键信息 8.2.2. 警告 查询计划中,可能会看到出现于操作符上的小图标,特别是黄色或红色的感叹号。这些图标都是警告。并非每个警告都指示一个严重问题,但发现时请检查该图标的属性窗口,其将包含该警告图标的具体细节。 8.…...
HCIA/HCIP基础知识笔记汇总
HCIA/HCIP基础知识笔记汇总 ICT产业链: 上游:芯片制造、元器件生产、光纤光缆制造 中游:硬件组装、软件开发、网络建设维护 下游:电信服务、互联网服务、终端产品 VLAN端口类型: access :…...
vue3 动态路由
定义: 对路由的添加通常是通过 routes 选项来完成的,但是在某些情况下,你可能想在应用程序已经运行的时候添加或删除路由 1. 动态添加路由规则 场景 在应用初始化时,可能需要根据用户的角色或权限动态添加路由规则。 实现 im…...
《Linux内存管理:实验驱动的深度探索》大纲
《Linux内存管理:实验驱动的深度探索》 ——通过递进式实验与问题剖析,从入门到精通 第一部分:初探内存——基础概念与简单实验 目标:理解内存的基本行为,学会观察和提问 第1章 内存初体验:从"free…...
【C语言】深入理解指针(五):sizeof、strlen与数组指针的那些事儿
前言 在C语言的学习中,指针始终是一个让人又爱又恨的话题。它强大而灵活,但同时也充满了陷阱。今天,我们就来深入探讨一下指针相关的几个重要知识点:sizeof和strlen的区别,以及数组和指针在笔试题中的那些常见问题。希…...
CMake学习-- install 指令详细说明
目录 CMake中install命令的用法背景知识使用方法项目结构示例代码CMakeLists.txt构建和安装 详细介绍安装库和头文件安装可执行文件安装额外的文件安装目录结构使用安装的库 总结 CMake中install命令的用法 背景知识 在软件开发过程中,构建和安装是两个重要的环节…...
Cannot find a valid baseurl for repo: centos-sclo-sclo/x86_64
rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-latest-5.0.el7.noarch.rpmyum clean allyum macache fast 编辑配置文件 /etc/yum.repos.d/zabbix.repo and enable zabbix-frontend repository. [zabbix-frontend]...enabled1... 下载相关…...
uniapp 微信小程序 使用ucharts
文章目录 前言一、组件功能概述二、代码结构分析2.1 模板结构 总结 前言 本文介绍一个基于 Vue 框架的小程序图表组件开发方案。该组件通过 uCharts 库实现折线图的绘制,并支持滚动、缩放、触摸提示等交互功能。文章将从代码结构、核心方法、交互实现和样式设计等方…...
空调开机启动后发出噼里啪啦的异响分析与解决
背景 当空调使用时由于制冷或制热运转时(关机后可能也会出现),塑料件热胀冷缩引起,可能会出现“咔咔”的声音;空调冷媒在空调内管路流动时会出现轻微的“沙沙”的声音;也有可能是新装的空调摆风轴出现响声…...
Python爬虫第3节-会话、Cookies及代理的基本原理
目录 一、会话和Cookies 1.1 静态网页和动态网页 1.2 无状态HTTP 1.3 常见误区 二、代理的基本原理 2.1 基本原理 2.2 代理的作用 2.3 爬虫代理 2.4 代理分类 2.5 常见代理设置 一、会话和Cookies 大家在浏览网站过程中,肯定经常遇到需要登录的场景。有些…...
《自然-方法》2024年度技术:空间蛋白质组学(spatial proteomics)
李升伟 编译 《自然-方法》第21卷 2195-2196页 (2024) 解析组织空间蛋白质组的技术,正成为图谱级研究项目的基石。这些项目正在兑现其承诺,帮助人类理解健康和疾病状态下的生物复杂性。 人类天生充满探索欲。我们热爱勘测未知疆域,并随之绘…...
pip安装timm依赖失败
在pycharm终端给虚拟环境安装timm库失败( pip install timm),提示你要访问 https://rustup.rs/ 来下载并安装 Rust 和 Cargo 直接不用管,换一条命令 pip install timm0.6.13 成功安装 简单粗暴...
【工具变量】全国分省低空经济高质量发展数据(2012-2023年)
测算方式:参考CSSCI《北京航空航天大学学报(社会科学版)》沈映春(2024)老师的做法,如商图指标构建图所示。 包含内容: 样例代码: 样例数据: 参考文献:沈映春,张豪兴.数字基础设施建设…...
【Kubernetes】如何使用 kubeadm 搭建 Kubernetes 集群?还有哪些部署工具?
使用 kubeadm 搭建 Kubernetes 集群是一个比较常见的方式。kubeadm 是 Kubernetes 提供的一个命令行工具,它可以简化 Kubernetes 集群的初始化和管理。下面是使用 kubeadm 搭建 Kubernetes 集群的基本步骤: 1. 准备工作 确保你的环境中有两台或更多的机…...
Java 枚举类 Key-Value 映射的几种实现方式及最佳实践
Java 枚举类 Key-Value 映射的几种实现方式及最佳实践 前言 在 Java 开发中,枚举(Enum)是一种特殊的类,它能够定义一组固定的常量。在实际应用中,我们经常需要为枚举常量添加额外的属性,并实现 key-value 的映射关系。本文将详细…...
JavaScript instanceof 运算符全解析
JavaScript instanceof 运算符全解析 核心语义: 判断一个对象(object)是否属于某个构造函数(constructor)或类的实例,基于原型链(prototype chain)实现类型检测。 一、JavaScript 中的基础用法 1. 语法结构 object instanceof constructor 返回值:布尔值(true/fal…...
问题大集09-如何实现vite创建的react项目的配置别名路径@
(1)如何实现vite创建的react项目的配置别名路径 1)直接修改 Vite 配置文件 ①打开项目根目录下的 vite.config.js 文件(如果没有则新建),添加 resolve.alias 配置(新增resolve部分)…...
鸿蒙开发_TS快速入门_TS中模块化操作_模块的导入导出---纯血鸿蒙HarmonyOS5.0工作笔记008
然后我们再来看鸿蒙中的模块如何导入导出。 其实就跟Java中的import是一个意思的。 只不过我们如果想把一个类中的某个方法导入到另一个类中, 那么首先要在这个类中去导出这个方法。 可以看到导出的关键字是export。 然后导入的关键字是import。 然后我们写个例子去看一下,…...
算法设计与分析之“分治法”
分治法(Divide and Conquer)是一种高效的算法设计策略,其核心思想是将复杂问题分解为多个子问题,递归求解后再合并结果。以下是分治法的详细介绍: 一、分治法的基本步骤 分治法遵循以下三步流程: 分解&…...
java 静态内部类
java 静态内部类 一、位置二、特点三、静态内部类的实例化四、代码示例一:演示特点一五、代码示例二:演示特点二六、代码实例三:演示特点三七、代码实例四:演示特点四 文章同步更新(更好的排版):…...
Axure疑难杂症:完美解决文本框读取、赋值、计数(玩转文本框)
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 课程主题:玩转文本框 主要内容:文本框读取、赋值、验证、计数 应用场景:验证码、文本限制、文本取值、文本赋值等场景 案例展示&…...
Python数据可视化-第2章-使用matplotlib绘制简单图表
环境 开发工具 VSCode库的版本 numpy1.26.4 matplotlib3.10.1 ipympl0.9.7教材 本书为《Python数据可视化》一书的配套内容,本章为第2章 使用matplotlib绘制简单图表 本文主要介绍了折线图、柱形图或堆积柱形图、条形图或堆积条形图、堆积面积图、直方图、饼图或…...
国产系统服务器识别不到SATA盘
在使用浪潮、海光、华三等系列服务器安装操作系统的时候提示没有足够的存储空间,其实是有两块512的SATA硬盘的,但是他没有识别到。 需要给硬盘做raid存储阵列才能让系统识别到他,下面是在BIOS中配置RAID的方法。 1、重启机器,按下…...
解决小程序video控件在真机和上线后黑屏不播放问题
小程序上线后,mp4格式的视频无法点击是黑屏,但是测试得时候在微信开发者工具中能够打开正常播放 原因:编码格式不能是vp9 微信开发者工具本地设置中把这个打开勾选。 排查:可以换一个视频尝试能不能真机播放,如果能&a…...
Vue3编译器深度解析:从模板编译到极致性能优化
一、编译技术架构演进 1.1 Vue2到Vue3编译架构升级 1.2 编译阶段性能基准对比 优化项Vue2编译耗时Vue3编译耗时性能提升模板解析速度12ms/千节点3ms/千节点75%AST遍历速度8ms/层级2ms/层级68%代码生成速度15ms/组件4ms/组件73%内存占用峰值84MB32MB62% 二、模板编译核心过程 …...
Google Gemini 2.0 网页抓取真丝滑
网页抓取从未如此简单——这一切都要归功于谷歌突破性的多模态实时API Gemini 2.0 借助这个工具,你可以毫不费力地从任何网页提取数据,无论页面结构多么复杂、内容多么杂乱无章,或是需要提取非常特定的信息。 今天,我将通过自己实…...
Leetcode-100 二分查找常见操作总结
二分查找常见操作总结 1. 基本二分查找 目标: 在有序数组 nums 中查找 target 的索引(如果存在)。 适用场景: 需要在 有序数组 中查找某个特定元素。适用于无重复元素的情况。 示例: 输入 nums [1, 2, 3, 4, 5], target 3,输出 2。 d…...
Android: Handler 的用法详解
Android 中 Handler 的用法详解 Handler 是 Android 中用于线程间通信的重要机制,主要用于在不同线程之间发送和处理消息。以下是 Handler 的全面用法指南: 一、Handler 的基本原理 Handler 基于消息队列(MessageQueue)和循环器(Looper)工作ÿ…...
第149场双周赛:找到字符串中合法的相邻数字、重新安排会议得到最多空余时间 Ⅰ、
Q1、找到字符串中合法的相邻数字 1、题目描述 给你一个只包含数字的字符串 s 。如果 s 中两个 相邻 的数字满足以下条件,我们称它们是 合法的 : 前面的数字 不等于 第二个数字。两个数字在 s 中出现的次数 恰好 分别等于这个数字本身。 请你从左到右…...
深入解析Translog机制:Elasticsearch的数据守护者
一、为什么需要Translog? Elasticsearch的数据写入流程是先写入内存缓冲区,然后定期刷新到磁盘生成Lucene分段。由于内存数据易失性,若在刷新前发生宕机,未持久化的数据将永久丢失。Translog的诞生正是为了解决这一数据可靠性问题…...
音视频入门基础:MPEG2-TS专题(25)——通过FFmpeg命令使用UDP发送TS流
音视频入门基础:MPEG2-TS专题系列文章: 音视频入门基础:MPEG2-TS专题(1)——MPEG2-TS官方文档下载 音视频入门基础:MPEG2-TS专题(2)——使用FFmpeg命令生成ts文件 音视频入门基础…...
3、nFR52xx蓝牙学习(点亮第一个LED灯)
一、点灯代码: led.h文件 #ifndef __LED_H #define __LED_H#include "nrf52840.h"#define LED_0 NRF_GPIO_PIN_MAP(0,13) #define LED_1 NRF_GPIO_PIN_MAP(0,14) #define LED_2 NRF_GPIO_PIN_MAP(0,15) #define LED_3 …...
符号秩检验
内容来源 非参数统计(第2版) 清华大学出版社 王星 褚挺进 编著 符号秩检验 在符号检验的基础上,增加了数据绝对值大小的信息 检验统计量 用一个简单的例子来说明 样本数据 X i , i 1 , ⋯ , 6 X_i,i1,\cdots,6 Xi,i1,⋯,6 如下 X …...
制造业数字化转型:流程改造先行还是系统固化数据?基于以MTO和MTS的投资回报分析
1. 执行摘要 制造业正经历一场深刻的数字化转型,企业面临着先进行流程改造以优化运营,还是直接上线系统以固化数据的战略选择。本文深入分析了以销定产(MTO)和以产定销(MTS)两种主要生产模式下,…...
python相关笔记
一。 is和的区别 1.is看的是发票逻辑地址,用来判断两个变量是否引用同一个对象,is关注的是‘身份’ 2.判断两个对象是否具有相同的值,关注的是内容是否相等,也即值是否相等。 3. if x is None: print(x is None")...
C++(匿名函数+继承+多态)
#include <iostream> #include <cstring> #include <cstdlib> #include <unistd.h> #include <sstream> #include <vector> #include <memory>using namespace std;// 基类 Weapon class Weapon { protected:int atk; public:Weapon…...
界面架构 - MVVM (Qt)
MVVM MVVM 的主要特点示例示例功能示例代码ViewModel 类(C)主函数入口(main.cpp) QML 文件(main.qml)总结 MVVM(Model-View-ViewModel)架构是一种旨在进一步分离界面和业务逻辑的设计…...
在未归一化的线性回归模型中,特征的尺度差异可能导致模型对特征重要性的误判
通过数学公式来更清晰地说明归一化对模型的影响,以及它如何改变特征的重要性评估。 1. 未归一化的情况 假设我们有一个线性回归模型: y β 0 β 1 x 1 β 2 x 2 ϵ y \beta_0 \beta_1 x_1 \beta_2 x_2 \epsilon yβ0β1x1β2x2ϵ 其…...
【大模型系列篇】大模型基建工程:使用 FastAPI 构建 MCP 服务器
今天我们将使用FastAPI来构建 MCP 服务器,Anthropic 推出的这个MCP 协议,目的是让 AI 代理和你的应用程序之间的对话变得更顺畅、更清晰。FastAPI 基于 Starlette 和 Uvicorn,采用异步编程模型,可轻松处理高并发请求,尤…...
基于微信小程序的智慧乡村旅游服务平台【附源码】
基于微信小程序的智慧乡村旅游服务平台(源码L文说明文档) 目录 4系统设计 4.1系统功能设计 4.2系统结构 4.3.数据库设计 4.3.1数据库实体 4.3.2数据库设计表 5系统详细实现 5.1 管理员模块的实现 5.1.1旅游景点管理…...
llm-universe 踩坑记录
踩坑 云服务器2G不够,因为后面用到内存向量数据库,把数据加载到内存,一个大点的pdf就导致整个服务器崩了。当时可以选择不加载大的文件,自己替换一个小点的pdf 注意点 LLM API.ipynb 这节要注意看下API的含义,了解m…...
【案例】跨境电商企业实践云成本优化,选对平台是关键
某跨境电商企业近年因业务发展迅猛,近年来在全球市场大力拓展业务。然而,伴随其全球化布局的深化,云资源成本逐年攀升,每年在云资源方面的投入超 500万元。庞大的云资源使用量虽支撑了业务的快速发展,但也带来了较高的…...
系统思考与时间管理
时间管理的真正秘诀:主动浪费时间? 巴菲特的私人飞机驾驶员觉得自己不够成功,于是向巴菲特请教应该怎么做。巴菲特让他列出了自己人生中最想实现的25个目标,并按重要程度排序,接着安排时间专注做前五件最重要的事情。…...
洛谷.P1563 [NOIP 2016 提高组] 玩具谜题
P1563 [NOIP 2016 提高组] 玩具谜题 - 洛谷 代码区: #include<algorithm> #include<iostream> #include<cstring> #include<string> #include<vector>using namespace std; const int MAX 1000005; struct PEOPLE {int cx;//0朝内…...
华为面试,机器学习深度学习知识点:
机器学习深度学习知识点: 机器学习一般有哪些分数,对于不同的任务: 分类任务: 准确率(Accuracy):预测正确的样本数占总样本数的比例,公式为 Accuracy TPTNFPFN TPTN ,…...
关于 数据库 UNION 和 UNION ALL 的使用,以及 分库分表环境下多表数据组合后的排序和分页问题的解决方案 的详细说明,并以表格总结关键内容
以下是关于 数据库 UNION 和 UNION ALL 的使用,以及 分库分表环境下多表数据组合后的排序和分页问题的解决方案 的详细说明,并以表格总结关键内容: 1. UNION 和 UNION ALL 的核心区别 1.1 定义与语法 UNION 功能:合并两个或多个 …...
架构设计基础系列:事件溯源模式浅析
图片来源网络,侵权删 1. 引言 1.1 研究背景 传统CRUD模型的局限性:状态覆盖导致审计困难、无法追溯历史。分布式系统复杂性的提升:微服务架构下数据一致性、回滚与调试的需求激增。监管合规性要求:金融、医疗等领域对数…...
虚拟试衣间-云尚衣橱小程序-衣橱管理实现
衣橱管理实现 目标 (Goal): 用户 (User): 能通过 UniApp 小程序上传衣服图片。 后端 (Backend): 接收图片,存到云存储,并将图片信息(URL、用户ID等)存入数据库。 用户 (User): 能在小程序里看到自己上传的所有衣服图片列表。 技术栈细化 (Refined Tech Stack for this Pha…...