FFmpeg 与 C++ 构建音视频处理全链路实战(五)—— 音视频编码与封装
在前面的系列文章中,我们已经层层深入,从 MP4 与 FLV 封装格式的剖析,到 H.264 和 AAC 原理的探索,再到 FFmpeg 的解封装、解码,以及音频重采样、视频尺寸变化的代码实现,为音视频处理打下了坚实基础。而今天,我们将迎来整个系列的终章 —— 音视频编码与封装,完成从原始音视频数据到可播放媒体文件的最后蜕变。
一、音视频编码基础回顾与进阶理解
在深入编码实战之前,我们先简单回顾并进一步拓展音视频编码的核心概念。视频编码,以 H.264 为例,其核心思想是通过帧内预测、帧间预测、变换编码和熵编码等技术,去除视频数据中的空间冗余、时间冗余和信息冗余,将庞大的原始视频数据压缩成适合存储和传输的格式。而音频编码,如 AAC,主要利用人耳的听觉特性,通过心理声学模型,将人耳难以感知的音频信息去除,实现高效压缩。
随着技术发展,如今 H.265(HEVC)等新一代视频编码标准凭借更高的压缩效率逐渐崭露头角。它们在 H.264 的基础上,进一步优化了编码算法,例如采用更大的编码单元、更精细的帧内预测模式等,在相同画质下可将码率降低约 50%,这对于带宽资源紧张的场景,如网络视频流传输,有着巨大的应用价值。在音频编码领域,也涌现出了像 Opus 这样的编码格式,它结合了多种编码技术的优势,在低码率下依然能保证出色的音质,适用于实时语音通信等场景。
二、FFmpeg 音视频编码流程剖析
使用 FFmpeg 进行音视频编码,大致可以分为以下几个关键步骤:
2.1 初始化编码器
在编码之前,我们需要根据需求选择合适的编码器,并进行初始化。以视频编码为例,我们可以使用avcodec_find_encoder函数查找 H.264 编码器,然后通过avcodec_alloc_context3分配编码器上下文,并对上下文的参数进行配置,如设置编码分辨率、帧率、码率等。音频编码的初始化过程与之类似,需要设置采样率、声道数、采样格式等参数。
视频:
// 查找编码器
codec = avcodec_find_encoder_by_name(codecName);
if (!codec) {std::cerr << "找不到编码器: " << codecName << std::endl;exit(1);
}
// 分配编码器上下文
codecContext = avcodec_alloc_context3(codec);
if (!codecContext) {std::cerr << "无法分配编码器上下文" << std::endl;exit(1);
}
// 设置编码器参数
codecContext->bit_rate = 400000;
codecContext->width = width;
codecContext->height = height;
codecContext->time_base = {1, fps};
codecContext->framerate = {fps, 1};
codecContext->gop_size = 10;
codecContext->max_b_frames = 1;
codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
音频:
// 设置编码器参数
codecContext->sample_fmt = codec->sample_fmts? codec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
codecContext->sample_rate = sampleRate;
codecContext->channels = channels;
codecContext->channel_layout = av_get_default_channel_layout(channels);
codecContext->bit_rate = 128000;
2.2 准备编码数据
在完成编码器初始化后,我们需要准备待编码的音视频数据。对于视频来说,通常是 YUV 格式的图像帧;音频则是 PCM 格式的音频样本。这些数据可能来自于之前的解码、重采样或其他处理步骤。我们需要将这些原始数据按照编码器的要求进行组织和传递。
// RGB到YUV的转换
const uint8_t* rgbPlanes[1] = { rgbData };
int rgbStrides[1] = { stride };
sws_scale(swsContext, rgbPlanes, rgbStrides, 0, height, frame->data, frame->linesize);
// 重采样
int dstNbSamples = av_rescale_rnd(swr_get_delay(swrContext, sampleRate) + samples,codecContext->sample_rate, sampleRate, AV_ROUND_UP);
int convertedSamples = swr_convert(swrContext, dstData, dstNbSamples,(const uint8_t **)srcData, samples);
2.3 执行编码操作
一切准备就绪后,就可以调用avcodec_send_frame函数将待编码的数据送入编码器,再通过avcodec_receive_packet获取编码后的码流数据。这个过程需要不断循环,直到所有数据都完成编码。
// 发送帧到编码器
if (avcodec_send_frame(codecContext, frame) < 0) {std::cerr << "Error sending frame to encoder" << std::endl;return;
}
// 从编码器接收数据包
while (true) {int ret = avcodec_receive_packet(codecContext, packet);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {break;} else if (ret < 0) {std::cerr << "Error receiving packet from encoder" << std::endl;break;}// 处理编码后的数据包//...av_packet_unref(packet);
}
2.4 释放资源
编码完成后,不要忘记释放编码器上下文以及相关的内存资源,避免内存泄漏。使用avcodec_free_context函数释放编码器上下文,对于编码过程中分配的其他资源,也需要按照对应的释放函数进行处理。
~VideoEncoder() {// 刷新编码器flush_encoder();// 释放资源sws_freeContext(swsContext);av_packet_free(&packet);av_frame_free(&frame);avcodec_free_context(&codecContext);
}
~AudioEncoder() {// 刷新编码器flush_encoder();// 释放资源if (srcData) {av_freep(&srcData[0]);}av_freep(&srcData);if (dstData) {av_freep(&dstData[0]);}av_freep(&dstData);swr_free(&swrContext);av_packet_free(&packet);av_frame_free(&frame);avcodec_free_context(&codecContext);
}
三、音视频封装:将编码后的码流组合成媒体文件
完成音视频编码后,我们得到了视频码流和音频码流,接下来的任务就是将它们封装成完整的媒体文件,如 MP4 或 FLV。封装的过程,就像是将不同的食材(音视频码流)按照特定的菜谱(封装格式规范)烹饪成一道美味的菜肴(媒体文件)。
3.1 选择封装格式与初始化封装器
我们可以使用avformat_alloc_output_context2函数根据指定的封装格式(如 “mp4” 或 “flv”)分配封装器上下文。然后,通过avformat_new_stream函数为视频流和音频流分别创建对应的输出流,并将之前初始化好的音视频编码器上下文与输出流关联起来。
// 分配输出格式上下文
if (avformat_alloc_output_context2(&formatContext, nullptr, nullptr, outputPath.c_str()) < 0) {std::cerr << "无法分配输出格式上下文" << std::endl;exit(1);
}
// 添加视频流
AVStream *stream = avformat_new_stream(formatContext, nullptr);
if (!stream) {std::cerr << "无法创建视频流" << std::endl;exit(1);
}
stream->time_base = codecContext->time_base;
videoStreamIndex = stream->index;
if (avcodec_parameters_from_context(stream->codecpar, codecContext) < 0) {std::cerr << "无法复制编码器参数" << std::endl;exit(1);
}
音频流的添加过程类似,通过类似方式设置相关参数并与编码器上下文关联。
3.2 写入文件头与编码数据
在开始写入音视频数据之前,需要调用avformat_write_header函数写入媒体文件的文件头,文件头中包含了媒体文件的基本信息,如封装格式、音视频流的参数等。之后,将编码后的音视频码流数据通过av_interleaved_write_frame函数写入封装器,该函数会自动将音视频数据按照时间戳进行交错排列,保证播放时音画同步。
// 写入文件头
if (avformat_write_header(formatContext, nullptr) < 0) {std::cerr << "无法写入文件头" << std::endl;exit(1);
}
// 写入视频数据包
AVPacket *newPacket = av_packet_clone(packet);
newPacket->pts -= firstVideoPts;
newPacket->dts -= firstVideoPts;
newPacket->stream_index = videoStreamIndex;
if (av_interleaved_write_frame(formatContext, newPacket) < 0) {std::cerr << "写入视频包失败" << std::endl;
}
av_packet_free(&newPacket);
3.3 写入文件尾并释放资源
当所有音视频数据都写入完成后,调用av_write_trailer函数写入文件尾,文件尾包含了一些用于文件校验和索引的信息。最后,释放封装器上下文以及相关资源,至此,一个完整的媒体文件就封装完成了。
// 写入文件尾
if (isInitialized) {av_write_trailer(formatContext);
}
// 关闭输出文件
if (!(formatContext->oformat->flags & AVFMT_NOFILE) && formatContext->pb) {avio_closep(&formatContext->pb);
}
// 释放格式上下文
avformat_free_context(formatContext);
formatContext = nullptr;
四、实战中的常见问题与解决方案
在实际的音视频编码与封装过程中,难免会遇到各种问题。比如,编码后的视频出现花屏,这可能是由于输入的视频帧格式与编码器不匹配,或者编码器参数设置不当导致的;音频出现杂音,可能是音频采样格式、声道数等参数配置错误。针对这些问题,我们需要仔细检查编码和解码过程中的参数设置,利用 FFmpeg 提供的调试信息进行排查。同时,合理设置缓冲区大小、优化数据传递流程等,也能有效提高编码与封装的稳定性和效率。
至此,我们通过一系列文章,完整地走完了 FFmpeg 与 C++ 构建音视频处理全链路的旅程。从最初对音视频格式和编码原理的探索,到一步步实现解封装、解码、处理、编码与封装,每一个环节都凝聚着音视频技术的精妙之处。希望这个系列文章能为你打开音视频处理的大门,让你在这个充满挑战与魅力的领域中继续探索前行。
相关文章:
FFmpeg 与 C++ 构建音视频处理全链路实战(五)—— 音视频编码与封装
在前面的系列文章中,我们已经层层深入,从 MP4 与 FLV 封装格式的剖析,到 H.264 和 AAC 原理的探索,再到 FFmpeg 的解封装、解码,以及音频重采样、视频尺寸变化的代码实现,为音视频处理打下了坚实基础。而今…...
NNLM神经网络语言模型总结
一开始还以为很复杂,总结一下就是: NNLM 将某个单词前 n−1 个词各自转为 embedding,拼接成一个 (n−1)⋅d 维的向量,再通过隐藏层 输出层 softmax,预测下一个词的概率分布 可以发现,这个2003年提出的模…...
开源Heygem本地跑AI数字人视频教程
图文教程: 点击跳转 视频教程 资料包下载 点击下载:...
软件验收测试有哪些流程?与确认测试又有什么不同?
随着信息技术的飞速发展,软件的应用覆盖面越来越广泛,软件验收测试的重要性也愈发显著。软件验收测试是指在软件开发完成后,对软件进行的最后一次全面审核,以确保软件的功能和性能满足用户需求。这一阶段通常由客户进行࿰…...
一文了解 HTTP Content-Type:从基础到实战
一文了解 HTTP Content-Type:从基础到实战 在 Web 开发中,HTTP 请求头中的 Content-Type 是一个看似简单却至关重要的概念。它决定了浏览器和服务器如何解析和处理传输的数据。本文将带你全面掌握 Content-Type 的核心知识,涵盖常见类型、应…...
数学建模初等模型应用
一、目的 掌握初等模型的建模方法,对简单的初等模型能借助Matlab工具软件进行辅助建模、求解和检验。 二、实验内容与设计思想(设计思路、主要代码分析) 1、预测鱼的质量 (1)设计思路:使用线性回归模型预测鱼的质量…...
map和unordered_map
一、map和unordered_map的基本概念——它们是啥? map:是一种“有序的关联容器”,存放一组“键值对”,内部元素按键排序(默认是升序),类似一本按字母排序的字典。 unordered_map:也是…...
【vue】脚手架
一、使用脚手架创建项目 1.打开编辑器终端 2.输入命令vue create 项目名 3.选择自定义配置,选以下几种常用的配置项(空格选中或删除) 二、常规操作 进入项目:cd 项目名 返回:cd .. 运行项目:npm run serve 停止项目:ct…...
PaddleNLP框架训练模型:使用SwanLab教程
PaddleNLP 是一款基于飞桨深度学习框架的大语言模型(LLM)开发套件,支持在多种硬件上进行高效的大模型训练、无损压缩以及高性能推理。PaddleNLP 具备简单易用和性能极致的特点,致力于助力开发者实现高效的大模型产业级应用。 你可以使用PaddleNLP快速进行…...
单向循环链表C语言实现实现(全)
#include<stdio.h> #include<stdlib.h> #define TRUE 1 #define FASLE 0//定义宏标识判断是否成功 typedef struct Node {int data;struct Node* next; }Node;Node* InitList() {Node* list (Node*)malloc(sizeof(Node));list->data 0;//创建节点保存datalist…...
数据结构:ArrayList简单实现与常见操作实例详解
目录 1.顺序表概念 2.自己实现 1.准备工作 接口 MyArrayList的定义 2.具体接口实现 添加 判满 扩容 查找 获得pos位置的值 和 更改pos位置的值 判空 删除 得到数组长度 清空数组 打印 3.ArrayList 1.简介 2.使用 1.ArrayList的构造 无参构造 有参构造&a…...
C++之fmt库介绍和使用(1)
C之fmt库介绍与使用(1) Author: Once Day Date: 2025年5月12日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: 源码分析_Once-Day的博客-CSDN博客 …...
嵌入式自学第二十一天(5.14)
gdb逻辑调试器: gcc 调试,发行版 gcc -g 调试版本,体积大,有源码。 一般调试:gdb a.out b n.c:行数 :设置断点,运行到这个位置,程序暂停。(可以直接加行数) r运行 n执行下…...
位与运算
只有当除数是 2 的幂次方(如 2、4、8、16...)时,取模运算才可以转换为位运算。 int b 19;int a1 b % 16; // 传统取模运算int a2 b & 15; // 位运算替代取模printf("b %d\n", b);printf("b %% 8 %d\n",…...
SparkSQL操作Mysql(2)
创建数据库和表 我们去创建一个新的数据库,数据表,并插入一条数据。 参考代码如下: -- 创建数据库 CREATE DATABASE spark; -- 使用数据库 USE spark; -- 创建表 create table person(id int, name char(20), age int); -- 插入示例数…...
Linux 中 open 函数的本质与细节全解析
一、open简介 在 Linux 下,一切皆文件。而对文件的读写,离不开文件的“打开”操作。虽然 C 语言标准库提供了方便的 fopen,但更底层、更强大的是系统调用 open,掌握它能让你对文件系统控制更细致,在系统编程、驱动开发…...
对抗系统熵增:从被动救火到主动防御的稳定性实战
📕我是廖志伟,一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》(基础篇)、(进阶篇)、(架构篇)清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、…...
高速系统设计实例设计分析二
6.6 仿真约束的生成和实施 进行到这一步,我们已经完成了对实例进行仿真的所有条件的设置,包括对板子的设计要求分析和预布局处理。虽然从技术上讲,我们可以开始进行仿真分析并生成设计的约束,但是根据作者的工作经验,…...
AUTOSAR图解==>AUTOSAR_SWS_V2XGeoNetworking
AUTOSAR V2X GeoNetworking 模块分析 车联网地理网络协议解析与实现 目录 1. 概述2. 模块架构分析 2.1 AUTOSAR V2X GeoNetworking 在BSW架构中的位置 2.1.1 架构层次说明2.1.2 模块间关系 2.2 V2X GeoNetworking 模块内部组件结构 2.2.1 核心组件2.2.2 接口说明 3. 消息处理…...
在 Rocky Linux 上手动安装 zsh
目录 🧩 一、准备:检查是否已经安装Zsh 🛠️ 二、从源码安装 Zsh(推荐方式) 1. 下载 Zsh 源码 2. 解压源码 3. 配置安装路径(到你的 home 目录下) 4. 编译并安装 🧪 三、测试…...
Vector和list
一、Vector和list的区别——从“它们是什么”到“区别在哪儿” 1. 它们是什么? Vector:类似于一排排整齐的书架(数组),存放元素时,元素排成一条线,连续存储。可以很快通过编号(索引…...
人工智能外呼系统:重构智能交互的全维度进化
在数字化浪潮席卷全球的今天,人工智能外呼系统正以其颠覆性的技术革新,重新定义企业与客户的沟通范式。这一融合语音识别、自然语言处理与机器学习的智能系统,不仅实现了从 “机械应答” 到 “智慧交互” 的跨越,更在金融、医疗、…...
嵌入式培训之数据结构学习(三)gdb调试
一、gdb调试 (一)一般调试步骤与命令 1、gcc -g (调试版本,内含调试信息与源码;eg:gcc -g main.c linklist.c) 2、gdb a.out(调试可执行文件,eg:gdb ./a.o…...
元宇宙赛道新势力:成都芯谷产业园创新业务如何重构产业格局
成都芯谷产业园在元宇宙有啥新搞头?看看它的创新业务怎么改变行业! 成都芯谷产业园在元宇宙赛道上的创新业务,核心在于系统性构建一个开放、协同、高效的元宇宙创新生态系统,以此重构产业格局。这并非简单的企业物理聚集…...
Java 日期解析与格式化:从标准格式到自然语言解析
使用 Java 搭配 Apache Commons Lang3 和 Natty 库,实现灵活高效的日期解析与格式化。 一、背景 将不同格式的日期统一成一个格式。日期格式可能有以下几种类型: 标准格式:2024-02-28、14/05/2022、2002年5月6日非英文月份缩写:…...
【windows server脚本每天从网络盘复制到本地】
windows server脚本每天从网络盘复制到本地 调试模板 echo off :: 显示详细操作 echo echo 执行批处理文件:文件复制任务 echo :: 配置参数 set sourcePath\\network_drive\shared_folder :: 网络盘路径 set destinationPathC:\LocalBackup :: 本地保…...
GraphPad Prism简介、安装与工作界面
GraphPad Prism图表可视化与统计数据分析(视频教学版) - 商品搜索 - 京东 1.1 GraphPad Prism简介 GraphPad Prism 将科学绘图、综合曲线拟合(包括非线性回归)、易于理解的统计分析以及数据管理功能集于一身,帮助用…...
尚硅谷阳哥JVM
文章目录 第01章 JVM快速入门1、什么是JVM2、主流虚拟机有哪些?3、结构图3、执行引擎Execution Engine4、本地方法接口Native Interface5、Native Method Stack6、PC寄存器(程序计数器) 第02章 类加载器ClassLoader1、 类的加载过程2、类加载器的作用3、类加载器分类…...
spark的Standalone模式介绍
Apache Spark 的 Standalone 模式是其自带的集群管理模式,无需依赖外部资源管理器(如 YARN 或 Mesos),可快速部署和运行 Spark 集群。以下是对 Standalone 模式的详细介绍: 1. 核心组件 Master 节点 集群的主控制器…...
自营交易考试中,怎么用“黄昏之星”形态做出漂亮反转单?
在自营交易考试中,如何在复杂的市场波动中抓住关键的趋势反转点,常常决定了一笔交易的成败。尤其是在规则清晰、交易明确的交易考试中,具备对K线形态的敏感度,是不少EagleTrader交易员在晋级过程中总结出的实用经验。今天…...
【算法】版本号排序
对版本号数组进行排序,比如:[0.1.2.3,1.2.1.0,4.2.1.0,0.1.2.0] 核心思路 将版本号拆分为数字数组,逐个比较每个子版本段。具体步骤: 拆分版本号:将每个版本字符串按 . 分割成数字数…...
wordcount程序
### 在 IntelliJ IDEA 中编写和运行 Spark WordCount 程序 要使用 IntelliJ IDEA 编写并运行 Spark 的 WordCount 程序,需按照以下流程逐步完成环境配置、代码编写以及任务提交。 --- #### 1. **安装与配置 IntelliJ IDEA** 确保已正确安装 IntelliJ IDEA&#x…...
MySQL Explain 中 Type 与 Extra 字段详解
引言 在数据库性能调优过程中,理解执行计划(EXPLAIN)的输出信息至关重要。MySQL 的 EXPLAIN 命令能够帮助开发者分析查询的执行路径和效率,其中 Type 和 Extra 字段提供了关键的执行细节。Type 字段表示访问类型,反映…...
代码随想录算法训练营第60期第三十六天打卡
大家好!今天我们就会正式进入动态规划的章节,以前我们相继学完了回溯算法,贪心算法,今天的动态规划应该是相当重要同时也是相当难的章节,那我们废话不多说直接进入我们今天的章节。 第一部分 动态规划理论基础 那究竟…...
Python操作MySQL 连接加入缓存层完整方案
更多内容请见: python3案例和总结-专栏介绍和目录 文章目录 1、整体架构设计2、MySQL 连接方案2.1 使用连接池 (推荐)2.2 使用 SQLAlchemy (ORM方案)3、缓存层实现方案3.1 Redis 缓存实现3.2 Memcached 缓存实现4、完整集成方案4.1 带缓存的数据库访问层4.2 使用装饰器实现缓存…...
PyTorch深度神经网络(前馈、卷积神经网络)
文章目录 神经网络概述神经元模型多层感知机前馈神经网络网络拓扑结构数学表示基本传播公式符号说明整体函数视角 卷积神经网络卷积神经网络发展简史第一代(1943-1980)第二代(1985-2006)第三代(2006-至今)快…...
现代垃圾收集器
大家好,我是你们的花姐。 话说java的长期支持版本已经发展到了JDK21,大部分同学对jvm中的垃圾收集器还停留在java8之前的CMS和G1。对java11之后引入的低延迟垃圾收集器shenandoah和zgc几乎是一无所知,甚至有同学是连这两个名字也没有听过呀,…...
Android学习总结之类LiveData与ViewModel关系篇
1. ViewModel 和 LiveData 的强依赖关系 ViewModel 和 LiveData 虽非强依赖,但在 Android 架构中常紧密协作,这基于它们的设计理念和优势互补: 数据与 UI 分离:ViewModel 的主要职责是存储和管理与 UI 相关的数据,而…...
GaussDB 实例 gsql 连接方式详解
GaussDB 实例 gsql 连接方式详解 GaussDB 是华为云推出的分布式关系型数据库服务,支持多种数据库引擎(如 MySQL、PostgreSQL、SQL Server 等)。gsql 是 GaussDB 提供的命令行客户端工具,用于连接和管理数据库实例。本文将详细介绍…...
智能体制作学习笔记2——情感客服
02 案例1-情感客服_哔哩哔哩_bilibili 目录 一、AI对视频内容总结 二、选择可代替视频总结的方案 三、豆包AI插件安装 四、通义 五、情感客服智能体制作 (一)注册 (二)进入工作空间 (三)创建智能体 (…...
部署GraphRAG配置Neo4j实现知识图谱可视化【踩坑经历】
文章目录 概要部署graphrag(一)使用conda创建虚拟环境(前提已经安装好anaconda)(二)部署graphrag 部署neo4jgraphrag生成的知识图谱导入neo4j踩坑经历1.graphrag执行graphrag index --root ./ragtest命令报错2.neo4j没有Relationship types 概要 在本地部署GraphRag࿰…...
跨域的几种方案
因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名、端口有一个不同就是跨域,Ajax 请求会失败。 我们可以通过以下几种常用方法解决跨域的问题 JSONP JSONP 的原理很简单,就是利用 <script> 标签没有跨域限制…...
5 WPF中的application对象介绍
WPF Application 类提供了一系列生命周期事件,了解它们的触发顺序对于应用程序开发非常重要。以下是主要事件的触发顺序 1. 主要事件顺序 Startup - 应用程序启动时触发 这是第一个触发的事件 适合在此处初始化应用程序级资源 可以在此取消启动(通过设置e.Cancel = true) Act…...
Nexus首次亮相迪拜 TOKEN2049:以“手机 + 钱包 + 公链 + RWA”生态系统引领未来区块链基建
迪拜,2025年5月—— 全球 Web3 基础设施创新平台 Nexus,在本年度迪拜 TOKEN2049 全球峰会 上完成了其主网与全生态系统的首次国际公开亮相。此次参会不仅展示了 Nexus 的国际生态布局,更标志着其迈出了全球化战略关键一步。凭借对现实世界资产…...
C++ 套接字函数详细介绍
目录 头文件1. 套接字创建与配置2. 绑定地址与端口3. 连接建立4. 数据传输5. 套接字选项6. 地址转换7. 套接字关闭8. 其他实用函数 C 套接字函数详细介绍 套接字(Socket)是网络通信的基本端点,C中通常使用BSD套接字API进行网络编程。以下是主要的套接字相关函数及其…...
WordPress 和 GPL – 您需要了解的一切
如果您使用 WordPress,GPL 对您来说应该很重要,您也应该了解它。查看有关 WordPress 和 GPL 的最全面指南。 您可能听说过 GPL(通常被称为 WordPress 的权利法案),但很可能并不完全了解它。这是有道理的–这是一个复杂…...
机器人示教操作
机器人基础操作 **ES机器人试教操作知识** **1. 视角移动** **1.1 基础模式** - 关节轴控制:通过关节1至关节6实现单轴正反转移动 - 直线移动:通过X/Y/Z坐标轴沿指定方向直线移动 - 旋转移动:通过RX/RY/RZ坐标轴绕指定轴旋转 **1.2 步进模式…...
【python】UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xb2
报错 C:\Users\zhangbin\AppData\Local\Programs\Python\Python310\python.exe D:\XTRANS\cuda\03-graph-db\04-cmkg\pdf2zh-v1.9.9-with-assets-win64\pdf2zh\gui.py Traceback (most recent call last): File “D:\XTRANS\cuda\03-graph-db\04-cmkg\pdf2zh-v1.9.9-with-asset…...
[python] python静态方法,类方法,实例方法实现及其区别
一 静态方法 格式: 使用 staticmethmod 装饰器修饰 应用: 某个方法既不需要使用实例属性也不需要使用类属性时,就可以考虑使用静态方法 注意: 静态方法与类无关,可以被转换成函数使用,属于类本身 1.1 经典示例 创建一个与日期相关的辅助函数,这些函数不需要访问或修改类的…...
Kite AI 自动机器人部署教程
最近比较火的AI赛道,每日自动对话训练AI,赚积分 一个个用于 Kite AI 平台的自动交互机器人,支持多钱包和代理。 登记 注册链接 🌟 功能 多钱包支持(手动输入或基于文件) 代理支持(HTTP/HTTP…...