协议-ACLLite-ffmpeg
是什么?
- FFmpeg是一个开源的多媒体处理工具包,它集成了多种功能,包括音视频的录制、转换和流式传输处理。
- FFmpeg由一系列的库和工具组成,其中最核心的是libavcodec和libavformat库。
- libavcodec是一个领先的音频/视频编解码器库,支持多种音频和视频格式的编码和解码操作。
- libavformat库则用于处理各种不同的多媒体容器格式,如MP4、AVI、MKV等。它能够解析提取其中的音频和视频流,以便进行进一步的处理
为什么?
为什么有GStreamer的前提下,还要使用FFmpeg?
- 在某些情况下,GStreamer 会比 FFmpeg 更适合特定的需求
- FFmpeg 是一个功能强大的单体框架,主要专注于媒体的编解码、转码和流处理
- GStreamer适合构建复杂的媒体处理管道,如视频会议、实时流媒体处理和视频编辑
功能 | FFmpeg | GStreamer |
---|---|---|
核心架构 | Monolithic | 模块化,基于管道线 |
易用性 | 使用 CLI 更容易完成简单的媒体任务 | 需要更多设置,但管道灵活 |
编解码器支持 | 广泛的编解码器支持,几乎涵盖所有编解码器 | 功能强大,但通常需要额外的插件 |
使用案例 | 媒体转换、流媒体 | 转码、实时流媒体、媒体应用 |
模块化 | 模块化程度低,围绕特定命令构建 | 模块化程度高,可定制组件 |
插件系统 | 有限的插件系统,主要集中于编解码器 | 广泛的插件系统,用于自定义处理 |
实时处理 | 可以,但不直观 | 专为实时流媒体和处理而设计 |
跨平台 | 是(Linux、Windows、macOS 等) | 是(Linux、Windows、macOS 等) |
复杂性 | 对于简单的任务来说更简单 | 对于复杂的自定义媒体工作流程来说更好 |
许可 | LGPL 或 GPL(取决于配置) | LGPL |
开发者社区 | 庞大、活跃、被广泛采用 | 活跃,但规模小于 FFmpeg |
怎么做?
- 官网Download FFmpeg,选择安装包
Windows builds from gyan.dev
- 找到
release bulids
部分,选择 ffmpeg-release-essentials.zip - 解压文件并检查目录结构
- 配置环境变量 并检验 ffmpeg -version
核心本质
本质就四个名词
- Demuxer:拆解多媒体文件,提取音频和视频流。
- Decoder:将编码后的音频或视频数据解码为原始数据。
- Encoder:将原始音频或视频数据编码为特定格式。
- Muxer:将音频和视频流重新封装为多媒体文件。
- Demuxer:拆解多媒体文件,提取音频和视频流。
- 解码器接收音频、视频、 或字幕基本流,并将它们解码为原始帧( 视频的像素,音频的 PCM)
- 编码器接收原始音频、视频或字幕帧并进行编码 它们被编码为数据包
- Muxer:将音频和视频流重新封装为多媒体文件
大局观总览
- 库总览
真正有用三库
- libavcodec库包含多种音频、视频和字幕流的解码器和编码器,以及多种位流过滤器。
- libavformat库用于将音频、视频和字幕流多路复用和解复用
- libavfilter库用于处理音频/视频数据,例如进行视频的缩放、裁剪、旋转,音频的混音、音量调整
辅助类型库
-
libavutil包含了一些安全的、可移植的字符串函数、随机数生成器、数据结构、额外的数学函数、密码学和与多媒体相关的功能(如枚举像素和采样格式)
-
libswscale是一个用于图像缩放和颜色空间以及像素格式转换的高效库。
-
libswresample是一个高度优化的音频重采样、重矩阵和采样格式转换库。
-
libavdevice是一个通用的框架,用于抓取和渲染许多常见的多媒体输入/输出设备。
-
命令总览
- 功能总览
转换格式流程图
- 输入文件拆解多媒体文件,提取音频和视频流 ;将编码后的音频或视频数据解码为原始数据;将原始音频或视频数据编码为特定格式;将音频和视频流重新封装为多媒体文件;
ffmpeg -i INPUT.mkv -map 0:v -map 0:a -c:v libx264 -c:a copy OUTPUT.mp4
简单的 filtergraph
- 将编码后的音频或视频数据解码为原始数据;并对原始数据进行处理;将原始音频或视频数据编码为特定格式;
复杂 filtergraph 它可能有多个输入,多个输出,可能是不同类型的(音频或 video)
- 第二个输入的帧将叠加在来自第一个输入的帧上。第三个 input 被重新缩放,然后被复制到两个相同的流中。其中之一 它们叠加在组合的前两个输入上,显示为 FilterGraph 的第一个输出。另一个是 filterGraph 的第二个输出
基本命令
ffmpeg -y -c:a libfdk_aac -c:v libx264 -i input.mp4 -c:v libvpx-vp9 -c:a libvorbis output.webm
- -y:不经过确认,输出时直接覆盖同名文件
- -c:指定编码器
- -c copy:直接复制,不经过重新编码(这样比较快)
- -c:v:指定视频编码器
- -c:a:指定音频编码器
- -i:指定输入文件
- -an:去除音频流
- -vn: 去除视频流
- -preset:指定输出的视频质量,会影响文件的生成速度,有以下几个可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow。
- -f:fmt指定格式(音频或视频格式)
- -t:duration 记录时长为t
- -acodec: 音频选项, 一般后面加copy表示拷贝
- -vcodec:视频选项,一般后面加copy表示拷贝
- h264: 表示输出的是h264的视频裸流
- mp4: 表示输出的是mp4的视频
- mpegts: 表示ts视频流
ffmpeg -r 1 -i racing.mp4 -c:v libx264 -profile:v high -level:v 5.1 -c:a copy -r 60 racingoutput.mp4
- -r 强制输入文件的帧速率(仅对 Raw 格式有效)为 1 fps,并且 输出文件的帧速率为 24 fps
- -profile:v -level 设置H.264画质级别
ffmpeg -i input.avi output.mp4
- 通过重新编码媒体流,将输入媒体文件转换为其他格式
ffmpeg -i input.avi -b:v 64k -bufsize 64k output.mp4
- -b:v 64k 设置输出文件的视频码率为 64 kbit/s
Streamcopy 流复制 -map 的使用
ffmpeg -i INPUT.mkv -map 0:1 -c copy OUTPUT.mp4
ffmpeg -i INPUT0.mkv -i INPUT1.aac -map 0:0 -map 1:0 -c copy OUTPUT.mp4
ffmpeg -i INPUT.mkv -map 0:0 -c copy OUTPUT0.mp4 -map 0:1 -c copy OUTPUT1.mp4
推拉流RTSP命令
UDP推流
ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream
- -re 为以流的方式读取
TCP推流
ffmpeg -re -i input.mp4 -c copy -rtsp_transport tcp -f rtsp rtsp://127.0.0.1:8554/stream
循环推流
ffmpeg -re -stream_loop -1 -i input.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream
- -stream_loop 为循环读取视频源的次数,-1为无限循环
拉流
ffplay rtsp://127.0.0.1:8554/stream
FFmpeg拉流保存成视频
ffmpeg -stimeout 30000000 -i rtsp://127.0.0.1:8554/stream -c copy output.mp4
- -stimeout 30000000 为等待RTSP 流连接的时间,单位为us微秒,等待 30 秒如果连接失败则退出
过滤器(fliter)命令
-
过滤器就是实现某一种视频功能的工具,FFmpeg自带开发了很多种filter用于实现不同的功能
-
源视频宽度扩大两倍
ffmpeg -i jidu.mp4 -t 10 -vf pad=2 * iw output.mp4
- 源视频水平翻转
ffmpeg -i jidu.mp4 -t 10 -vf hflip output2.mp4
- 水平翻转视频覆盖output.mp4
ffmpeg -i output.mp4 -i output2.mp4 -filter_complex overlay=w compare.mp4
核心结构体
- 围绕解协议,解封装,解码
- libavcodec 的核心是 AVCodec 和 AVCodecContext
AVIOContext,URLProtocol,URLContext,AVFormatContext
解协议(http,rtsp,rtmp,mms)
- AVIOContext,URLProtocol,URLContext
- AVIOContext是FFMPEG管理输入输出数据的结构体,内含指针指向URLContext结构体
- URLContext结构体中包含结构体URLProtocol
- URLContext存储音频/视频使用的协议的类型以及状态
- URLProtocol存储音频/视频使用的协议(rtp,rtmp,file等)操作函数接口
解封装(flv,avi,rmvb,mp4)
- AVFormatContext存储音频/视频封装包含的数据和信息
- AVInputFormat表示音频/视频输入格式
AVCodec AVCodecContext AVStream
架构类似于昇腾的device conent steam
解码(h264,mpeg2,aac,mp3)
- AVCodecContext,存储该音视频流使用解码器的相关数据(所需的上下文环境)
- AVCodec (该音视频的解码器)(h264 mpeg2 AAC mp3)
- 实际使用时有可能会有多个 AVCodecContext 关联同一个 AVCodec 的情况。尤其是我们解码音频的时候。
音频文件时 5.1声道的 AVCodec AVCodecContext AVStream关系
-
通常会对应 3 个 AVStream
- 左右声道在一个 AVStream
- 环绕声在一个 AVStream
- 最后低音在另一个AVStream
-
3 个AVStream的编码可能是相同的
-
解码这个音频文件时就应该建立 3 个 AVCodecContext ,分别对应三个 AVStream。然后只需要有 1 个 AVCodec 。每个 AVCodecContext 都利用这一个 AVCodec 来解码。
AVPacket - AVFrame
- 所谓解码就是把一个 AVPacket 中的数据解成 AVFrame
- AVPacket是 编码压缩之后的数据
- AVFrame 是原始的,没有编码、没有压缩的数据 对视频来说是YUV RGB,对音频来说是PCM
I帧 P帧 B帧 的影响
-
我们会遇到前几个 AVPacket 解不出数据。
- 到了某个 AVPacket ,可以连续解出多个 AVFrame 来的情况。
- 这时这多个 AVFrame 就包括前面积压的 AVPacket 里的数据
-
avcodec_send_packet() 调用一次将一个 packet 推给Codec,
-
avcodec_receive_frame() 调用一次或多次来获得 frame
华为昇腾ACLLite库封装ffmpeg案例
什么是华为昇腾ACLLite库?
- ACLLite库是对CANN提供的ACL接口进行的高阶封装,简化用户调用流程,为用户提供一组简易的公共接口。当前主要针对边缘场景设计
ACLLite\Media\CameraRead.cpp
void CameraRead::DecodeFrameThread(void* decoderSelf)
对照核心结构体 理解 具体解码流程
void CameraRead::DecodeFrameThread(void* decoderSelf)
{CameraRead* thisPtr = (CameraRead*)decoderSelf;int videoStreamIndex = -1;for (int i = 0; i < thisPtr->formatContext_->nb_streams; ++i) {if (thisPtr->formatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {videoStreamIndex = i;break;}}if (videoStreamIndex == -1) {LOG_PRINT("[ERROR] usb camera %s index is -1", thisPtr->streamName_.c_str());thisPtr->isOpened_ = false;return;}AVCodecParameters* codecParameters = thisPtr->formatContext_->streams[videoStreamIndex]->codecpar;AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id);if (codec == nullptr) {LOG_PRINT("[ERROR] Could not find ffmpeg decoder.");thisPtr->isOpened_ = false;return;}AVCodecContext* codecContext = avcodec_alloc_context3(codec);if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) {LOG_PRINT("[ERROR] Could not create decoder context.");thisPtr->isOpened_ = false;return;}if (avcodec_open2(codecContext, codec, nullptr) < 0) {LOG_PRINT("[ERROR] Could not open decoder context.");thisPtr->isOpened_ = false;return;}AVFrame* frame = av_frame_alloc();AVPacket packet;while (av_read_frame(thisPtr->formatContext_, &packet) >= 0 && !thisPtr->isStop_) {if (packet.stream_index == videoStreamIndex) {int response = avcodec_send_packet(codecContext, &packet);if (response < 0 || response == AVERROR(EAGAIN)) {continue;}while (response >= 0) {response = avcodec_receive_frame(codecContext, frame);if (response == AVERROR(EAGAIN)) {break;} else if (response < 0) {LOG_PRINT("[ERROR] Receive false frame from ffmpeg.");thisPtr->isOpened_ = false;return;}bool ret = thisPtr->SendFrame(packet.data, packet.size);if (!ret) {thisPtr->isOpened_ = false;LOG_PRINT("[ERROR] Send single frame from ffmpeg failed.");return;}}}av_packet_unref(&packet);}av_frame_free(&frame);avcodec_close(codecContext);avformat_close_input(&thisPtr->formatContext_);thisPtr->isOpened_ = false;return;
}
- avcodec_find_decoder 根据编解码参数的编解码器ID查找对应的编解码器
- avcodec_alloc_context3 分配编解码器上下文
- avcodec_open2 打开编解码器上下文
- av_frame_alloc 分配帧结构体
- av_read_frame 从输入文件中读取一个数据包(AVPacket),并将其存储到 packet 中
- avcodec_send_packet 将一个数据包发送到解码器
- avcodec_receive_frame 从解码器中接收一个解码后的帧
- SendFrame 用于将解码后的帧发送到其他地方(例如显示或进一步处理)
- av_frame_free avcodec_close avformat_close_input 最后释放资源
ACLLite\DVPPLite\src\VideoRead.cpp
void FFmpegDecoder::Decode(FrameProcessCallBack callback,void *callbackParam)
对照核心结构体 理解 具体解码流程
void FFmpegDecoder::Decode(FrameProcessCallBack callback,void *callbackParam)
{LOG_PRINT("[INFO] Start ffmpeg decode video %s ...", streamName_.c_str());avformat_network_init(); // init networkAVFormatContext* avFormatContext = avformat_alloc_context();// check open video resultif (!OpenVideo(avFormatContext)) {return;}int videoIndex = GetVideoIndex(avFormatContext);if (videoIndex == kInvalidVideoIndex) { // check video index is validLOG_PRINT("[ERROR] Rtsp %s index is -1", streamName_.c_str());return;}AVBSFContext* bsfCtx = nullptr;// check initialize video parameters resultif (!InitVideoParams(videoIndex, avFormatContext, bsfCtx)) {return;}LOG_PRINT("[INFO] Start decode frame of video %s ...", streamName_.c_str());AVPacket avPacket;int processOk = true;// loop to get every frame from video streamwhile ((av_read_frame(avFormatContext, &avPacket) == 0) && processOk && !isStop_) {if (avPacket.stream_index == videoIndex) { // check current stream is video// send video packet to ffmpegif (av_bsf_send_packet(bsfCtx, &avPacket)) {LOG_PRINT("[ERROR] Fail to call av_bsf_send_packet, channel id:%s",streamName_.c_str());}// receive single frame from ffmpegwhile ((av_bsf_receive_packet(bsfCtx, &avPacket) == 0) && !isStop_) {int ret = callback(callbackParam, avPacket.data, avPacket.size);if (ret != 0) {processOk = false;break;}}}av_packet_unref(&avPacket);}av_bsf_free(&bsfCtx); // free AVBSFContext pointeravformat_close_input(&avFormatContext); // close input videoisFinished_ = true;LOG_PRINT("[INFO] Ffmpeg decoder %s finished", streamName_.c_str());
}
- av_read_frame 从输入文件中读取一个数据包(AVPacket)
- av_bsf_send_packet 数据包发送到解码器
- av_bsf_receive_packet 从解码器中接收解码后的帧
- callback 进一步处理
- av_packet_unref av_bsf_free avformat_close_input 最后释放资源
根据对应类型初始化过滤器
void FFmpegDecoder::InitVideoStreamFilter(const AVBitStreamFilter*& videoFilter)
{if (videoType_ == AV_CODEC_ID_H264) { // check video type is h264videoFilter = av_bsf_get_by_name("h264_mp4toannexb"); // 目的是从Avcodec库中获取一个名为"h264_mp4toannexb"的视频过滤器。} else { // the video type is h265videoFilter = av_bsf_get_by_name("hevc_mp4toannexb");}
}
附录-h264基础概念
H264
为什么诞生
-
⼀段分辨率为 1920 * 1080,每个像素点为 RGB 占⽤3 个字节,帧率是 25 的视频,对于传输带宽的要求是
-
换成 bps 则意味着视频每秒带宽为 1186.523Mbps,这样的速率对于⽹络存储是不可接受的
-
H264 采⽤了 16 * 16 的分块⼤⼩对,视频帧图像进⾏相似⽐较和压缩编码
- 一帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU 了
H264有两种封装
-
H.264码流分Annex-B和mp4两种格式。
-
⼀种是 annexb 模式,传统模式
-
⼀种是 mp4 模式,⼀般 mp4 mkv 都是 mp4 模式
-
很多解码器只⽀持 annexb 这种模式,因此需要将 mp4 做转换:
-
在 ffmpeg 中⽤h264_mp4toannexb_filter 可以做转换
ffmpeg -i INPUT.mp4 -codec copy -bsf:v h264_mp4toannexb OUTPUT.ts
- -bsf:v h264_mp4toannexb:指定视频过滤器为h264_mp4toannexb,这个过滤器的作用是将H.264流从长度前缀模式转换为开始代码前缀模式。
H.264有四种画质级别,分别是baseline, extended, main, high:
- Baseline Profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC;
- Extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;(用的少)
- Main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced), 也支持CAVLC 和CABAC 的支持;
- High profile:高级画质。在main Profile 的基础上增加了8x8内部预测、自定义量化、 无损视频编码和更多的YUV 格式;
ffmpeg -i input.mp4 -profile:v baseline -level 3.0 output.mp4
ffmpeg -i input.mp4 -profile:v main -level 4.2 output.mp4
ffmpeg -i input.mp4 -profile:v high -level 5.1 output.mp4
GOP - I帧 P帧 B帧
-
编码器将多张图像进行编码后生产成一段一段的 GOP ( Group of Pictures )
-
解码器在播放时则是读取一段一段的 GOP 进行解码后读取画面再渲染显示
-
GOP ( Group of Pictures) 是一组连续的画面,由一张 I 帧和数张 B / P 帧组成
-
I 帧是内部编码帧(也称为关键帧),P帧是前向预测帧(前向参考帧),B 帧是双向内插帧(双向参考帧)
简单地讲,I 帧是一个完整的画面,而 P 帧和 B 帧记录的是相对于 I 帧的变化。
- I帧表示关键帧,你可以理解为经过适度地压缩这一帧画面的完整保留
- P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别
- B帧记录的是本帧与前后帧的差别
- B帧传送的是它与前面的I帧或P帧和后面的P帧之间的预测误差及运动矢量
有了 I帧,P帧, 为什么需要B帧
- 因为B帧记录的是前后帧的差别,比P帧能节约更多的空间
IDR 图像(立即刷新图像)
- 一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像
- H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,
- 将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列
- 如果前一个序列出现重大错误,在这里可以获得重新同步的机会
- IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码
DTS PTS
为什么会有PTS和DTS的概念
-
P帧需要参考前面的I帧或P帧才可以生成一张完整的图片
-
B帧则需要参考前面I帧或P帧及其后面的一个P帧才可以生成一张完整的图片
-
这样就带来了一个问题:在视频流中,先到来的 B 帧无法立即解码,需要等待它依赖的后面的 I、P 帧先解码完成,这样一来播放时间与解码时间不一致了,顺序打乱了,那这些帧该如何播放呢?
PTS和DTS的概念
- DTS(Decoding Time Stamp):即解码时间戳
- 这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
- PTS(Presentation Time Stamp):即显示时间戳
- 这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。
文档链接说明
-
官方文档
Documentation (ffmpeg.org) -
基本概念
I帧、P帧、B帧、GOP、IDR 和PTS, DTS之间的关系 - 夜行过客 - 博客园 -
参考文档
音视频八股文 – h264 AnnexB_音视频开发面试八股文-CSDN博客 -
参考文档
FFmpeg基础知识之-—— H264编码profile & level控制_ffmpeg level-CSDN博客 -
参考文档
基于 FFMPEG 的视频解码(libavcodec ,致敬雷霄骅)-CSDN博客 -
参考文档
ffmpeg 结构体之间的关系_packet解码frame之间的对应-CSDN博客
FFMPEG结构体分析:AVIOContext-CSDN博客 -
参考文档
ffmpeg 常用命令汇总_ffmpeg命令大全-CSDN博客
基于FFmpeg进行rtsp推流及拉流(详细教程)_ffmpeg rtsp推流-CSDN博客 -
华为昇腾ACLLite仓库
Ascend/ACLLite -
华为昇腾对照概念
AscendCL架构及基本概念-AscendCL应用开发概述-AscendCL应用开发(C&C++)-应用开发-开发指南-CANN社区版8.0.0.alpha003开发文档-昇腾社区
相关文章:
协议-ACLLite-ffmpeg
是什么? FFmpeg是一个开源的多媒体处理工具包,它集成了多种功能,包括音视频的录制、转换和流式传输处理。FFmpeg由一系列的库和工具组成,其中最核心的是libavcodec和libavformat库。 libavcodec是一个领先的音频/视频编解码器库&…...
flask开发的网站,后端服务关闭后,可以找回之前的数据的吗
如果使用 Flask 开发的网页,后端服务关闭后,是否还能找回数据取决于数据的存储方式: 可能找回数据的情况: 数据库存储(MySQL、PostgreSQL、SQLite 等) 如果 Flask 连接的是持久化数据库,即使后…...
deepseek API开发简介
1、申请deepseek api key: https://platform.deepseek.com/api_keys创建API Key,并复制Key 2、安装python、pip,然后安装requests pip install requests3、.示例代码 import requests import json# DeepSeek API 地址 API_URL "ht…...
【AI】在Ubuntu中使用docker对DeepSeek的部署与使用
这篇文章前言是我基于部署好的deepseek-r1:8b模型跑出来的 关于部署DeepSeek的前言与介绍 在当今快速发展的技术环境中,有效地利用机器学习工具来解决问题变得越来越重要。今天,我将引入一个名为DeepSeek 的工具,它作为一种强大的搜索引擎&a…...
Baklib推进内容中台智能推荐系统的技术创新与执行方案
内容概要 在当前数字化快速发展的背景下,内容中台的智能化推荐系统显得尤为重要。通过技术创新,Baklib致力于提升平台的用户体验,实现精准的个性化推荐,满足多样化的用户需求。内容中台不仅能够高效管理和组织大量的信息与知识&a…...
MySQL8.0实现MHA高可用
一、简介 MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL 主从复制架构提供了 automating master failover 功能。MHA 在监控到 master 节点故障时,会提升其中拥有最新数据的 slave 节点成为新的master 节点…...
ip地址是手机号地址还是手机地址
在数字化生活的浪潮中,IP地址、手机号和手机地址这三个概念如影随形,它们各自承载着网络世界的独特功能,却又因名称和功能的相似性而时常被混淆。尤其是“IP地址”这一术语,经常被错误地与手机号地址或手机地址划上等号。本文旨在…...
多光谱成像技术在华为Mate70系列的应用
华为Mate70系列搭载了光谱技术的产物——红枫原色摄像头,这是一款150万像素的多光谱摄像头。 相较于普通摄像头,它具有以下优势: 色彩还原度高:色彩还原准确度提升约 120%,能捕捉更多光谱信息,使拍摄照片色…...
21.2.6 字体和边框
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 通过设置Rang.Font对象的几个成员就可以修改字体,设置Range.Borders就可以修改边框样式。 【例 21.6】【项目ÿ…...
详解命令模式
引言 当遇到发送者和接受者之间不是直接连接关系,而是间接连接关系,即发送者和接受者之间需要解耦,我们通常需要命令模式。比如电灯和开关,开关设计时并不知道自己是控制电灯的,也可能控制排气扇、电力设备等等&#x…...
Debian 安装 Nextcloud 使用 MariaDB 数据库 + Caddy + PHP-FPM
前言 之前通过 docker在ubuntu上安装Nextcloud,但是现在我使用PVE安装Debian虚拟机,不想通过docker安装了。下面开始折腾。 安装过程 步骤 1:更新系统并安装必要的软件 sudo apt update && sudo apt upgrade -y sudo apt install…...
string 与 wstring 的字符编码
测试代码: #include<stdio.h> #include<stdlib.h> #include<windows.h> #include <locale.h> #include <string> #include <iostream>// 函数用于计算UTF-8字符串中的字符数 int utf8_strlen(const char* str) {int len = 0;for (; *s…...
golang 开启HTTP代理认证
内部网路不能直接访问外网接口,可以通过代理发送HTTP请求。 HTTP代理服务需要进行认证。 package cmdimport ("fmt""io/ioutil""log""net/http""net/url""strings" )// 推送CBC07功能 func main() {l…...
第九届华为ICT大赛实践赛中国总决赛举行通知及考试地址
经大赛组委会决定,第九届华为ICT大赛实践赛中国总决赛将于2025年3月8日-9日举行具体赛事安排如下,期待与您顶峰相见! 理论考试:线上答题,团队3名成员共同完成1套试题,统一提交一份答案【60分钟,20道试题(含判断、单选…...
FFmpeg 与 FFplay 参数详解:-f、-pix_fmt、-pixel_format 和 -video_size 的区别与用法
FFmpeg 与 FFplay 参数详解:-f、-pix_fmt、-pixel_format 和 -video_size 的区别与用法 在使用 FFmpeg 和 FFplay 进行视频处理和播放时,-f、-pix_fmt、-pixel_format 和 -video_size 是常用的参数。这些参数的作用和使用场景略有不同,理解它们的区别和用法对于正确处理和播…...
深入理解 C++17 std::is_swappable
文章目录 深入理解 C17 std::is_swappable引言std::is_swappable 概述std::is_swappable 的工作原理std::is_swappable 的变体注意事项结论 深入理解 C17 std::is_swappable 引言 在 C 编程中,交换两个对象的值是一个常见的操作。为了确保代码的通用性和安全性&am…...
直接插入排序
一:直接插入排序是什么。 二:如何实现直接插入排序 三:直接插入排序时间复杂度 一:直接插入排序它是排序得一种,其目的无非是将乱序通过排序排成有序的。 我们可以通过动画直观看什么是直接插入排序 这是我找的直接…...
基于可信数据空间的企业数据要素与流通体系建设(附ppt 下载)
近期,可信数据空间会议召开。大数据系统软件国家工程研究中心总工程师王晨发表了题为《基于可信数据空间的企业数据要素与流通体系建设》主旨演讲。 WeChat Subscription Account【智慧城市指北】,可搜索相关关键字“20250107”,可获取具体获…...
处理 this
this指向改变this this指向 构造函数和原型对象都指向 实例 改变this指向的三个方法: call()apply()bind() call() apply() 与call的区别就是call中参数任意,但是apply中参数必须是数组 bind()(最重要) 与…...
kafka服务端之日志存储
文章目录 日志布局日志索引日志清理日志删除基于时间基千日志大小基于日志起始偏移量 日志压缩总结 日志布局 Ka饮a 中的消息是以主题为基本单位进行归类的, 各个主题在逻辑 上相互独立。 每个主题又可以分为一个或多个分区, 分区的数量可以在主题创建的…...
【Apache Paimon】-- 15 -- 利用 paimon-flink-action 同步 postgresql 表数据
利用 Paimon Schema Evolution 核心特性同步变更的 postgresql 表结构和数据 1、背景信息 在Paimon 诞生以前,若 mysql/pg 等数据源的表结构发生变化时,我们有几种处理方式 (1)人工消息通知,然后手动同步到数据仓库中(2)使用 flink 消费 DDL binlog ,然后自动更新 Hi…...
正则表达式进阶(二)——零宽断言详解:\b \B \K \z \A
在正则表达式中,零宽断言是一种非常强大的工具,能够在不消费字符的情况下对匹配位置进行约束。除了环视(lookahead 和 lookbehind)以外,还有一些常用的零宽断言,它们用于处理边界、字符串的开头和结尾等特殊…...
java poi Excel 文件导入导出常见错误及解决方案
在使用 Apache POI 进行 Excel 文件的导入导出操作时,可能会遇到各种问题。以下是一些常见的错误及其解决方案: 一、文件格式相关问题 1. 文件格式不兼容 问题描述:尝试使用 HSSFWorkbook 读取 .xlsx 文件,或者使用 XSSFWorkbo…...
批量提取word表格数据到一个excel
新建一个excel到word同级目录altf11打开vba窗口并新建模块粘贴下方代码(修改一些必要参数)回到excel表格界面,altf8选择执行该宏注意要在信任中心开启运行vba宏 Sub 批量提取word表格数据到excel()Dim wdApp As Object, wdDoc As ObjectDim …...
快速建立私有化知识库(私有化训练DeepSeek,通过ollama方式)
简介 什么?!老是有人问你需求,不同版本的需求你记不清还得去扒拉过程文档、设计文档? 什么?!领导会询问功能使用情况、用户相关数据,你每次还得手动查询反馈? 什么?&…...
python 一句话打印行号
在C语言中,打印行号可以直接用预定义的宏__LINE__,打印当前行号,方便调试。 printf("%d", __LINE__); // C语言打印当前行号 python中没有这样的预定义宏。 但可以用这种方式,实现一句话打印行号: impor…...
设计模式-生产者消费者模型
阻塞队列: 在介绍生产消费者模型之前,我们先认识一下阻塞队列。 阻塞队列是一种支持阻塞操作的队列,常用于生产者消费者模型,它提供了线程安全的队列操作,并且在队列为空或满时,能够阻塞等待,…...
Kubernetes是什么?为什么它是云原生的基石
从“手工时代”到“自动化工厂” 想象一下,你正在经营一家工厂。在传统模式下,每个工人(服务器)需要手动组装产品(应用),效率低下且容易出错。而Kubernetes(k8s)就像一个…...
全国计算机等级考试(NCRE)四级计算机网络考试大纲(2025年版)
文章目录 基本要求1. 理解计算机网络的基本概念。2. 掌握局域网的基本工作原理。局域网(LAN)基本工作原理 3. 掌握TCP/IP及其相关协议。 TCP/IP协议及其相关协议1. TCP/IP协议的分层结构2. 主要协议详解(1)IP协议(2&am…...
扩展知识--缓存和分时复用cpu
在多核CPU中,缓存和分时复用CPU是两个重要的概念,它们分别涉及硬件架构和资源管理策略。以下将从缓存的层次结构、工作原理以及分时复用CPU的概念进行详细解释。 一、多核CPU中的缓存 缓存的定义与作用 缓存(Cache)是位于CPU与主…...
6.Centos7上部署flask+SQLAlchemy+python+达梦数据库
情况说明 前面已经介绍了window上使用pycharm工具开发项目时,window版的python连接达梦数据库需要的第三方包。 这篇文章讲述,centos7上的python版本连接达梦数据库需要的第三方包。 之前是在windows上安装达梦数据库的客户端,将驱动包安装到windows版本的python中。(开…...
如何将3DMAX中的3D文件转换为AutoCAD中的2D图形?
大家好,今天我们来探讨一下如何将3DMAX中的3D文件转换为AutoCAD中的2D图形。无论是出于设计交流、施工准备还是其他实际需求,这种转换在工程设计领域都是一项非常实用的技能。接下来,我将为大家详细介绍几种实现这一转换的方法,帮助大家轻松跨越3D与2D设计之间的鸿沟。让我…...
使用LLaMA Factory踩坑记录
前置条件:电脑显卡RTX 4080 问题:LLaMA-Factory在运行的时候,弹出未检测到CUDA的报错信息 结论:出现了以上的报错,主要可以归结于以下两个方面: 1、没有安装GPU版本的pytorch,下载的是CPU版本…...
四柱预测学
图表 后天八卦 十二地支不仅代表了时间,还代表了方位。具体来说: 子:代表正北方丑寅:合起来代表东北方卯:代表正东方辰巳:合起来代表东南方午:代表正南方未申:合起来代表西南方酉:代表正西方戌亥:合起来代表西北方四季-五行-六神…...
使用 JFreeChart 创建动态图表:从入门到实战
文章目录 前言一、JFreeChart 简介二、环境准备三、 创建第一个折线图四、自定义图表样式4.1 设置背景色4.2 设置折线颜色4.3 设置字体(解决中文乱码)4.4 设置横坐标的标签宽度和方向 五、导出图表六、实战:动态生成日报图表总结 前言 在数据…...
【自学笔记】文言一心的基础知识点总览-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 文心一言知识点总览一、文心一言简介二、文心一言的核心功能三、文心一言的技术特点四、文心一言的应用场景五、文心一言的使用技巧六、文心一言的未来发展 总结 文…...
解锁AI语音魅力——yoyo鹿鸣在线语音合成器,让创意声音即刻绽放!
yoyo鹿鸣-在线语音合成 人工智能语音克隆生成,二次元~ AI工具 | AI探金 可以在AI探金社区来找我~ yoyo鹿鸣 - 在线语音生成器 需求人群: 有语音合成需求的用户。 使用场景示例: 合成yoyo鹿鸣语音 等等 产品特色&a…...
【无标题】堆
[TOC](优先级队列(堆)) 【本节目标】 1. 掌握堆的概念及实现 2. 掌握 PriorityQueue 的使用 # 1. 优先级队列 ## 1.1 概念 前面介绍过队列,**队列是一种先进先出(FIFO)的数据结构**,但有些情况下,**操作的数据可…...
【工具变量】上市公司企业绿色新闻数据(2013-2023年)
测算方式: 参考《中国工业经济》周泽将(2023)老师的做法,首先通过网络爬虫的方法检索并爬取上市公司相关新闻,并辅以人工检索补充校对;新闻文本清理,并通过公司相关性判定以及主题模型识别该新闻是否为上市公司环保主…...
【vue】高德地图AMap.Polyline动态更新画折线,逐步绘制
可以使用 setTimeout 或 setInterval 来逐个点绘制折线,确保每次添加新的点到 path 并更新 Polyline,如下所示: localPolyline(path) {console.log(逐点绘制 polyline...);let drawnPath []; // 用于存储当前绘制的点let index 0;let poly…...
Lecture8 | LPV VXGI SSAO SSDO
Review: Lecture 7 | Lecture 8 LPV (Light Propagation Volumes) Light Propagation Volumes(LPV)-孤岛惊魂CryEngine引进的技术 LPV做GI快|好 大体步骤: Step1.Generation of Radiance Point Set Scene Representation 生成辐射点集的场景表示:辐射…...
三种Excel文本连接方法!
大家好,我是小鱼。 在处理Excel表格数据时,有时需要对表格某些单元格中的文本进行连接组合。今天就跟大家分享3种Excel文本连接方法!学会后遇到Excel文本连接问题也不求人! 方法一、使用&符号连接 使用&符号连接文本的话…...
ubuntu 本地部署deepseek r1 蒸馏模型
本文中的文件路径或网络代理需要根据自身环境自行删改 一、交互式chat页面 1.1 open-webui 交互窗口部署:基于docker安装,且支持联网搜索 Open WebUI 是一个可扩展、功能丰富且用户友好的自托管 AI 平台,旨在完全离线操作。它支持各种 LLM…...
如何删除本地大模型
随着Deepseep模型的爆火,越来越多的用户尝试在本地安装并体验这一强大的AI工具。然而,许多人在安装过程中发现,模型默认会安装在C盘,而C盘的空间通常有限,尤其是对于那些系统盘容量较小的用户来说,这无疑是…...
【共享文件夹】使用Samba服务可在Ubuntu和Windows系统之间共享一个实际的文件夹
目标:在Ubuntu和Windows系统之间共享一个实际的文件夹,并能够共同编辑其中的文件 安装Samba创建共享文件夹配置Samba设置Samba密码重启Samba服务以应用更改:在Windows中访问共享文件夹如果客户机无法访问 Samba 服务器,解决方法①…...
用Llama Factory单机多卡微调Qwen2.5时报torch.OutOfMemoryError: CUDA out of memory的解决办法
接着上一篇博客:在Ubuntu上用Llama Factory命令行微调Qwen2.5的简单过程_llamafactory 微调qwen 2.5-CSDN博客 如果需要微调比较大的模型,例如Qwen2.5-32B,那么在两个3090上可能不够用,这里我用A60004的服务器。但如果仿照上篇博…...
第 26 场 蓝桥入门赛
3.电子舞龙【算法赛】 - 蓝桥云课 问题描述 话说这年头,连舞龙都得电子化!这不,蓝桥村的老程序员王大爷突发奇想,用LED灯带和一堆传感器鼓捣出了一条“电子舞龙”,它能根据程序指令在村里的广场上“翩翩起舞”。 广…...
文华财经期货支撑压力多空K线变色期货指标,博易大师指标公式大全
低线:25,DOT; 中线:55,DOT; 高线:85,DOT; LOWV:LLV(LOW,9); HIGHV:HHV(HIGH,9); RSV:EMA((CLOSE-LOWV)/(HIGHV-LOWV)*100,3); K:EMA(RSV,3); 趋势线:MA(K,3); DBA:K-趋势线; STICKLINE(DBA>0,(K-DBA*0.1),(K-DBA*0.75),2,0),COLORRED; STICKLINE(DBA<0,(趋势线DBA*0.1),…...
基于大模型的围术期脆弱性评估系统研究报告
一、引言 1.1 研究背景与意义 围术期是指从患者决定接受手术治疗开始,到手术治疗直至基本康复的全过程,包括术前、术中和术后三个阶段。围术期管理对于保障患者安全、提高治疗效果具有至关重要的意义。在术前阶段,全面准确的评估患者身体状况能够帮助医生提前发现潜在风险…...
星网锐捷 视频话机设备pwdsetting管理密码信息泄漏
星网锐捷 视频话机设备pwdsetting管理密码信息泄漏 漏洞描述 星网锐捷视频话机设备 泄露管理员密码,攻击者可利用密码直接进入后台配置页面,执行恶意操作,进行一步攻击。 威胁等级: 高危 漏洞分类: 信息泄露 涉及厂商及产品:…...