首页 Home.

剖析 Java 虚拟机(JVM)内存模型的字节码层面,可以更深入理解 JVM 的内存分配、线程交互以及字节码如何影响性能优化。以下是深入探讨的关键点: 1. JVM 内存模型概述 JVM 内存模型分为以下几个主要区域: JVM 的内存模型确保了多线程环境中对共享变量的可见性和有序性,通过 主内存(Main Memory) 和 工作内存(Working Memory) 来实现。 2. 字节码与 JVM 内存模型的交互 字节码是 Java 源代码编译后的指令集,它通过以下方式与 JVM 内存模型交互: 2.1 加载与类元信息存储 2.2 操作数栈与局部变量表 每个栈帧都包含操作数栈和局部变量表。以下是常见字节码的行为: 2.3 堆与方法区的交互 3. JVM 内存模型与线程安全 JVM 使用内存屏障(Memory Barrier)和指令重排序规则来确保线程间的可见性和一致性。以下是与字节码相关的线程安全机制: 3.1 volatile 的实现 3.2 synchronized 的实现 3.3 原子操作 4. JVM 字节码调优 通过分析字节码,可以进行以下优化: 5. 工具与实践 5.1 使用工具 5.2 示例分析 以下是简单代码的字节码拆解: 反编译结果: 5.3 分析结果 通过剖析字节码和 JVM 内存模型,可以深入理解 Java 的运行时行为,优化性能,提升多线程编程的安全性和效率。如果你对具体的字节码示例或某些机制有进一步需求,欢迎继续探讨!

https://arthurchiao.art/blog/how-nat-traversal-works-zh/#231-%E5%8F%8C%E5%90%91%E4%B8%BB%E5%8A%A8%E5%BB%BA%E8%BF%9E%E6%97%81%E8%B7%AF%E4%BF%A1%E9%81%93

https://wanglichao.com https://www.cnblogs.com/zhengyun_ustc https://developer.aliyun.com/article/25562

  • 安装详细介绍见官网: https://docs.getutm.app/guides/windows 安装方式一:VHDX 需要事先准备好 1.spice-guest-tools-0.164.4.iso 安装驱动镜像官网下载 2.Windows11_InsiderPreview_Client_ARM64_en-us_26080.VHDX 安装虚拟镜像 下载地址 以下是安装步骤: 安装方式二:ISO 需要事先准备好 1.spice-guest-tools-0.164.4.iso 安装驱动镜像官网下载 2.Windows 11.iso 安装镜像 下载地址 以下是安装步骤: 参考: https://archive.org/download/WIndows-XP-Professional-SP3 https://www.bilibili.com/read/cv22694631 https://wiki.eryajf.net/pages/3f19f0/#_4-%E5%AE%89%E8%A3%85

  • PlantUML是一个通用性很强的工具,可以快速、直接地创建各种图表。利用简单直观的语言,用户可以毫不费力地绘制各种类型的图表。支持序列图、用例图、类图、对象图、活动图、组件图、部署图、状态图、时序图。 「毫不费力」这个特点非常有吸引力,当然没那么夸张,还是要费点力气的。它有自己的一套语法,类似于写代码的方式表示各个实体之间的关系、指示要生成哪种类型的图。用过 Markdown 的一下就能理解。 举个例子,下面的代码可以表示 Client 向 Server 发送 Hello。 如果你想自己用它的语法规则,通过写代码的方式画图,可以到官网 https://plantuml.com/zh/ 上学习一下语法。 可以直接在 PlantUML 在线环境上运行 https://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000 上方写代码,下面就直接生成对应的 UML 图了,可以调整样式,可以下载各种格式的图片。 也可以在本地安装运行,支持 Java 包运行,也支持 Docker 。 另外,像 VSCode 这些编辑器或者一些笔记软件都有对应的插件支持,可以搜索安装。 ChatGPT + PlantUML 如果你还是觉得不够「毫不费力」,那可以让 ChatGPT 直接生成给你。 打开 ChatGPT ,在「探索 GPT」里面可以搜索 “PlantUML Diagram Wizard”,这个应用是专门用来帮你画 PlantUML 的,但是使用的话需要 GPT-4o,如果超过最大限制,则需要开通 plus 才能用,有实力的同学可以用这个。 不用它也完全可以,我就直接用的免费版 ChatGPT-3.5,效果也没有问题。除此之外,用 Kimi 等大模型应该也问题不大。 那应该怎么给 ChatGPT 提示词呢? 下面我举几个例子,不一定是最好的,但是基本上能解决问题。 用 ChatGPT 怎么做呢? 第一步就是将代码给到 ChatGPT。这一步要看你的代码量有多少,如果代码量不多的话,可以一次性都给它,如果多的话,ChatGPT 的输入token 是有限制的,就要分批次告诉它。 第一步 prompt:接下来我会发给你几个 java 文件,在我告诉你开始画图之前,你只需要记住文件的内容就好了。之后GPT会表示明白了,请你发送文件内容。 第二步:将你要画的文件一个个的输送给 GPT。 第三步:好了,请帮我生成 PlantUML 格式的类图,请开始画图吧。 然后 GPT 就会输出一个 PlantUML 代码段。

  • JSON Hero 是一个简单实用的 JSON 工具,通过简洁美观的 UI 及增强的额外功能,使得阅读和理解 JSON 文档变得更容易、直观。 支持多种视图以便查看 JSON:列视图、树视图、JSON 视图等 本地安装 要在本地运行 JSON Hero,首先 clone 源代码,并安装相关依赖项: Then, create a file at the root of the repo called .env and set the SESSION_SECRET value: Then, run npm run build or npm run dev to build. Now, run npm start and open your browser to http://localhost:8787 源码地址 https://github.com/triggerdotdev/jsonhero-web

  • 在遇到锁竞争激烈的时候,很多开发人员会想到“我需要一个更快的锁”。实际上,某些锁实现机制异常缓慢,对于这类锁,可以使用更快的锁来代替。但是,快慢是相对的,无论锁的速度有多快,都必然会导致线程串行化,因此使用更快的锁对程序性能的提高是一个定值,对程序的可扩展性并无改善。要提高程序的可扩展性,要么不使用锁,要么化解锁的竞争。 在前面讨论死锁时,曾经提到可以通过复制资源的方式来避免使用锁。只要可行,这是一个非常好的解决方法。这样,每个线程访问自己的资源副本,从而可以避免使用锁。如果有需要的话,可以在程序的最后将各个线程占有的资源副本合并成一个单一的共享资源副本。 根据排队理论,一个资源闲置得越少,要得到它的平均等待时间就越长。这种关系是非线性的;如果锁的个数翻倍,平均等待这个锁的时间就比原来的两倍还要多。减少对锁的等待时间的最有效方法是减少这个锁所保护的范围大小。所以如果某个资源无法被复制,就可以考虑将该资源分割成若干个部分,然后用彼此独立的锁分别保护分割以后的各个部分。考虑多个线程同时向一个散列表中插入数据的情形。为了避免数据竞争,每个线程在访问散列表的时候都需要对散列表加锁。这种方案存在一个重大的缺陷,所有的线程都必须竞争同一个锁,这就形成了一个性能瓶颈。于是我们可以通过一个散列函数,将关键字映射到一个子表,并且使每个子表有一个独立的锁。对于一个给定的关键字,线程可以使用散列函数将关键字映射到一个子表,然后线程取得这个子表的锁,再对这个子表进行操作。只要有足够数量的子表和足够好的散列函数,线程之间就不会出现竞争同一个子表的锁的情况。 基于将竞争分担到多个锁的思想,出现了细粒度锁(fine-grained locking)的概念。例如,散列表一般是以桶数组(array of buckets)的方式实现,数组中每个桶都包含被映射到同一数组元素的关键字。在细粒度锁机制中,每个桶上都可能有一个锁。这样,多个线程就可以并发访问不同的桶。如果桶的数量固定,就可以直接实现。但是如果桶的数量必须不断增加,情况就比较复杂,因为进行数组大小变化时,锁将锁定整个桶数组,这就意味着只有进行当前操作的线程能够访问桶数组,其他的线程都被拒绝访问。可以使用读写锁解决这个问题。这种机制的另一个缺点是如果桶容量很小,那么锁的空间开销就会变得很显著。 如果一个数据结构读取频繁但是写入并不频繁,就可以使用读写锁(reader-writer lock)来解决竞争。读写锁可以区分写入者和读取者。多个读取者可以同时获取锁,但某一个时刻只有一个写入者可以获取锁。读取者在写入者持有锁的时候不能获取锁。 在多数访问为读访问,而写访问频率较低、持续时间也比较短的情况下,读写锁的性能最好。多个读线程与单个写线程交替进行操作,所以读线程和写线程都不会长时间阻止。 一个线程可以持有读线程锁或写线程锁,但是不能同时持有两者。 读线程和写线程将分别排入各自的队列。当线程释放写线程锁时,此刻读线程队列中的所有等待线程都将被授予读线程锁;当已释放所有读线程锁时,写线程队列中处于等待状态的下一个线程(如果存在)将被授予写线程锁,依此类推。换句话说,ReaderWriterLock 在一组读线程和一个写线程之间交替进行操作。 当写线程队列中有一个线程在等待活动读线程锁被释放时,请求新的读线程锁的线程会排入读线程队列。即使它们能和现有的读线程锁持有者共享并发访问,也不会给它们的请求授予权限;这有助于防止写入者被读取者无限期阻塞。 大多数在读写锁上获取锁的方法都采用超时值。使用超时可以避免应用程序中出现死锁。例如,某个线程可能获取了一个资源上的写线程锁,然后请求第二个资源上的读线程锁;同时,另一个线程获取了第二个资源上的写线程锁,并请求第一个资源上的读线程锁。如果不使用超时,这两个线程将出现死锁。如果超时间隔过期并且没有授予锁请求,则此方法通过引发ApplicationException 将控制返回给调用线程。线程可以捕捉此异常并确定下一步要进行的操作。 在使用细粒度锁的时候,需要提到的一点是过细粒度将增加对锁的请求和释放的频率,因而会增加额外的指令。您必须在过细和过粗粒度之间找到平衡。最佳粒度不得不通过试验找到。下图显示了锁的吞吐量和粒度之间的关系。 图:锁的吞吐量和粒度之间的关系 这个图是一个简单的双坐标轴图表。垂直轴或 y 轴表示吞吐量。水平轴或 x 轴表示粒度,沿着坐标标尺向外移动时粒度从精细到粗糙而变化。一条延长的贝尔曲线表明了粒度对吞吐量的关系。随着粒度从精细到粗糙,吞吐量逐渐增加到一个最大水平,然后开始慢慢下降。这表明为了达到最大吞吐量,必须在粒度上折衷。

  • 序号 分类 内容 备注 1 业务评审 需求背景,期望目标 业务是否合理 2 业务流程、交互方式 3 技术评审 整体架构设计(架构图) 技术是否合理 4 数据模型设计 5 关键技术、核心算法 6 数据交互方式 7 核心接口设计 8 中间件 消息中间件 配置是否申请 9 任务调度 10 搜索引擎 11 文件存储 12 数据安全 历史数据处理 13 数据补偿方案 14 灰度方案 客户端灰度 15 接口灰度 16 回滚策略 17 系统性能 需求系统性能 TPS、RT、VU(并发用户数)各是多少? 18 随着数据量的增大系统性能会不会出现明显问题 19 系统哪个环节会是最大的瓶颈?系统性能拐点是那里? 20 是否打算做压力测试?做哪些类型的压力测试,为何?压力测试方案是怎么样的? 21 性能瓶颈发生后是否有降级或熔断措施? 22 可伸缩性 每一个环节是否都是可以横向扩展的? 水平扩容、垂直扩容 23 数据库不能横向扩展怎么办? 24 扩展后是否可以提高响应速度? 25 可靠性 MQ或存储出现问题的时候系统会怎么样? 26 是否有数据丢失的可能性? 27 数据丢失后是否可以恢复? 28 系统彻底挂了对其它业务的影响是什么? 29 监控&日志&告警 是否接入统一日志系统 30 是否接入全链路日志 31 告警粒度? 32 其他 上线顺序 33 服务调用申请 34 开关配置

  • 写法如下: 控制台打印sql语句如下:

  • 1. 先提前视频的音频 2. 把提前出来的音频变声(速度会变慢,到是视频变长) 3. 把速度改成和最开始的音频速度一直 4. 把变声后的音频和视频合并 FFmpeg介绍 要给一个视频添加新的音频,你可以使用 FFmpeg 工具来实现。你需要先提取视频的音频流,然后将新的音频文件合并到视频中。以下是一个示例命令: 解释: 执行此命令后,FFmpeg 将会从输入的视频文件中提取视频流,从新的音频文件中提取音频流,然后将视频流和音频流合并为一个新的 MP4 视频文件。你可以将 input_video.mp4 替换为你实际的视频文件名,new_audio.mp3 替换为你希望添加的新音频文件名,output_video.mp4 替换为你希望保存的输出视频文件名。 请确保你已经安装了 FFmpeg,并且已经将其添加到系统的环境变量中,这样你就可以在命令行中直接调用 FFmpeg 命令。 源码:https://github.com/ycltpe/tools

  • 在 macOS 上,你可以使用相同的 Python 代码来利用 Tesseract-OCR 提取图片中的文字。你可以按照以下步骤操作: 在这个示例中,example.png 是你要提取文字的图片文件。pytesseract.image_to_string(img) 函数将图片转换为文字,并返回识别结果。 这样,你就可以在 macOS 上使用 Python 和 Tesseract-OCR 提取图片中的文字了。

  • 有什么办法把视频里的声音提取出来转成mp3 你可以使用专门的音频提取工具来从视频文件中提取声音,并将其转换为 MP3 格式。以下是一种常见的方法: 实操预览 2. 使用在线转换工具: 无论你选择哪种方法,提取视频中的声音并将其转换为 MP3 格式都是相对简单的操作。

  • Hexo 是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown(或其他标记语言)解析文章,在几秒内,即可利用靓丽的主题生成静态网页。 参考: https://github.com/fluid-dev/hexo-theme-fluid https://hexo.io/zh-cn/docs/ https://www.zhangkunzhi.com/ https://github.com/ycltpe/blogHexo

  • 安装详细介绍见官网: https://docs.getutm.app/guides/windows 安装方式一:VHDX 需要事先准备好 1.spice-guest-tools-0.164.4.iso 安装驱动镜像官网下载 2.Windows11_InsiderPreview_Client_ARM64_en-us_26080.VHDX 安装虚拟镜像 下载地址 以下是安装步骤: 安装方式二:ISO 需要事先准备好 1.spice-guest-tools-0.164.4.iso 安装驱动镜像官网下载 2.Windows 11.iso 安装镜像 下载地址 以下是安装步骤: 参考: https://archive.org/download/WIndows-XP-Professional-SP3 https://www.bilibili.com/read/cv22694631 https://wiki.eryajf.net/pages/3f19f0/#_4-%E5%AE%89%E8%A3%85

  • PlantUML是一个通用性很强的工具,可以快速、直接地创建各种图表。利用简单直观的语言,用户可以毫不费力地绘制各种类型的图表。支持序列图、用例图、类图、对象图、活动图、组件图、部署图、状态图、时序图。 「毫不费力」这个特点非常有吸引力,当然没那么夸张,还是要费点力气的。它有自己的一套语法,类似于写代码的方式表示各个实体之间的关系、指示要生成哪种类型的图。用过 Markdown 的一下就能理解。 举个例子,下面的代码可以表示 Client 向 Server 发送 Hello。 如果你想自己用它的语法规则,通过写代码的方式画图,可以到官网 https://plantuml.com/zh/ 上学习一下语法。 可以直接在 PlantUML 在线环境上运行 https://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000 上方写代码,下面就直接生成对应的 UML 图了,可以调整样式,可以下载各种格式的图片。 也可以在本地安装运行,支持 Java 包运行,也支持 Docker 。 另外,像 VSCode 这些编辑器或者一些笔记软件都有对应的插件支持,可以搜索安装。 ChatGPT + PlantUML 如果你还是觉得不够「毫不费力」,那可以让 ChatGPT 直接生成给你。 打开 ChatGPT ,在「探索 GPT」里面可以搜索 “PlantUML Diagram Wizard”,这个应用是专门用来帮你画 PlantUML 的,但是使用的话需要 GPT-4o,如果超过最大限制,则需要开通 plus 才能用,有实力的同学可以用这个。 不用它也完全可以,我就直接用的免费版 ChatGPT-3.5,效果也没有问题。除此之外,用 Kimi 等大模型应该也问题不大。 那应该怎么给 ChatGPT 提示词呢? 下面我举几个例子,不一定是最好的,但是基本上能解决问题。 用 ChatGPT 怎么做呢? 第一步就是将代码给到 ChatGPT。这一步要看你的代码量有多少,如果代码量不多的话,可以一次性都给它,如果多的话,ChatGPT 的输入token 是有限制的,就要分批次告诉它。 第一步 prompt:接下来我会发给你几个 java 文件,在我告诉你开始画图之前,你只需要记住文件的内容就好了。之后GPT会表示明白了,请你发送文件内容。 第二步:将你要画的文件一个个的输送给 GPT。 第三步:好了,请帮我生成 PlantUML 格式的类图,请开始画图吧。 然后 GPT 就会输出一个 PlantUML 代码段。

  • JSON Hero 是一个简单实用的 JSON 工具,通过简洁美观的 UI 及增强的额外功能,使得阅读和理解 JSON 文档变得更容易、直观。 支持多种视图以便查看 JSON:列视图、树视图、JSON 视图等 本地安装 要在本地运行 JSON Hero,首先 clone 源代码,并安装相关依赖项: Then, create a file at the root of the repo called .env and set the SESSION_SECRET value: Then, run npm run build or npm run dev to build. Now, run npm start and open your browser to http://localhost:8787 源码地址 https://github.com/triggerdotdev/jsonhero-web

  • 在遇到锁竞争激烈的时候,很多开发人员会想到“我需要一个更快的锁”。实际上,某些锁实现机制异常缓慢,对于这类锁,可以使用更快的锁来代替。但是,快慢是相对的,无论锁的速度有多快,都必然会导致线程串行化,因此使用更快的锁对程序性能的提高是一个定值,对程序的可扩展性并无改善。要提高程序的可扩展性,要么不使用锁,要么化解锁的竞争。 在前面讨论死锁时,曾经提到可以通过复制资源的方式来避免使用锁。只要可行,这是一个非常好的解决方法。这样,每个线程访问自己的资源副本,从而可以避免使用锁。如果有需要的话,可以在程序的最后将各个线程占有的资源副本合并成一个单一的共享资源副本。 根据排队理论,一个资源闲置得越少,要得到它的平均等待时间就越长。这种关系是非线性的;如果锁的个数翻倍,平均等待这个锁的时间就比原来的两倍还要多。减少对锁的等待时间的最有效方法是减少这个锁所保护的范围大小。所以如果某个资源无法被复制,就可以考虑将该资源分割成若干个部分,然后用彼此独立的锁分别保护分割以后的各个部分。考虑多个线程同时向一个散列表中插入数据的情形。为了避免数据竞争,每个线程在访问散列表的时候都需要对散列表加锁。这种方案存在一个重大的缺陷,所有的线程都必须竞争同一个锁,这就形成了一个性能瓶颈。于是我们可以通过一个散列函数,将关键字映射到一个子表,并且使每个子表有一个独立的锁。对于一个给定的关键字,线程可以使用散列函数将关键字映射到一个子表,然后线程取得这个子表的锁,再对这个子表进行操作。只要有足够数量的子表和足够好的散列函数,线程之间就不会出现竞争同一个子表的锁的情况。 基于将竞争分担到多个锁的思想,出现了细粒度锁(fine-grained locking)的概念。例如,散列表一般是以桶数组(array of buckets)的方式实现,数组中每个桶都包含被映射到同一数组元素的关键字。在细粒度锁机制中,每个桶上都可能有一个锁。这样,多个线程就可以并发访问不同的桶。如果桶的数量固定,就可以直接实现。但是如果桶的数量必须不断增加,情况就比较复杂,因为进行数组大小变化时,锁将锁定整个桶数组,这就意味着只有进行当前操作的线程能够访问桶数组,其他的线程都被拒绝访问。可以使用读写锁解决这个问题。这种机制的另一个缺点是如果桶容量很小,那么锁的空间开销就会变得很显著。 如果一个数据结构读取频繁但是写入并不频繁,就可以使用读写锁(reader-writer lock)来解决竞争。读写锁可以区分写入者和读取者。多个读取者可以同时获取锁,但某一个时刻只有一个写入者可以获取锁。读取者在写入者持有锁的时候不能获取锁。 在多数访问为读访问,而写访问频率较低、持续时间也比较短的情况下,读写锁的性能最好。多个读线程与单个写线程交替进行操作,所以读线程和写线程都不会长时间阻止。 一个线程可以持有读线程锁或写线程锁,但是不能同时持有两者。 读线程和写线程将分别排入各自的队列。当线程释放写线程锁时,此刻读线程队列中的所有等待线程都将被授予读线程锁;当已释放所有读线程锁时,写线程队列中处于等待状态的下一个线程(如果存在)将被授予写线程锁,依此类推。换句话说,ReaderWriterLock 在一组读线程和一个写线程之间交替进行操作。 当写线程队列中有一个线程在等待活动读线程锁被释放时,请求新的读线程锁的线程会排入读线程队列。即使它们能和现有的读线程锁持有者共享并发访问,也不会给它们的请求授予权限;这有助于防止写入者被读取者无限期阻塞。 大多数在读写锁上获取锁的方法都采用超时值。使用超时可以避免应用程序中出现死锁。例如,某个线程可能获取了一个资源上的写线程锁,然后请求第二个资源上的读线程锁;同时,另一个线程获取了第二个资源上的写线程锁,并请求第一个资源上的读线程锁。如果不使用超时,这两个线程将出现死锁。如果超时间隔过期并且没有授予锁请求,则此方法通过引发ApplicationException 将控制返回给调用线程。线程可以捕捉此异常并确定下一步要进行的操作。 在使用细粒度锁的时候,需要提到的一点是过细粒度将增加对锁的请求和释放的频率,因而会增加额外的指令。您必须在过细和过粗粒度之间找到平衡。最佳粒度不得不通过试验找到。下图显示了锁的吞吐量和粒度之间的关系。 图:锁的吞吐量和粒度之间的关系 这个图是一个简单的双坐标轴图表。垂直轴或 y 轴表示吞吐量。水平轴或 x 轴表示粒度,沿着坐标标尺向外移动时粒度从精细到粗糙而变化。一条延长的贝尔曲线表明了粒度对吞吐量的关系。随着粒度从精细到粗糙,吞吐量逐渐增加到一个最大水平,然后开始慢慢下降。这表明为了达到最大吞吐量,必须在粒度上折衷。

  • 序号 分类 内容 备注 1 业务评审 需求背景,期望目标 业务是否合理 2 业务流程、交互方式 3 技术评审 整体架构设计(架构图) 技术是否合理 4 数据模型设计 5 关键技术、核心算法 6 数据交互方式 7 核心接口设计 8 中间件 消息中间件 配置是否申请 9 任务调度 10 搜索引擎 11 文件存储 12 数据安全 历史数据处理 13 数据补偿方案 14 灰度方案 客户端灰度 15 接口灰度 16 回滚策略 17 系统性能 需求系统性能 TPS、RT、VU(并发用户数)各是多少? 18 随着数据量的增大系统性能会不会出现明显问题 19 系统哪个环节会是最大的瓶颈?系统性能拐点是那里? 20 是否打算做压力测试?做哪些类型的压力测试,为何?压力测试方案是怎么样的? 21 性能瓶颈发生后是否有降级或熔断措施? 22 可伸缩性 每一个环节是否都是可以横向扩展的? 水平扩容、垂直扩容 23 数据库不能横向扩展怎么办? 24 扩展后是否可以提高响应速度? 25 可靠性 MQ或存储出现问题的时候系统会怎么样? 26 是否有数据丢失的可能性? 27 数据丢失后是否可以恢复? 28 系统彻底挂了对其它业务的影响是什么? 29 监控&日志&告警 是否接入统一日志系统 30 是否接入全链路日志 31 告警粒度? 32 其他 上线顺序 33 服务调用申请 34 开关配置

  • 写法如下: 控制台打印sql语句如下:

  • 1. 先提前视频的音频 2. 把提前出来的音频变声(速度会变慢,到是视频变长) 3. 把速度改成和最开始的音频速度一直 4. 把变声后的音频和视频合并 FFmpeg介绍 要给一个视频添加新的音频,你可以使用 FFmpeg 工具来实现。你需要先提取视频的音频流,然后将新的音频文件合并到视频中。以下是一个示例命令: 解释: 执行此命令后,FFmpeg 将会从输入的视频文件中提取视频流,从新的音频文件中提取音频流,然后将视频流和音频流合并为一个新的 MP4 视频文件。你可以将 input_video.mp4 替换为你实际的视频文件名,new_audio.mp3 替换为你希望添加的新音频文件名,output_video.mp4 替换为你希望保存的输出视频文件名。 请确保你已经安装了 FFmpeg,并且已经将其添加到系统的环境变量中,这样你就可以在命令行中直接调用 FFmpeg 命令。 源码:https://github.com/ycltpe/tools

  • 在 macOS 上,你可以使用相同的 Python 代码来利用 Tesseract-OCR 提取图片中的文字。你可以按照以下步骤操作: 在这个示例中,example.png 是你要提取文字的图片文件。pytesseract.image_to_string(img) 函数将图片转换为文字,并返回识别结果。 这样,你就可以在 macOS 上使用 Python 和 Tesseract-OCR 提取图片中的文字了。

  • 有什么办法把视频里的声音提取出来转成mp3 你可以使用专门的音频提取工具来从视频文件中提取声音,并将其转换为 MP3 格式。以下是一种常见的方法: 实操预览 2. 使用在线转换工具: 无论你选择哪种方法,提取视频中的声音并将其转换为 MP3 格式都是相对简单的操作。

  • Hexo 是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown(或其他标记语言)解析文章,在几秒内,即可利用靓丽的主题生成静态网页。 参考: https://github.com/fluid-dev/hexo-theme-fluid https://hexo.io/zh-cn/docs/ https://www.zhangkunzhi.com/ https://github.com/ycltpe/blogHexo