2024年8月

VMware vSAN 解决方案中,为了充分利用 vSAN HCI 集群内的存储资源, vSAN HCI 和 vSAN HCI 集群之间可以相互共享存储资源,这种解决方案早期叫 vSAN HCI Mesh,现在被称为具有数据存储共享的 vSAN HCI(
vSAN HCI with datastore sharing
)。VMware vSAN 集群根据主机磁盘的组成方式分为 Original Storage Architecture(OSA)原始存储架构和 Express Storage Architecture(ESA)快速存储架构,根据部署架构所使用的类型分为 vSAN 计算集群(Compute Only)、vSAN HCI 集群(Compute & Storage)以及 vSAN Max 集群(Storage Only)。

VMware Cloud Foundation 解决方案中可以添加不同 vSAN 类型的主机并创建用于不同用途的 vSAN 集群类型,并且在 SDDC Manager 中可以直接管理并挂载远程 vSAN 数据存储。VMware Cloud Foundation 5.2 版本开始增加对 vSAN Max 分解存储(Disaggregated Storage)类型的支持,你在增加 VI 工作负载域或者创建新集群的时候可以将 vSAN Max 集群的存储作为主体存储(Principal Storage)进行使用,但是,当前 VCF 还不支持 vSAN Max 延伸集群架构。有关更多关于 vSAN Max 分解存储的内容和细节请查看这篇(
创建vSAN Max集群并配置挂载远程数据存储。
)文章。

使用挂载远程 vSAN 数据存储功能具有许多要求和注意事项,挂载端集群被称为客户端(Client)集群,被挂载端集群被称为服务器端(Server)集群,客户端集群和服务器端集群之间挂载和被挂载具有一定的数量限制,客户端集群和服务器端集群之间共享存储,对于两者之间部署架构的类型也有限制,vSAN 计算集群可以挂载 vSAN HCI OSA/ESA 集群和 vSAN Max 集群,vSAN HCI OSA 集群只能挂载 vSAN HCI OSA 集群,vSAN HCI ESA 集群只能挂载 vSAN HCI ESA 集群和 vSAN Max 集群等。下面来看看具体的配置过程。

一、vSAN 计算集群

vSAN 计算集群其实就是标准的 vSphere 集群,本身不存在本地/共享存储,只提供计算资源。通过配置为 vSAN 计算集群,会在集群的主机之上安装一个精简的 vSAN,用于作为客户端集群,然后挂载远程服务器端集群(vSAN HCI 集群/vSAN Max 集群)上的存储资源后,提供给本集群中的工作负载进行使用。

导航到 SDDC Manager->清单->主机,点击“服役主机”添加用于 vSAN 计算集群的 ESXi 主机。选择“vSAN”存储类型并选择 vSAN 类型为“vSAN 计算集群”,其他选项可根据情况自行进行调整,然后完成服役主机添加工作流。

由于是 vSAN 集群,因此你还是需要至少准备 3 台主机以用于 vSAN 计算集群,使用上述同样的方式完成其他主机添加即可,主机服役后会显示在未分配的主机列表当中,如下图所示。

导航到 SDDC Manager->清单->工作负载域,在管理域左边三个点处点击“添加集群”。

存储类型选择“vSAN”,点击开始。

设置 vSAN 计算集群的名称(vcf-mgmt01-cluster02),点击下一步。

选择 vSAN 集群类型为“vSAN 计算集群”,点击下一步。

选择当前可挂载的远程 vSAN 数据存储,管理域默认集群是 vSAN HCI,所以可供 vSAN 计算集群挂载使用,点击下一步。

选择用于 vSAN 计算集群的 ESXi 主机,点击下一步。

配置 vSAN 计算集群主机的虚拟交换机,选择创建自定义交换机配置。

配置过程就忽略了,请注意主机配置用于 vSAN 网络流量的交换机所分配的 vSAN VMkernel 网卡需要与挂载远程的 vSAN 集群的 vSAN VMkernel 网卡互通,后面也是一样。

配置用于 vSAN 计算集群的许可证,这个地方需要选择 VMware vSAN 许可证,其实 vSAN 计算集群是不需要 vSAN 许可证的,但是这里要选择,点击下一步。

检查配置,点击完成。

下图可以看到,只用到 VMware vSphere 许可证。

如果一切顺利,导航到 SDDC Manager->清单->工作负载域->集群,可以看到 vSAN 计算集群已经创建成功,在 vSAN 配置处显示了配置挂载远程 vSAN 数据存储的集群状态。

点击进入该集群,能够看到 vSAN 计算集群挂载 vSAN HCI 集群存储的拓扑。

在服务器端集群中,也能看到挂载的客户端集群拓扑。

在 vCenter Server(vSphere Client)中查看 vSAN 计算集群的状态。

查看 vSAN 计算集群挂载的远程 vSAN 数据存储。

二、vSAN HCI 集群

vSAN HCI 集群就是标准的 vSAN 超融合集群,通过将主机的本地硬盘进行聚合后,最终形成一个统一的存储池供工作负载使用。VCF 管理域集群就是一个标准的 vSAN HCI 集群,关于 vSAN HCI 集群的详细创建过程这里就不再赘述了,有需要可以查看之前这篇(
VMware Cloud Foundation Part 07:管理工作负载域中的主机和集群。
)文章,下面只陈述创建 vSAN HCI 集群需要注意的地方,以及 vSAN HCI 集群之间远程挂载数据存储的过程。

添加用于 vSAN HCI 集群的服役主机时,主机的 vSAN 类型选择“vSAN HCI”,根据挂载远程数据存储要求选择 vSAN OSA/ESA 架构。

由于 VCF 管理域初始集群是 vSAN ESA 架构,所以需要添加 3 台用于 vSAN HCI ESA 集群的 ESXi 主机。

添加 vSAN 集群时需要选择 vSAN ESA 架构并选择 vSAN 集群类型为“vSAN HCI”。

最终,vSAN HCI 集群(vcf-mgmt01-cluster03)创建成功,如下图所示。

点击该集群左边三个点处,选择“挂载远程数据存储”。

可选择的远程 vSAN 数据存储,勾选后,点击下一步。

新创建的 vSAN HCI 集群当前没有远程 vSAN 容量,如果执行本次挂载远程数据存储后,新的远程 vSAN 容量如下图所示。

远程 vSAN 数据存储挂载进行中......

已成功挂载远程 vSAN 数据存储。

点击该集群,查看挂载情况。

服务器端集群查看挂载情况,现在有两个客户端集群挂载了自己。

其实,对于 vSAN HCI 集群来说,支持互相挂载远程 vSAN 数据存储,在 VCF 管理域集群上点击“挂载远程数据存储”。

可以选择的远程 vSAN 数据存储。

如果挂载了此远程 vSAN 数据存储,可以增加的远程 vSAN 容量。

挂载成功后,查看 vSAN 配置。

点击进入集群,查看挂载情况。

在 vCenter Server(vSphere Client)查看 vSAN HCI 集群的状态。

查看 vSAN HCI 集群挂载的远程 vSAN 数据存储。

三、vSAN Max 集群

vSAN Max 是基于 vSAN ESA 的全新分解存储架构,通过充分利用 vSAN ESA 架构的各种优势,并单独针对存储数据的处理任务进行各种优化,专门用来向 vSAN 计算集群和 vSAN HCI 集群提供远程数据存储。有关更多内容和细节请查看这篇(
创建vSAN Max集群并配置挂载远程数据存储。
)文章。

导航到 SDDC Manager->清单->主机,点击“服役主机”添加用于 vSAN Max 集群的 ESXi 主机。选择“vSAN”存储类型并选择 vSAN 类型为“vSAN Max”,其他选项可根据情况自行进行调整,然后完成服役主机添加工作流。

使用上述同样的方式添加 3 台主机以用于 vSAN Max 集群,主机服役后会显示在未分配的主机列表当中,如下图所示。

导航到 SDDC Manager->清单->工作负载域,在管理域左边三个点处点击“添加集群”。

存储类型选择“vSAN”并勾选“启用 vSAN ESA”,点击开始。

设置 vSAN Max 集群的名称(vcf-mgmt01-cluster04),点击下一步。

选择 vSAN 集群类型为“vSAN Max”,点击下一步。

选择用于 vSAN Max 集群的 ESXi 主机,点击下一步。

配置 vSAN Max 集群主机的虚拟交换机,选择创建自定义交换机配置,过程同样也忽略了,点击下一步。

配置用于 vSAN Max 集群的许可证,点击下一步。

检查配置,点击完成。

如果一切顺利,vSAN Max 集群创建成功。

先在 vSAN 计算集群上挂载远程 vSAN Max 集群的数据存储。

选择 vSAN Max 集群的数据存储,下面的 vSAN HCI 集群的数据存储已经挂载了所以是灰色的,点击下一步。

因为已经挂载了 vSAN HCI 的数据存储,所以当前的远程 vSAN 容量有 3 TB,如果执行了此挂载任务,则新的远程 vSAN 容量可以达到 4 TB,如下图所示,点击完成。

挂载成功后,vSAN Max 集群的 vSAN 配置状态已变成服务器端。

点击 vSAN 计算集群查看挂载情况。

点击 vSAN Max 集群查看挂载情况。

同样,vSAN Max 集群也可以被 vSAN HCI 集群进行挂载使用。

点击 vSAN HCI 集群查看挂载情况。

请注意,vSAN Max 集群只能充当服务器端,不能充当客户端,也就是说只能被其他类型的集群挂载使用,不能去挂载别的远程 vSAN 数据存储。同时,挂载了远程 vSAN 数据存储的集群不能被删除,只有当远程数据存储被卸载了以后才能进行删除。

在 vCenter Server(vSphere Client)查看 vSAN Max 集群的状态。

查看 vSAN Max 集群所挂载的 vSAN 客户端集群。

如果你看过这篇(
创建vSAN Max集群并配置挂载远程数据存储。
)文章,那应该知道挂载远程 vSAN 数据存储是支持跨 vCenter Server 实例共享的,这对于 VMware Cloud Foundation 解决方案来说,就是跨工作负载域共享,但是目前说是只支持在同一工作负载域中的不同集群之间远程共享数据存储,我看了一下,这在 SDDC Manager 中好像确实不能,但是从技术上讲,在工作负载域的 vCenter Server(vSphere Client)中配置跨 vCenter Server 挂载远程 vSAN 数据存储应该是可行的,这仅限于 VI 工作负载域,因为管理工作负载域只有一个。当然,VMware 没有表明那肯定不受官方支持,所以还是严格按照文档指引来使用吧!

在当今数字化高速发展的时代,B 端产品经理作为企业数字化转型的关键推动者,肩负着重大的责任。不仅要深入了解企业的业务需求,还要紧跟技术发展的步伐,为企业提供高效、创新的解决方案。那么,未来几年,B 端产品领域将会呈现出哪些发展趋势呢?

B 端产品未来几年的发展趋势

一、人工智能与机器学习的深度融合

人工智能(AI)和机器学习(ML)已经在 B 端产品中崭露头角,未来几年,它们的应用将更加广泛和深入。

  • 智能客服与自动化服务

智能客服系统将不断升级,能够更准确地理解客户问题,并提供个性化的解决方案。通过机器学习算法,智能客服可以不断学习和改进,提高回答问题的准确率和效率。同时,自动化服务也将在更多的业务场景中得到应用,例如自动化订单处理、自动化库存管理等,大大提高企业的运营效率。

  • 数据分析与预测

AI 和 ML 技术将在数据分析领域发挥更大的作用。可以利用这些技术对大量的业务数据进行分析,挖掘出有价值的信息,为企业决策提供支持。例如,通过预测分析,企业可以提前预测市场需求、客户行为等,从而优化生产计划、营销策略等。

  • 智能推荐与个性化服务

基于用户行为和偏好的智能推荐系统将成为 B 端产品的重要组成部分。通过机器学习算法,产品可以为用户提供个性化的服务和推荐,提高用户体验和满意度。例如,在企业资源规划(ERP)系统中,根据用户的历史操作和偏好,为用户推荐相关的业务流程和功能。

二、云计算与容器化技术的持续发展

云计算和容器化技术已经成为企业数字化转型的重要支撑,未来几年,它们将继续发挥重要作用。

  • 多云战略与混合云部署

随着企业对云计算的需求不断增加,多云战略将成为越来越多企业的选择。考虑如何支持企业的多云战略,实现不同云平台之间的无缝集成和管理。同时,混合云部署也将越来越普遍,企业可以根据自身的业务需求和安全要求,灵活地选择公有云、私有云和本地部署的组合。

  • 容器化技术与微服务架构

容器化技术和微服务架构将进一步推动 B 端产品的发展。容器化技术可以提高应用的部署效率和可移植性,微服务架构可以提高系统的可扩展性和灵活性。需要了解这些技术的特点和优势,为企业设计和开发更加高效、灵活的产品。

  • 云原生应用与开发

云原生应用是指基于云计算技术构建的应用,具有高可用、高弹性、易扩展等特点。未来几年,云原生应用将成为 B 端产品的主流发展方向。需要掌握云原生技术,为企业开发出更加符合云时代需求的产品。

三、用户体验与设计的重要性日益凸显

在 B 端产品领域,用户体验和设计的重要性也越来越受到重视。未来几年,产品经理需要更加注重用户体验和设计,为用户提供更加优质的产品和服务。

  • 以用户为中心的设计理念

深入了解用户的需求和痛点,以用户为中心进行产品设计。通过用户调研、用户测试等方法,不断优化产品的用户体验,提高用户满意度。同时,产品设计也需要更加注重简洁性和易用性,让用户能够快速上手并高效地完成工作。

  • 个性化用户体验

随着用户需求的不断变化,个性化用户体验将成为 B 端产品的重要发展方向。通过用户画像、数据分析等方法,了解用户的个性化需求,为用户提供个性化的产品和服务。例如,在企业管理软件中,根据不同用户的角色和权限,为用户定制个性化的工作界面和功能菜单。

  • 设计思维与创新

设计思维将成为 B 端产品经理必备的技能之一。通过设计思维,产品经理可以更好地理解用户需求,提出创新的解决方案。同时,创新也是 B 端产品发展的关键,产品经理需要不断探索新的技术和业务模式,为企业带来更多的价值。

四、数据安全与隐私保护的挑战与机遇

随着数字化程度的不断提高,数据安全和隐私保护也成为企业面临的重要挑战。未来几年,更加重视数据安全和隐私保护,为企业提供更加安全可靠的产品和服务。

  • 数据安全管理

需要建立完善的数据安全管理体系,包括数据加密、访问控制、数据备份等措施,确保企业数据的安全。同时,产品也需要符合相关的安全标准和法规,如 GDPR、HIPAA 等。

  • 隐私保护技术

隐私保护技术将不断发展,例如差分隐私、同态加密等。了解这些技术的特点和应用场景,为企业提供更加有效的隐私保护解决方案。同时,产品也需要在设计和开发过程中充分考虑用户隐私保护的需求,确保用户数据的安全和隐私。

  • 安全意识培训

数据安全和隐私保护不仅仅是技术问题,也是人的问题。加强用户的安全意识培训,提高用户对数据安全和隐私保护的重视程度。同时,企业也需要建立健全的安全管理制度,加强内部安全管理。

五、行业垂直化与专业化发展

随着市场竞争的加剧,B 端产品将越来越向行业垂直化和专业化方向发展。未来几年,更加深入地了解行业特点和业务需求,为企业提供更加专业的产品和服务。

  • 行业解决方案

针对不同的行业特点,开发出行业专属的解决方案。例如,在医疗行业,开发出符合医疗行业标准和法规的医疗管理软件;在金融行业,开发出安全可靠的金融交易系统等。这些行业解决方案将更加贴近用户需求,提高用户满意度。

  • 专业化功能模块

除了行业解决方案,B 端产品也将越来越注重专业化功能模块的开发。例如,在企业资源规划(ERP)系统中,开发出针对不同行业的财务管理模块、供应链管理模块等。这些专业化功能模块将更加满足用户的特定需求,提高产品的竞争力。

  • 行业合作与生态建设

加强与行业内其他企业的合作,共同打造行业生态。通过合作,企业可以共享资源、优势互补,提高产品的质量和服务水平。同时,行业生态的建设也将促进整个行业的发展,为企业带来更多的机遇。

六、敏捷开发与持续交付的普及

敏捷开发和持续交付已经成为软件开发的主流方法,未来几年,它们将在 B 端产品开发中得到更加广泛的应用。

  • 敏捷开发方法

敏捷开发方法强调快速迭代、用户参与和团队协作。采用敏捷开发方法,提高产品开发的效率和质量。同时,产品经理也需要与开发团队、测试团队等密切合作,确保产品能够按时交付。

  • 持续交付与部署

持续交付和部署是指将产品的开发、测试和部署过程自动化,实现快速交付和部署。建立完善的持续交付和部署体系,提高产品的交付速度和稳定性。同时,产品也需要支持自动化测试和部署,确保产品的质量和安全性。

  • 敏捷项目管理

敏捷项目管理强调项目的灵活性和适应性。采用敏捷项目管理方法,对项目进行有效的管理和控制。同时,产品经理也需要与项目团队成员密切合作,及时解决项目中出现的问题,确保项目能够按时完成。

七、总结

未来几年,B 端产品领域将面临着诸多挑战和机遇。人工智能与机器学习的深度融合、云计算与容器化技术的持续发展、用户体验与设计的重要性日益凸显、数据安全与隐私保护的挑战与机遇、行业垂直化与专业化发展以及敏捷开发与持续交付的普及等趋势,将对 B 端产品经理提出更高的要求。作为 B 端产品经理,我们需要不断学习和掌握新的技术和方法,深入了解用户需求和行业特点,为企业提供更加高效、创新、安全可靠的产品和服务。只有这样,我们才能在激烈的市场竞争中立于不败之地,为企业的数字化转型和发展做出更大的贡献。

引言

在三年前,写智能小车的时候,当时小车上有一个摄像头需要采集,实现推拉流的操作,技术选型当时第一版用的是nginx的rtmp的推拉流,服务器的配置环境是centos,2H4G3M的一个配置,nginx的rtmp的延迟是20秒,超慢,后来研究了SRS以及ZLMediaKit这两个开源的推拉流服务器,没记错的话,两个都是基于c++开发的,性能都很棒,后来更换了推拉流服务器,小汽车的延迟在一秒不到,性能大幅度提升,当时研究了一下,然后没有记录,这次使用SRS实现了音视频通话,以及共享桌面的功能,特此记录以及分享给大家。

技术概览


本demo总共涉及到三个服务,部署环境是腾讯云的轻量服务器,配置是2H2G3M的服务器,CENTOS系统,nginx部署前端,docker部署后端以及SRS服务。

SRS

SRS是一个开源的(MIT协议)简单高效的实时视频服务器,支持RTMP、WebRTC、HLS、HTTP-FLV、SRT、MPEG-DASH和GB28181等协议。 SRS媒体服务器和FFmpeg、OBS、VLC、 WebRTC等客户端配合使用,提供流的接收和分发的能力,是一个典型的发布 (推流)和订阅(播放)服务器模型。 SRS支持互联网广泛应用的音视频协议转换,比如可以将RTMP或SRT, 转成HLS或HTTP-FLV或WebRTC等协议。

后端

后端是一个基于
net8.0基础框架开发的一个webapi的接口,

前后端通讯使用的是
signalr,用来实现不同用户之间的一个消息更改通知,本项目没有涉及到任何数据库方面的。

前端


前端是基于
node20.16.0,vue3。

其中,推拉流的地址和后端服务器的地址配置在
configjs.json中配置,pushUrl是推流的地址,pullUrl是拉流的地址,apiUrl是后端接口的地址,signalrUrl是用来做前后端websocket通讯的一个地址。在apiUrl和signalrUrl中的端口需要和上方的后端运行的端口保持一致才可以互相访问通讯,

具体配置文档查看下方图例

功能概览

总体功能分为一下几个:

设备检测/参数设置

这个页码主要是用来配置摄像头,并且检测摄像头是否可用,音频检测音频是否可用,并且配置音频设备,后续的音视频通话都是根据此处选择的设备进行推拉流,用户名称,由于本项目是一个demo,所以都是基于内存,用户是自己设置之后,在demo中与人通讯的一个标识;在这个页面配置好视频设备,音频设备,以及用户名称,就可以去后续的页面进行群聊或者单聊,或者桌面共享的功能。

群聊

群聊进入到页面,就可以看到已经存在的群聊信息,以及在线人数,可以进行加入或者删除群聊的操作,如果有新增的群组,此处也会使用Signalr进行同步更新获取最新的群组列表数据,此demo没有判断删除的时候权限问题以及如果有人正在群聊删除群组的问题,在设备检测页面没有选择音视频设备,也可以进入群组,可以查看有音视频的在线人员的一个音视频,如图所示,在上方输入要创建的群组名称,点击添加群组即可到如下页面,进入视频页面,会先去推流到服务器,以便下一个进入的人可以看到你的视频流,同时如果没有选择音视频设备,点击加入也是如下页面,并且该页面不会展示群组的在线人,可以从视频的摄像头上方可以查看是哪个用户的音视频。

单聊

单聊就是只有两个人进行音视频通话,同时也支持没有选择设备可以进行通话,没有添加文字聊天的支持,单聊列表,也会使用signalr进行同步更新,在用户设置了用户名称之后,在这里就可以看到列表数据的更新。点击通话就可以和在线的人员进行音视频通话,同时不能和自己通话,且选择的人如果在处于单聊状态中,也无法进行音视频通话,在选择了要进行通话的用户后,会进入到聊天页面,同时对方用户会收到一个提醒,是否接受音视频通话,可以拒绝,也可以接受,拒绝之后,请求方会退出到在线列表的页面,点击接受会进入到双方的一个音视频通话的页面,可以进行语音聊天,可以看对方的摄像头推送的视频流。同时接受之后,任意一方离开聊天,另外一方也会直接退出聊天页面。返回到用户在线列表页面中。

共享桌面

共享桌面的操作和群组的一样,在上方输入共享桌面的名称,点击按钮,即可进入到共享桌面的页面中去。进入到页面,会提示需要共享的屏幕内容,可选整个屏幕,浏览器或者窗口都可以,同时也可以选择是否要共享此页面的音频,点击分享之后,即可看到共享的视频内容,右侧显示了参与人列表,并且如果选择了音频设备,也会采集语音推送,多个参与人进行语音聊天,语音会显示谁在发言,收到了谁的语音流。同时当共享的人,点击了停止共享,其他参与人也可以共享自己的桌面,点击了共享桌面按钮,其他参与人的共享桌面按钮会隐藏,并且他们会看到采集的你的屏幕的视频信息。

程序配置

关于配置方面,主要是前端的配置以及SRS的配置,前端方面的配置,在刚开始已经阐述过,主要是SRS的推拉流的配置,以及API和Signalr的地址配置,如果服务器是外网, 地址必须是外网服务器的地址,关于SRS的配置,在下载好SRS之后,SRS提供了默认的配置文件夹,文件夹名字是叫conf文件夹,里面提供了各种不同功能的conf配置文件,此处我们基于console.conf进行改造,下面的是console.conf的配置信息,第一行是listen,默认是1935,代表SRS启动的时候的RMP的直播服务端口。max_connection代表最大连接数量,默认是1000,srs_log_tank是日志的打印方式,默认是console,即控制台,可选配置有file和console,file是文件的输出形式,如果是file的形式,必须通过配置srs_log_file参数配置日志的打印文件的路径,默认是.objs/srs.log的文件。daemon,代表的是是否以后台的形式运行,on代表开启,off代表关闭。http_api,SRS提供了一些api,这个配置代表是否开启http_api,并且端口是8080。下方,展示了SRS官网提供的API导航。rtc_server启用webrtc的功能,端口是udp的8000,默认是8000,其中最后一个配置是candidata,如果是本机部署,这个可以不需要配置,如果是需要部署在外网服务器,那这个就需要设置成外网的服务器地址。

SRS的视频推拉流,有虚拟主机的概念,默认提供了一个defaultVhost的虚拟主机在配置文件里,虚拟主机内有单独的关于主机的配置,hls代表开启hls的视频协议功能,http_remux,是否为http开启直播流服务,mout代表的是挂载的http流,可以是不同的格式,默认是flv,可选有ts,即后缀是.ts,有mp3,aac等协议。rtc代表是否给虚拟主机开启webrtc的功能,并且是否开启rtmp转rtc,以及rtc转rtmp的功能。http_hooks是SRS在有客户端推流或者拉流的时候配置的一个接口回调,这个回调可以是我们自己写的后端服务,这里的配置是我配置的我实际的后端服务的接口地址,可以根据自己的实际情况进行调整,enable代表是开启HOOK,publish是推流的回调,unpublish是停止推流的时候,play和stop是拉流的播放和停止回调。play是针对拉流的配置,gop_cache是否缓存最后一帧,如果开启,客户端能够快速播放,如果关闭,客户端拉取的一直都是最新的,queue_length是缓存的帧一秒缓存的队列长度,如果超过这个,会移除之前的帧,mw_latency,关于流的合并写入的延迟,毫秒级单位。Publish是推流的一个配置,mr是合并读取的延迟,毫米级单位。

关于上面说了那么多的配置,主要的配置还是http_hooks的配置,这个配置,是SRS在接收到推流请求,或者停止推流,以及拉流,停止拉流的时候对我们后端服务的一个回调,enabled代表是否开启回调,publish是开始推流的回调,unpublish是停止推流,play和stop是客户端在播放流或者停止流的时候的一个回调,这里如果部署在外网,且srs和后端服务在一个服务器,此处的地址可以使用局域网的地址,与前端配置不同的是,前端的配置必须是外网的地址。

以上关于所有的全面配置可以参考以下网址:

http_api:
http://ossrs.net/lts/zh-cn/docs/v6/doc/http-api

http_server:
http://ossrs.net/lts/zh-cn/docs/v6/doc/http-server

rtc_server/rtc:
http://ossrs.net/lts/zh-cn/docs/v6/doc/webrtc

hls:
http://ossrs.net/lts/zh-cn/docs/v6/doc/hls

部署

上面说到,我们的发布环境是centos,nginx和docker,所以在安装好了nginx之后 需要对nginx进行一个端口反向代理的配置,这里我用的是443端口,在网上生成了一个ssl证书,因为如果是使用http开头的网址,浏览器的机制,会不让使用摄像头,需要更改浏览器的配置才可以使得http的网址可以访问摄像头,如果是在本地部署和调试此服务,建议使用127.0.0.1或者localhost等方式来获取摄像头的信息,因为浏览器的安全机制,非https并且url地址是IP非127.0.0.1或者localhost的方式获取摄像头是有限制,接触限制的方式是在浏览器地址输入chrome://flags,回车之后,在弹出的页面中搜索Insecure origins treated as secure,如图,回车之后,需要将服务的IP地址输入在下方输入框中,并且将disabled更改为enabled,在更改完成后,浏览器下方会出现图3的面板,点击Relauch重启浏览器即可通过IP地址访问服务,并且加载摄像头,如果是中文disable是禁用,enable是启用,Relauch是重启。

所以基于上面http的问题,需要生成一个ssl证书,让web使用https进行访问。下面我放一份我的nginx的配置,在下面的443的配置中,指定了servicename,以及root指向的是我们发布的之后的web前端的地址。指定了index.html,以及ssl证书相关的配置地址,配置根路径访问的是web前端的index.html,然后将路由中包括api,pull,push的指向对应的端口,如上图的端口配置情况,1985,使用webrtc进行推流,8080,进行拉流的端口,video是signalr的反向代理地址。

以上是我服务器自己部署的nginx的一个配置。

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /video/dist/;
        index index.html;
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
        location / {
            try_files $uri $uri/ /index.html;
        }
        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
    server {
        listen      443 ssl;
        listen       [::]:443;
        server_name  49.233.22.57;
        root         /video/dist/;
        index index.html;
        ssl_certificate /sslfile/49.233.22.57.crt; # ssl证书存储路径
        ssl_certificate_key /sslfile/49.233.22.57.private; # 秘钥存储路径

        # ssl的一些配置
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_prefer_server_ciphers  on;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #开启TLS协议

        location / {
            try_files $uri $uri/ /index.html;
        }
        location /api {
            proxy_pass http://10.2.20.12:5000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
        }
        location /rtc {
            proxy_pass http://10.2.20.12:1985;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
        }
        location /pull {
            rewrite ^/pull/(.*)$ /$1 break;
            proxy_pass http://10.2.20.12:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
        }
        location /video {
            proxy_pass http://10.2.20.12:5000;
            proxy_set_header Host $host;
            proxy_set_header Upgrade $http_upgrade;
            proxy_cache_bypass $http_upgrade != '';
            proxy_set_header Connection $connection_upgrade;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
        }
	}

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

后端部署在docker中, 环境是net8的开发环境,dockerfile配置如下,将发布后的文件和dockerfile放在一起,执行docker build -t videoimg .指令,打包docker镜像。记得后面有一个点.,回车之后,生成了videoimg的docker镜像,生成镜像后,需要启动容器,docker run --name videoc --security-opt seccomp=unconfined  -d -p 5000:8080 videoimg 回车之后即可启动了后端服务的容器,本机的端口是5000,需要防火墙或者云服务器开启5000端口,

#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:8.0AS baseWORKDIR/appEXPOSE 8080
EXPOSE 8081
COPY. .FROMbase AS finalWORKDIR/appENTRYPOINT ["dotnet", "WebApplication1.dll"]

docker启动SRS,如果SRS部署在外网服务器,需要在启动SRS容器之前,配置一个环境变量CANDIDATE="外网服务器IP地址",将外网的IP地址写入环境变量中,SRS启动会从中读取配置,也可以直接修改conf中关于CANDIDATE的配置直接更改为你的外网服务器的地址。配置好之后,启动SRS,docker run --rm  --name srs  -it -d -p 1935:1935 -p 1985:1985 -p 8080:8080 -p 1990:1990 -p 8088:8088 -p 8000:8000/udp -v /video/conf:/conf --env CANDIDATE=$CANDIDATE     registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 ./objs/srs -c /conf/console.conf  上面的指令,-v是将容器内部的conf文件夹挂载出来,然后在后面指定使用了console.conf作为启动的配置文件,并且将端口信息暴露出来,推拉流,以及web服务器需要使用这些端口。

SRS提供了一个web管理系统,防火墙等配置好之后,在浏览器输入IP:8080即可打开如下页面,在控制台可以看到视频的推拉流信息,以及流量的流入和流出。

端口配置

服务器需要开启一下端口

1:后端服务的端口,例如本例子的5000端口

2:SRS相关端口:1935,1985,8080,1990,8088,8000/udp

代码和详细Windows文档地址

关于更多的详细解读,可以查看写好的windows的文档部署地址,除了部署方式的差异,其余都一样。

git地址:
https://gitee.com/cxd199645/audio-video.git

总结

关于做一个音视频通话的技术分享就到这里了,如果又不懂的,可以添加QQ/WX:934550201.

1.
SRS

SRS是一个开源的(
MIT协议
)简单高效的实时视频服务器,支持
RTMP、WebRTC、HLS、HTTP-FLV、SRT、MPEG-DASH和GB28181等协议。 SRS媒体服务器和

FFmpeg

OBS

VLC


WebRTC
等客户端配合使用,提供
流的接收和分发
的能力,是一个典型的发布
(推流)和订阅(播放)服务器模型。
SRS支持互联网广泛应用的音视频协议转换,比如可以将

RTMP

SRT

转成
HLS

HTTP-FLV

WebRTC
等协议。

开心一刻

今天小学女同学给我发消息
她:你现在是毕业了吗
我:嗯,今年刚毕业
她给我发了一张照片,怀里抱着一只大橘猫
她:我的眯眯长这么大了,好看吗
我:你把猫挪开点,它挡住了,我看不到
她:你是 sb 吗,滚
我解释道:你说的是猫呀
可消息刚发出,就出现了红色感叹号,并提示:消息已发出,但被对方拒收了

你也没说猫叫眯眯呀

kafka搭建

出于简单考虑,基于
docker
搭建一个
kafka
节点;因为一些原因,国内的 Docker Hub 镜像加速器都不可用了,目前比较靠谱的做法是搭建个人镜像仓库,可参考:
Docker无法拉取镜像解决办法
,我已经试过了,是可行的,但还是想补充几点

  1. sync-image-example.yml
    只需要修改最后的镜像拷贝,其他内容不需要改


    sync-image-example_改动点

    支持一次配置多个镜像的拷贝

  2. 镜像拷贝

    docker 镜像拷贝命令的格式


    skopeo copy docker://docker.io/命名空间/镜像名:TAG docker://阿里云镜像地址/命名空间/镜像名:TAG


    我们以 kafka 为例,去 Docker Hub 一搜,好家伙,搜出来上万个


    上万个kafka镜像

    我们将搜索条件精确化一些,搜
    wurstmeister/kafka


    wurstmeister_kafka

    点进去,它在 Docker Hub 的地址是:


    https://hub.docker.com/r/wurstmeister/kafka


    那它的 docker 地址就是


    docker://docker.io/wurstmeister/kafka


    其他的镜像用类似的方式去找,所以最终的拷贝命令类似如下:


    skopeo copy docker://docker.io/wurstmeister/kafka:latest docker://registry.cn-hangzhou.aliyuncs.com/qingshilu/wurstmeister_kafka:latest


    如果一切顺利,那么在我们的阿里云个人镜像仓库就能看到我们拷贝的镜像了


    阿里云个人镜像
  3. 如何 pull

    在个人仓库点镜像名,会看到
    操作指南


    如何pull

    我们只关注前两步,就可以将镜像 pull 下来


    镜像过滤_wurstmeister

镜像获取到之后,就可以搭建
kafka
了;因为依赖
zookeeper
,我们先启动它

docker run -d --name zookeeper-test -p 2181:2181 \
--env ZOO_MY_ID=1 \
-v zookeeper_vol:/data \
-v zookeeper_vol:/datalog \
-v zookeeper_vol:/logs \
registry.cn-hangzhou.aliyuncs.com/qingshilu/wurstmeister_zookeeper

然后启动
kafka

docker run -d --name kafka-test -p 9092:9092 \
--env KAFKA_ZOOKEEPER_CONNECT=192.168.2.118:2181 \
--env KAFKA_ADVERTISED_HOST_NAME=192.168.2.118 \
--env KAFKA_ADVERTISED_PORT=9092  \
--env KAFKA_LOG_DIRS=/kafka/logs \
-v kafka_vol:/kafka  \
registry.cn-hangzhou.aliyuncs.com/qingshilu/wurstmeister_kafka

不出意外的话,都启动成功

kafka启动成功

如果出意外了,大家也别慌,用
docker log
去查看日志,然后找对应的解决方案

# 1.先找到启动失败的容器id
docker ps -a
# 2.用 docker log 查看容器启动日志
docker log 容器id

如果需要开启
kafka

SASL
认证,可参考:
Docker-Compose搭建带SASL用户密码验证的Kafka
来搭建

Kafka Tool

详情可查看:
kafka可视化客户端工具(Kafka Tool)的基本使用

kafka_tool连接成功

创建 Topic:
test-topic
,并发送一条消息

创建test_topic并发送一条消息

此时
test-topic
中有 1 条消息

消费者 poll

代码很简单

/**
 * @author: 青石路
 */
public class MsgConsumer {

    private static final Logger LOGGER = LoggerFactory.getLogger(MsgConsumer.class);

    public static void main(String[] args) {
        Properties props = new Properties();
        props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.2.118:9092");
        props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, "test_group");
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
        // 如果在kafka中找不到当前消费者的偏移量,则设置为最旧的
        props.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 500);
        KafkaConsumer<String, String> consumer = new KafkaConsumer<String,String>(props);
        // 订阅主题
        consumer.subscribe(Collections.singleton("test-topic"));
        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
        LOGGER.info("records count = {}", records.count());
        records.forEach(record -> LOGGER.info("{} - {} - {}", record.offset(), record.key(), record.value()));
        // consumer.commitAsync();
        consumer.close();
    }
}

我们执行下,输出日志如下

poll没拉取到消息_日志

竟然 poll 不到消息,为什么呀?

思考考

我们调整下代码,循环 poll

while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
    LOGGER.info("records count = {}", records.count());
    records.forEach(record -> LOGGER.info("{} - {} - {}", record.offset(), record.key(), record.value()));
}

我们再执行下,输出日志如下

while循环后日志

消费者 poll 的过程中会先判断当前消费者是否在
消费者组
中,如果不在,会先加入消费者组,在加入过程中,
ConsumerCoordinator
会对这个消费者组 Rebalance,整个过程中该消费者组内的所有消费者都不能工作,而 poll 又配置了超时时间(
100 毫秒
),如果在超时时间内,当前消费者还未正常加入消费者组中,那么 poll 肯定是拉取不到数据的;根据日志可以看出,第 3 次 poll 的时候,消费者已经正常加入消费者组中,那么就能 poll 到数据了

很多小伙伴可能可能会有这样的疑问

平时在项目中使用的时候,从来没有感受到这样的问题,为什么呢

原因有以下几点

  1. poll 的超时时间设置比较长,超时时间内消费者能够正常加入到消费者组中
  2. 消费者随项目的启动创建,存活周期与项目一致,那么只有前几次 poll 的时候,可能会因为消费者未加入到消费者组中而拉取不到数据,而一旦消费者成功加入到消费者组之后,那么只要 Topic 中有数据,poll 肯定能拉取到数据;从整个次数占比来看,poll 拉取不到数据的异常情况(Topic 中有可拉取的数据,但 poll 不到)占比非常小,小到可以忽略不计了

所以你们感受不到这样;但如果某些场景下,比如 DataX 从 kafka 读数据

异源数据同步 → DataX 为什么要支持 kafka?

消费者要不断新建,那么 poll 不到数据的异常情况的占比就会上来了,那就需要通过一些机制来降低其所造成的的影响了,比如说重试机制

总结

  1. 示例代码:
    kafka-demo
  2. 如果大家平时用 docker 比较多,推荐通过搭建个人镜像仓库来解决镜像拉取超时的问题
  3. kakfa 消费者 poll 的时候,消费者如果不在消费者组中,会先加入消费者组,那么超时时间内可能 poll 不到数据,可以通过增大超时时间,或者重试机制来降低 poll 不到数据的异常次数(Topic 中没有可拉取的数据而 poll 不到的情况不算异常情况)

兴趣是最好的老师,
HelloGitHub
让你对编程感兴趣!

简介

HelloGitHub
分享 GitHub 上有趣、入门级的开源项目。

github.com/521xueweihan/HelloGitHub

这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 Python、Java、Go、C/C++、Swift...让你在短时间内感受到开源的魅力,对编程产生兴趣!


以下为本期内容|每个月
28
号更新

C 项目

1、
austin
:深入 Python 程序性能分析的工具。这是一款专为 Python 程序设计的性能分析工具,无需修改代码即可轻松定位 Python 程序的性能瓶颈和内存使用情况。它是采用 C 语言编写的 CPython 帧堆栈采样器,具有体积小、运行速度快、零代码侵入等特点,支持 WebUI、TUI、VSCode 等多种可视化方式(需额外安装)。

2、
chsrc
:全平台通用的换源工具。该项目能够为常见的 Linux 发行版、编程语言和软件切换至国内镜像源,操作简单仅需一条命令。它采用 C 语言编写,具有高效和轻量级的特点,支持测速、多平台以及项目级换源等功能,适用于优化下载速度或解决源受限的场景。来自
@ccmywish
的分享

3、
collectd
:灵活的系统信息收集守护进程。这是一个功能强大的收集系统信息的守护进程,能够定期收集和统计系统信息。它支持丰富的数据收集插件,可以监控硬件使用情况、系统性能指标、网络流量等多种数据类型,包括 Apache、MySQL、电池、传感器等。并支持将收集的数据输出到 RRDtool、InfluxDB 等多种数据库和监控系统,适用于嵌入式、物联网和服务器集群监控等场景。

C# 项目

4、
LenovoLegionToolkit
:轻量级的联想拯救者工具箱。该项目是专为联想拯救者系列笔记本设计的开源工具,它具有小巧轻便、占用内存少、不收集用户信息等优点,支持调节电源模式、显卡工作模式、风扇速度和键盘灯效等功能,提供了中文界面,可作为联想 Vantage 软件的开源替代品。

5、
PDFQFZ
:免费的 PDF 加盖骑缝章工具。该项目是用于在 PDF 文件上加盖骑缝章的工具,适用于 Windows 平台。它不仅免费且开源,使用时可以指定目录,对多个 PDF 文件进行批量处理,并支持预览、调整印章大小和位置等功能。

C++ 项目

6、
lnav
:强大的终端日志文件查看工具。这是一款用于查看和分析日志文件的轻量级工具。它无需配置、开箱即用,可自动识别日志格式并解压文件,支持同时处理多个文件和目录、实时更新、文本高亮、正则与 SQL 过滤日志等功能,特别适合在服务器和开发环境中使用。来自
@DeShuiYu
的分享

7、
shadPS4
:开源的 PS4 模拟器。这是用 C++ 编写的 PlayStation 4(PS4)模拟器,支持在 Windows、Linux 和 macOS 系统上玩 PS4 游戏。虽然项目仍处于早期开发阶段,能运行的游戏有限,但最新版已经能够成功运行《血源诅咒》和《黑暗之魂II》等游戏。

Go 项目

8、
doggo
:友好的命令行 DNS 查询工具。该项目是用 Go 语言编写的命令行 DNS 客户端工具,安装简单且开箱即用。它提供了友好的命令行界面,可快速显示 DNS 记录信息,支持高亮显示、响应时间和多种 DNS 记录类型等,适用于网络诊断等场景。

# Simple DNS lookup
doggo example.com

# Query MX records using a specific nameserver
doggo MX github.com @9.9.9.9

# Use DNS over HTTPS
doggo example.com @https://cloudflare-dns.com/dns-query

# JSON output for scripting
doggo example.com --json | jq '.responses[0].answers[].address'

# Reverse DNS lookup
doggo --reverse 8.8.8.8 --short

9、
glasskube
:更容易上手的 K8s 包管理器。这是一款提供直观图形界面和灵活命令行工具的 Kubernetes 软件包管理工具。它操作简单更容易上手,支持自动处理依赖、GitOps 和自动更新等功能,简化了繁琐的手动配置过程。

10、
lancet
:全面的 Go 语言工具函数库。这是一个高效且全面的 Go 语言工具函数库,包含 600 多个函数,涵盖字符串处理、切片操作、网络编程、并发、加解密、文件处理、时间/日期、流处理、迭代器等功能。来自
@两双筷子sqldc
的分享

package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/strutil"
)

func main() {
    s := "hello"
    rs := strutil.Reverse(s)
    fmt.Println(rs) //olleh
}

11、
neko
:多功能的虚拟浏览器工具。该项目是运行在 Docker 容器中的自托管虚拟浏览器环境,为用户提供安全、隔离和功能齐全的虚拟浏览器。此外,它还支持在线共享浏览器和实时互动演示,具备多人访问、管理员用户、文本聊天和双向文件传输等功能。来自
@猎隼丶止戈reNo7
的分享

12、
sftpgo
:集成云存储的 SFTP 服务器。该项目是用 Go 编写的功能齐全、灵活可配置的 SFTP 服务器,支持 SFTP、SCP、FTP/S、WebDAV、HTTP/S 等多种文件传输协议,并兼容本地文件系统、S3、谷歌云存储等多种存储后端。此外,它还提供了 Web 界面,便于轻松创建和管理用户、文件夹、群组等资源。来自
@猎隼丶止戈reNo7
的分享

Java 项目

13、
JPlag
:开源的代码抄袭检测工具。这是一个用于检测源代码相似度的工具,支持 Java、C/C++、Python、JavaScript 等多种编程语言,适用于识别编程作业中的抄袭行为等场景。

14、
MooTool
:跨平台的开发者工具箱。这是一款用 Java 开发的开发者常用工具的桌面应用,支持 Windows、macOS 和 Linux 系统。它为开发者提供了多种实用工具,如文本转换、时间处理、JSON 格式化和正则匹配测试等。来自
@周波
的分享

JavaScript 项目

15、
paint-board
:简洁易用的 Web 端创意画板。这是一款支持移动端的 Web 画板应用,它集成了多种创意画笔和绘画功能,支持形状绘制、橡皮擦、自定义画板等操作,并可以将作品保存为图片。来自
@Leo Song
的分享

16、
PptxGenJS
:创建演示文稿(PPT)的 JavaScript 库。这是一个用于生成 PPT 文件的 JavaScript 库,它上手无门槛、功能强大,支持添加图表、表格、SVG、GIF 等内容,并且生成的文件兼容 PowerPoint 和 Keynote 等应用。来自
@Fenix
的分享

import pptxgen from "pptxgenjs";

// 1. Create a new Presentation
let pres = new pptxgen();

// 2. Add a Slide
let slide = pres.addSlide();

// 3. Add one or more objects (Tables, Shapes, Images, Text and Media) to the Slide
let textboxText = "Hello World from PptxGenJS!";
let textboxOpts = { x: 1, y: 1, color: "363636" };
slide.addText(textboxText, textboxOpts);

// 4. Save the Presentation
pres.writeFile();

17、
Reactive-Resume
:免费开源的简历设计平台。这是一个免费、开源、无广告的在线简历制作平台,内置 12 款专业的简历模板,支持多语言、PDF 导出和 OpenAI 集成等功能。

18、
vue-XiuXianGame
:开源的文字修仙游戏。这是一个基于 Vue.js 开发的修仙模拟器,互动式的文字游戏,适合喜欢放置类和修仙题材游戏的玩家。

19、
xyflow
:强大灵活的流程图引擎。该项目是用于构建基于节点的编辑器和交互式图表,支持 React 和 Svelte 框架。它开箱即用且高度可定制,适用于开发工作流和流程图等场景。来自
@塔咖
的分享

const initialNodes = [
{ id: '1', position: { x: 0, y: 0 }, data: { label: '1' } },
{ id: '2', position: { x: 0, y: 100 }, data: { label: '2' } },
];

const initialEdges = [{ id: 'e1-2', source: '1', target: '2' }];

function Flow() {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), [setEdges]);

return (
  <ReactFlow
    nodes={nodes}
    edges={edges}
    onNodesChange={onNodesChange}
    onEdgesChange={onEdgesChange}
    onConnect={onConnect}
  >
    <MiniMap />
    <Controls />
    <Background />
  </ReactFlow>
);
}

Kotlin 项目

20、
Android-DataBackup
:Android 的数据备份应用。该项目为 Android 7.0 及以上系统,提供了应用数据的备份和恢复功能,解决了换机后应用需要重新登录或下载额外数据包等问题。

21、
BinaryEye
:Android 的条形码扫描应用。这是一款简单易用、无广告的 Android 条形码和二维码扫描器,支持快速识别多种类型的条形码和二维码,并提供二维码/条形码生成功能。

PHP 项目

22、
cachet
:PHP 写的服务运行状态页面。该项目是采用 Laravel+Bootstrap 构建的服务状态监控和管理平台,免费且开源。它不仅可以自动监控服务的正常运行时间,还提供了管理后台支持主动记录和维护事故信息,支持多语言、自托管、移动端适配和邮件通知等功能。

23、
minimalist-web-notepad
:极简的在线记事本应用。该项目是采用 PHP 编写的 Web 记事本工具,核心功能仅通过一个文件实现。它提供了在线编辑、自动保存和分享笔记的功能,用户无需注册和登录即可使用,适合临时记录、快速保存和分享文字的场景。

Python 项目

24、
Box
:高级字典操作的 Python 库。这是一个提升 Python 字典易用性的库,兼容原生字典。它支持点表示法(dict.user.name)轻松访问和设置值,并能自动创建缺失的键,避免出现 KeyError 异常。来自
@Bit0rls1Mc
的分享

from box import Box

hg_box = Box({ "HelloGitHub": { "star": "89k", "fork": "9.5k" } })
hg_box.HelloGitHub.star
# 89k
hg_box.to_json(filename="hg.json")
new_box = Box.from_json(filename="hg.json")
new_box.keys()
# dict_keys(['HelloGitHub'])

25、
Game-Cheats-Manager
:游戏修改器管理工具。这是一款强大的游戏修改器管理工具,支持搜索、下载、启动、导入和更新游戏修改器等功能。

26、
linkding
:极简的浏览器书签管理平台。该项目是基于 Django 构建的浏览器书签管理平台,它提供了简洁易用的 Web 界面和强大的搜索功能,支持标签分类、批量编辑和稍后阅读等功能,并配有 Chrome 和 Firefox 插件,方便用户随时随地保存和访问书签。

27、
mkdocs-material
:快速生成 Material 风格的文档网站。该项目是基于 MkDocs 构建的美观且功能丰富的文档网站生成器,支持 Markdown、搜索、移动端适配、多语言等功能,适用于快速创建技术文档、产品手册和教程等类型的网站。来自
@猎隼丶止戈reNo7
的分享

28、
SeleniumBase
:功能全面的浏览器自动化框架。该项目是基于 Selenium 的 Python 自动化测试框架,集成了爬虫、自动化测试和生成报告等多种功能。它提供了丰富的示例,并且独特的 UC 模式,可以帮助开发者在进行浏览器自动化操作时避免被检测出来。

from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)

class TestSimpleLogin(BaseCase):
    def test_simple_login(self):
        self.open("seleniumbase.io/simple/login")
        self.type("#username", "demo_user")
        self.type("#password", "secret_pass")
        self.click('a:contains("Sign in")')
        self.assert_exact_text("Welcome!", "h1")
        self.assert_element("img#image1")
        self.highlight("#image1")
        self.click_link("Sign out")
        self.assert_text("signed out", "#top_message")

Rust 项目

29、
abstreet
:开源的城市交通模拟器。这是一个用 Rust 编写的城市交通模拟工具,支持模拟多种交通方式,包括私家车、公共交通、步行和自行车。用户可以在软件中模拟不同的交通策略和基础设施调整。

30、
delta
:提升 Git 差异可读性的命令行工具。这是一个用 Rust 写的命令行工具,能够以更清晰、美观的方式展示 Git 的 diff、blame 和 grep 命令。它支持显示行号、语法高亮和更智能的行内差异显示等功能,可无缝集成到 Git 工作流中。

31、
dust
:快速显示硬盘使用情况的命令行工具。这是一个可视化磁盘使用情况的命令行工具,名字源自 du 和 Rust 编程语言组合。它体积小巧、运行速度快,能够以直观的方式展示磁盘空间概览。来自
@DeShuiYu
的分享

32、
mail-server
:安全且易于部署的邮件服务。该项目是用 Rust 编写的邮件服务器,支持 SMTP、IMAP 和 POP3 等常见邮件协议,内置强大的垃圾邮件和钓鱼网站过滤器。来自
@Mauro D.
的分享

Swift 项目

33、
Pearcleaner
:免费的 Mac 应用清理工具。这是一款免费开源的 Mac 应用清理工具,能够彻底卸载应用并清理残留文件。它采用 SwiftUI 开发,提供了简单易用的界面,支持右键卸载、迷你模式和 Homebrew 清理等功能。

其它

34、
deskreen
:能将任何设备变为电脑第二屏幕的工具。该项目利用 WebRTC 技术将电脑屏幕,通过 WiFi 镜像到具有 Web 浏览器的设备屏幕上,实现屏幕共享功能,使其成为电脑的辅助显示器。

35、
Kazumi
:跨平台的追番神器。这是一款采用 Flutter 开发的番剧采集应用,用户可以通过自定义 Xpath 规则,实现采集、追踪、搜索和在线观看动漫,支持字幕、弹幕、时间表、硬件加速和无线投屏等功能,适用于 Android、Windows 和 macOS 等平台。来自
@Micro·J
的分享

36、
open-and-shut
:笔记本盖的新玩法。这是一个通过反复合上和打开笔记本电脑的盖子,输入摩斯电码的工具。

37、
rime-ice
:开箱即用的 RIME 输入法配置。这是一份 RIME 输入法的配置文件,需要配合 RIME 客户端使用。它提供了高质量、长期维护的简体中文词库,并优化了英文输入体验。

38、
vCards
:开源的电子名片文件。该项目收集并整理了常用联系人的号码和头像,优化了手机来电和通讯录信息界面的体验,支持订阅(自动更新)和手动导入 vcf 文件两种使用方式。来自
@Mingo
的分享

39、
Watchy
:开源电子墨水屏智能手表。该项目是采用 ESP32-PICO-D4 和电子墨水屏制作的一款智能手表,支持日历、闹钟、步数、手势检测,以及 WiFi 和蓝牙等功能。

开源书籍

40、
grammar-club
:《语法俱乐部》。这是旋元佑老师写的一本英语语法书籍,旨在帮助读者建立扎实的语法基础,适合各个水平的英语学习者。

机器学习

41、
k8sgpt
:Kubernetes 故障诊断 AI 助手。该项目利用 LLM 自动分析 Kubernetes 集群问题,并给出故障诊断和优化建议。它通过读取集群的状态数据和配置,生成靠谱的诊断报告。

42、
llama_index
:大型语言模型的数据框架。该项目是专为 LLM 应用设计的数据框架,帮助开发者将私有数据与 LLM 轻松结合。它提供了数据连接器,支持从 API、PDF、文档、SQL 等多种数据源构建索引,并简化数据导入和查询操作,让初学者也能用几行代码完成 LLMs 上下文增强。

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("Some question about the data should go here")
print(response)

43、
RAG_Techniques
:检索增强生成(RAG)教程集合。该项目提供了 20 多种先进的 RAG 技术教程,包含实现指南和示例代码,并定期更新。内容涵盖检索查询、上下文增强、融合检索(Fusion Retrieval)、分层索引、上下文压缩、知识图谱整合等多种 RAG 技术。

44、
video2x
:视频和图像无损放大工具。该项目集成了多种超分辨率算法(如 Waifu2x、Anime4K、Real-ESRGAN),能够有效提高视频和图像的分辨率,并提供了图形界面(GUI)、Docker 和命令行界面(CLI)的使用方式。

最后

感谢参与分享开源项目的小伙伴们,欢迎更多的开源爱好者来 HelloGitHub 自荐/推荐开源项目。如果你发现了 GitHub 上有趣的项目,就
点击这里
分享给大家伙吧!

本期有你感兴趣的开源项目吗?如果有的话就留言告诉我吧~如果还没看过瘾,可以
点击阅读
往期内容。

感谢您的阅读,如果觉得本期内容还不错的话
求赞、求分享
❤️