当前位置: 首页 > news >正文

深入解析 iOS 视频录制(三):完整录制流程的实现与整合

深入解析 iOS 视频录制(一):录制管理核心MWRecordingController 类的设计与实现

深入解析iOS视频录制(二):自定义UI的实现​​​​​​​

深入解析 iOS 视频录制(三):完整录制流程的实现与整合

引言

在之前的两篇博客中,我们详细探讨了如何实现 iOS 视频录制功能的核心部分。第一篇博客《深入解析 iOS 视频录制(一):录制管理核心MWRecordingController 类的设计与实现》介绍了如何设计并实现一个录制管理类MWRecordingController,该类负责管理视频录制的核心功能,包括启动会话、设置输入输出、切换摄像头以及控制录制的开始与停止。第二篇《深入解析 iOS 视频录制(二):自定义 UI 的实现》中,我们详细探讨了如何通过自定义 UI 提供更流畅的用户体验,包括录制按钮、预览视图、控制视图等组件的实现与布局。

本篇博客将以这些基础为依托,重点讲解如何在一个 ViewController 中实现完整的视频录制流程。我们将把前两篇博客中的内容整合,展示如何在单一视图控制器中实现从视频预览到录制控制、从开始录制到保存视频文件的全过程。通过这篇博客,你将了解如何将这些不同模块融合成一个完整、可交互的视频录制应用。

希望通过这篇博客,你能深入理解如何实现一个简单而强大的视频录制功能,并为未来的应用开发打下坚实的基础。

准备工作

在开始实现视频录制功能之前,我们需要做好一些必要的准备工作。确保项目配置正确,依赖库安装完毕,以及设备权限已正确设置,才能顺利进行开发和测试。

项目设置与依赖

首先,确保你的 Xcode 项目已经设置好并配置了正确的依赖项。在本项目中,我们主要依赖 AVFoundation 框架来实现视频录制功能。

import AVFoundation

配置 Info.plist 权限请求

iOS 中,应用访问设备的硬件(如摄像头和麦克风)时需要请求响应的权限。为了确保应用能顺利进行示例录制,我们需要在 Info.plist 文件中添加以下权限描述:

<key>NSCameraUsageDescription</key>
<string>需要访问摄像头来进行视频录制</string>
<key>NSMicrophoneUsageDescription</key>
<string>需要访问麦克风来录制音频</string>

这些描述会在应用首次请求权限时,向用户展示权限请求弹窗。确保根据你应用的功能,调整描述内容,提供清晰且易懂的理由,以提升用户体验。

设备要求与测试

为了保证视频录制功能能够顺利运行,请确保测试设备支持摄像头和麦克风,在模拟器中一般无法使用真实摄像头进行录制,因此必须使用真实设备进行开发和调试。

录制完整流程代码实现

在这一部分,我们将会结合代码一步一步实现录制视频的完整流程。

录制管理与UI组件集成

MWRecordingViewController是本次实现的核心视图控制,它将 MWRecordingController 作为录制的核心控制器,并通过自定义的视图组件(如MWRecordingPreview、MWRecordingControlView、MWRecordingNavgationView)构建了一个完成的视频录制界面。

MWRecordingController

录制控制器(MWRecordingController):负责启动会话、开始和停止录制、切换摄像头。

    /// 录制控制器private let recordingController = MWRecordingController()
  public override func viewDidLoad() {super.viewDidLoad()setupRecording()addPreviewView()addNavgationView()addControlView()}private func setupRecording() {recordingController.recordingSource = self.recordingSource// 设置recordingController.setupSession()// 开始会话recordingController.startSession()recordingController.delegate = self}

MWRecordingPreview

预览视图(MWRecordingPreview):负责展示视频录制过程中的实时画面。

    /// 预览视图private let previewView = MWRecordingPreview()

MWRecordingControlView

控制器视图(MWRecordingControlView):提供开始/暂停录制、重新录制、完成录制等按钮。

    /// 底部控制视图private let controlView = MWRecordingControlView()
    // 控制视图private func addControlView() {self.view.addSubview(controlView)controlView.snp.makeConstraints { make inmake.leading.trailing.equalToSuperview()make.height.equalTo(103.0)make.bottom.equalToSuperview().offset(-MW_BOTTOM_SAFE_HEIGHT - 14.0)}// 开始/暂停 录制controlView.recordButtonClickBlock = { [weak self] inguard let self = self else { return }....}// 重新录制controlView.reRecordButtonClickBlock = { [weak self] inguard let self = self else { return }.....}// 完成controlView.finishButtonClickBlock = { [weak self] inguard let self = self else { return }...}}

MWRecordingNavgationView

导航栏(MWRecordingNavgationView):提供切换摄像头和返回的按钮。

  /// 导航栏private let navgationView = MWRecordingNavgationView()
   // 导航private func addNavgationView() {self.view.addSubview(navgationView)navgationView.snp.makeConstraints { make inmake.top.equalToSuperview().offset(MW_TOP_SAFE_HEIGHT)make.leading.trailing.equalToSuperview()make.height.equalTo(56.0)}// 返回navgationView.backButtonClickBlock = { [weak self] inguard let self = self else { return }self.exit()}// 切换摄像头navgationView.switchCameraButtonClickBlock = { [weak self] inguard let self = self else { return }self.recordingController.switchCamera()}}

实现录制的核心逻辑

在这一部分将会重点讲解如何在MWRecordingViewController中实现视频录制的核心功能,就是UI组件与用操作的交互,以及UI组件与录制核心类MWRecordingController的交互。

在创建MWRecordingController时,我们已经设置并启动了会话,那么第一步我们来实现控制视图的开始/暂停录制的功能,在MWRecordingControlView中我们创建了多个闭包。

录制/暂停

其中recordButtonClickBlock负责回调中间录制/暂停按钮的事件。

        // 开始/暂停 录制controlView.recordButtonClickBlock = { [weak self] inguard let self = self else { return }if self.recordingState == .normal {// 正常状态 开始录制self.recordingState = .recordingself.recordingController.startRecording()} else if self.recordingState == .recording {// 录制状态 暂停self.recordingState = .finishself.recordingController.stopRecording()} else if self.recordingState == .finish {// 完成状态 重新录制self.recordingState = .recordingself.recordingController.startRecording()}if self.recordingState == .recording {self.currentDuration = 0self.startTimer()} else {self.stopTimer()}// 隐藏/显示 切换按钮self.navgationView.isHiddenSwitchCameraButton = self.recordingState != .normalself.controlView.setRecordingState(state: self.recordingState)}

该按钮的点击事件会根据当前的状态来执行不同的操作。

  1. normal:当状态为normal,调用MWRecordingController的开始录制startRecording()方法,并修改状态为recording。
  2. recording:当状态为recording,调用MWRecordingController的结束录制stopRecording()方法,并修改状态为finish。
  3. finish:当状态为finish时,直接重新录制,调用开始录制方法。
  4. 切换状态后,如果状态为recording,重新开启定时器,定时读取录制时长,否则停止定时器。
  5. 根据切换后的状态,更新MWRecordingControlView以及MWRecordingNavgationView视图的状态。

重新录制

点击重新录制按钮,直接切换状态为录制状态,并执行开始录制,启动定时器开始读取录制时长。

        // 重新录制controlView.reRecordButtonClickBlock = { [weak self] inguard let self = self else { return }self.stopPlay()self.recordingState = .recordingself.controlView.setRecordingState(state: self.recordingState)self.recordingController.startRecording()self.startTimer()}

完成事件

点击完成事件,首先判断录制时长是否符合要求,然后将录制视频的URL传递回调用的视图控制器,并隐藏当前录制的视图控制器。

        // 完成controlView.finishButtonClickBlock = { [weak self] inguard let self = self else { return }// 判断时长if self.currentDuration < self.minDuration {MWToast.showToast("Video at least \(self.minDuration) seconds")return}self.recordingCompletionHandler?(self.coverImage,self.videoURL)self.exit()}

录制的代理

在MWRecordingController中我们定义了两个代理方法,用于回调录制的错误信息以及录制完成的视频地址。

    //MARK: MWRecordingControllerDelegate/// 录制报错func recordingController(_ controller: MWRecordingController, didFailWithError error: any Error) {let image = UIImage(named: "login_toast_left_icon")MWToast.showTopToast(error.localizedDescription, icon: image)}/// 录制完成func recordingController(_ controller: MWRecordingController, didFinishRecordingTo outputFileURL: URL) {videoURL = outputFileURLlet image = generateCoverImage()coverImage = imageif currentDuration < minDuration {MWToast.showToast("Video at least \(minDuration) seconds")return}}
  1. 错误信息直接显示Toast。
  2. 录制完成后,根据视频地址读取视频封面。

计时器

开启和关闭计时器,在定时事件中更新录制时长,如果达到录制的最大时长自动结束录制。

    /// 开启定时器private func startTimer() {if timer != nil {return}MWLogHelper.debug("开启定时器", context: "MWRecordingViewController")timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)}/// 结束定时器private func stopTimer() {MWLogHelper.debug("结束定时器", context: "MWRecordingViewController")timer?.invalidate()timer = nil}/// 定时器事件@objc private func timerAction() {// 读取录制时长let duration = recordingController.durationcurrentDuration = CMTimeGetSeconds(duration)if currentDuration >= maxDuration {// 结束录制recordingController.stopRecording()recordingState = .finishcontrolView.setRecordingState(state: recordingState)stopTimer()} else {controlView.updateTime(time: currentDuration)}}

结语

在本篇博客中,我们详细介绍了如何在 ViewController 中实现完整的 iOS 视频录制功能。通过整合之前讨论的录制管理核心 MWRecordingController 和自定义的 UI 组件,我们构建了一个可交互的视频录制界面,涵盖了录制的各个方面:从视频预览、录制控制到视频保存与封面生成,提供了一个完整且流畅的用户体验。

通过这次实现,大家可以了解到如何使用 AVFoundation 框架来处理视频录制,同时也掌握了如何结合自定义 UI 和交互设计,提升应用的易用性与功能性。

在未来,视频录制功能的扩展性非常强,可以根据需求加入更多的特性,如视频特效、实时滤镜、录制过程中的实时预览调整等。随着技术的不断发展,如何优化视频录制的性能、降低资源消耗、提高录制质量等,仍然是值得我们不断探索的方向。

希望本系列博客能够帮助你更好地理解 iOS 视频录制的实现方式,也期待你能将这些知识应用到自己的项目中,打造出更丰富、更有趣的用户体验!

相关文章:

深入解析 iOS 视频录制(三):完整录制流程的实现与整合

深入解析 iOS 视频录制&#xff08;一&#xff09;&#xff1a;录制管理核心MWRecordingController 类的设计与实现 深入解析iOS视频录制&#xff08;二&#xff09;&#xff1a;自定义UI的实现​​​​​​​ 深入解析 iOS 视频录制&#xff08;三&#xff09;&#xff1a;完…...

Python基于Flask的豆瓣Top250电影数据可视化分析与评分预测系统(附源码,技术说明)

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…...

AStar低代码平台RpcServiceBase的应用:客户端事务管理

由于AStar平台是基于RPC协议与AStar后端服务进行通讯&#xff0c;而又非常接近常规BS的编码方式&#xff0c;直接写SQL即可对数据库进行操作&#xff0c;那么如果有若干个访问需要在同一事务中进行的&#xff0c;如何处理&#xff1f;比如先生成临时表&#xff0c;再对临时表进…...

Postman如何流畅使用DeepSeek

上次写了一篇文章是用chatBox调用api的方式使用DeepSeek&#xff0c;但是实际只能请求少数几次就不再能给回响应。这回我干脆用最原生的方法Postman调用接口请求好了。 1. 通过下载安装Postman软件 postman下载(https://pan.quark.cn/s/c8d1c7d526f3)&#xff0c;包含7.0和10…...

RocketMQ - 常见问题

RocketMQ常见问题 文章目录 RocketMQ常见问题一&#xff1a;消息幂等问题1&#xff1a;什么是消费幂等2&#xff1a;消息重复的场景分析2.1&#xff1a;发送时消息重复2.2&#xff1a;消费时消息重复2.3&#xff1a;Rebalance时消息重复 3&#xff1a;通用解决方案3.1&#xff…...

YOLOv12推理详解及部署实现

目录 前言一、YOLOv12推理(Python)1. YOLOv12预测2. YOLOv12预处理3. YOLOv12后处理4. YOLOv12推理 二、YOLOv12推理(C)1. ONNX导出2. YOLOv12预处理3. YOLOv12后处理4. YOLOv12推理 三、YOLOv12部署1. 源码下载2. 环境配置2.1 配置CMakeLists.txt2.2 配置Makefile 3. ONNX导出…...

docker 安装的open-webui链接ollama出现网络错误

# 故事背景 部署完ollama以后&#xff0c;使用谷歌浏览器的插件Page Assist - 本地 AI 模型的 Web UI 可以比较流畅的使用DeepSeek&#xff0c;但是只局限于个人使用&#xff0c;想分享给更多的小伙伴使用&#xff0c;于是打算使用open-webui 来管理用户&#xff0c;经官网推荐…...

【大模型】DeepSeek 的人工智能发展之路

【大模型】DeepSeek 的人工智能发展之路 初出茅庐&#xff1a;成立与奠基&#xff08;2023 年&#xff09;崭露头角&#xff1a;大模型的初步发布&#xff08;2024 年&#xff09;首个大模型 DeepSeek LLM 发布&#xff08;2024 年 1 月 5 日&#xff09;开源第二代 MoE 大模型…...

关于Unity的一些基础知识点汇总

1.Prefab实例化后&#xff0c;哪些资源是共用的&#xff1f;哪些资源是拷贝的&#xff1f; 共用资源 脚本组件&#xff1a;实例化后的 Prefab 共享脚本组件的代码。若脚本中无状态数据&#xff0c;多个实例对脚本方法的调用会有相同逻辑。比如一个控制物体移动的脚本&#xff0…...

Java 大视界 -- 企业数字化转型中的 Java 大数据战略与实践(93)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

Compose常用UI组件

Compose常用UI组件 概述Modifier 修饰符常用Modifier修饰符作用域限定Modifier Modifier 实现原理Modifier.Element链的构建链的解析 常用基础组件文字组件图片组件按钮组件选择器对话框进度条 常用布局组件线性布局帧布局 列表组件 概述 Compose 预置了很多基础组件&#xff…...

【EndNote】WPS 导入EndNote 21

写在前面&#xff1a;有没有人有激活码&#xff0c;跪求&#xff01; EndNote&#xff0c;在文献管理和文献引用方面很好用。写文章的时候&#xff0c;使用EndNote引入需要的文献会很方便。我目前用的WPS&#xff0c;想把EndNote的CWYW&#xff08;Cite While You Write&#…...

【Spring详解三】默认标签的解析

三、默认标签的解析 Spring的标签中有 默认标签和 自定义标签&#xff0c;两者的解析有着很大的不同&#xff0c;这次重点说默认标签的解析过程。 DefaultBeanDefinitionDocumentReader.class 默认标签的解析是在 DefaultBeanDefinitionDocumentReader.parseDefaultElement()函…...

leetcode 2585. 获得分数的方法数

题目如下 数据范围 莫要被困难的外衣骗了&#xff0c;本题就是有数量限制的完全背包问题。显然我们可以令 f(x,y)为当有x种题目时分数为y时的方法数 令某种题目的数量为k 那么方法数应该是 f(x,y) f(x - 1,y - k * (分值))其中(0 < k < 题目数量)通过代码 class So…...

Java Spring boot 篇:常用注解

Configuration 作用 Configuration 注解的核心作用是把一个类标记为 Spring 应用上下文里的配置类。配置类就像一个 Java 版的 XML 配置文件&#xff0c;能够在其中定义 Bean 定义和 Bean 之间的依赖关系。当 Spring 容器启动时&#xff0c;会扫描这些配置类&#xff0c;解析其…...

检索增强生成(RAG)技术应用方案设计

检索增强生成&#xff08;RAG&#xff09;技术应用方案设计 目录 引言背景分析核心技术原理应用领域与案例分析设计方案 5.1 设计目标5.2 技术路线5.3 实施步骤 风险评估与应对措施预期效果与长远展望总结 1. 引言 随着人工智能技术的飞速发展&#xff0c;大型语言模型&…...

【JavaEE进阶】数据库连接池

目录 &#x1f334;数据库连接池 &#x1f38b;数据库连接池的使用 &#x1f332;MySQL企业开发规范 &#x1f334;数据库连接池 数据库连接池负责分配、管理和释放数据库连接&#xff0c;它允许应⽤程序重复使⽤⼀个现有的数据库连接&#xff0c;⽽不是再重新建⽴⼀个. 没…...

意图识别概述

在当今的人工智能领域&#xff0c;意图识别技术是自然语言处理&#xff08;NLP&#xff09;中的一个重要分支&#xff0c;它使得机器能够理解人类语言背后的目的或意图。对于鸿蒙操作系统而言&#xff0c;掌握意图识别技术可以极大地提升用户体验&#xff0c;使设备能更好地响应…...

istio实现灰度发布,A/B发布, Kiali网格可视化(二)

代码发布是软件开发生命周期中的一个重要环节&#xff0c;确保新功能和修复能够顺利上线。以下是几种常见的代码发布流程。在学习灰度发布之前。我们首先回忆下代码发布常用的几种方法。 A/B&#xff08;蓝绿&#xff09;发布&#xff1a; 蓝绿部署是一种通过维护两套独立的环…...

python-leetcode 36.二叉树的最大深度

题目&#xff1a; 给定一个二叉树root,返回其最大深度 二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数 方法一&#xff1a;深度优先搜索 知道了左子树和右子树的最大深度l和r&#xff0c;那么该二叉树的最大深度即为:max(l,r)1 而左子树和右子树的最大深…...

在 Ubuntu 22.04 中修改主机名称(hostname)

在 Ubuntu 22.04 中修改主机名称&#xff08;hostname&#xff09;可以通过以下两种方法实现&#xff0c;一种是临时修改&#xff08;重启后失效&#xff09;&#xff0c;另一种是永久修改。以下是详细步骤&#xff1a; 方法 1&#xff1a;使用 hostnamectl 永久修改 查看当前主…...

解锁机器学习核心算法 | 随机森林算法:机器学习的超强武器

一、引言 在机器学习的广阔领域中&#xff0c;算法的选择犹如为一场冒险挑选趁手的武器&#xff0c;至关重要。面对海量的数据和复杂的任务&#xff0c;合适的算法能够化繁为简&#xff0c;精准地挖掘出数据背后隐藏的模式与价值。机器学习领域有十大核心算法&#xff0c;而随…...

JAVA学习第五天

接口的变量定义固定为静态变量 接口里面只能有抽象方法&#xff0c;且不能有构造方法 如果不重写tostring方法&#xff0c;会打印没有价值的信息...

【CUDA 】第4章 全局内存——4.4 核函数可达到的带宽(4对角转置)

CUDA C编程笔记 第四章 全局内存4.4 核函数可达到的带宽4.4.2.4 对角转置【让DRAM访问更均匀&#xff0c;提高性能】 待解决的问题&#xff1a; 第四章 全局内存 4.4 核函数可达到的带宽 4.4.2.4 对角转置【让DRAM访问更均匀&#xff0c;提高性能】 前置条件场景&#xff1…...

深入理解 lua_KFunction 和 lua_CFunction

在 Lua C API 中,lua_KFunction 和 lua_CFunction 是两个核心概念,尤其在处理协程和 C 函数扩展时扮演着至关重要的角色。lua_CFunction 作为一种 C 函数类型,允许开发者将 C 函数注册到 Lua 环境中,使得这些 C 函数可以在 Lua 脚本中被调用,进而实现 Lua 的功能扩展。而 …...

Nacos Derby 远程命令执行漏洞修复建议

由于Nacos < 2.4.0 BETA 存在 Derby 远程命令执行漏洞&#xff0c;恶意攻击者利用此漏洞可以未授权执行SQL语句&#xff0c;最终导致任意代码执行。目前该漏洞PoC和技术细节已在互联网上公开。 一、漏洞情况分析 Nacos 是一个功能强大的服务注册与发现、配置管理平台&#…...

MySQL(1)基础篇

执行一条 select 语句&#xff0c;期间发生了什么&#xff1f; | 小林coding 目录 1、连接MySQL服务器 2、查询缓存 3、解析SQL语句 4、执行SQL语句 5、MySQL一行记录的存储结构 Server 层负责建立连接、分析和执行 SQL存储引擎层负责数据的存储和提取。支持InnoDB、MyIS…...

java每日精进 2.13 MySql迁移人大金仓

1.迁移数据库 1. 数据库创建语句 MySQL&#xff1a; CREATE DATABASE dbname; 人大金仓&#xff08;Kingbase&#xff09;&#xff1a; 在人大金仓中&#xff0c;CREATE DATABASE 的语法通常相同&#xff0c;但可能需要特别注意字符集的指定&#xff08;如果涉及到多语言支持…...

Java开发实习面试笔试题(含答案)

在广州一家中大公司面试&#xff08;BOSS标注是1000-9999人&#xff0c;薪资2-3k&#xff09;&#xff0c;招聘上写着Java开发&#xff0c;基本没有标注前端要求&#xff0c;但是到场知道是前后端分离人不分离。开始先让你做笔试&#xff08;12道问答4道SQL题&#xff09;&…...

C语言流程控制学习笔记

1. 顺序结构 顺序结构是程序中最基本的控制结构&#xff0c;代码按从上到下的顺序依次执行。大多数C语言程序都是由顺序结构组成的。 2. 选择结构 选择结构根据条件的真假来决定执行哪一段代码。在C语言中&#xff0c;选择结构主要有以下几种&#xff1a; 2.1 if 语句 if语…...

解析DrugBank数据库数据|Python

一、DrugBank 数据库简介 DrugBank 是一个综合性的生物信息学和化学信息学数据库&#xff0c;专门收录药物和靶点的详细信息。它由加拿大阿尔伯塔大学的 Wishart 研究组 维护&#xff0c;提供化学、药理学、相互作用、代谢、靶点等多方面的药物数据。DrugBank 结合了实验数据和…...

排序算法:冒泡排序

冒泡排序标准代码&#xff08;C语言&#xff09; c复制代码 #include <stdio.h>// 冒泡排序函数 void bubbleSort(int arr[], int n) {// 外层循环&#xff1a;控制排序轮数for (int i 0; i < n - 1; i) {// 内层循环&#xff1a;控制每轮比较次数for (int j 0; j…...

网络爬虫学习:借助DeepSeek完善爬虫软件,实现模拟鼠标右键点击,将链接另存为本地文件

一、前言 最近几个月里&#xff0c;我一直在学习网络爬虫方面的知识&#xff0c;每有收获都会将所得整理成文发布&#xff0c;不知不觉已经发了7篇日志了&#xff1a; 网络爬虫学习&#xff1a;从百度搜索结果抓取标题、链接、内容&#xff0c;并保存到xlsx文件中 网络爬虫学…...

[原创](Modern C++)现代C++的关键性概念: 妙用std::reference_wrapper, 让std::list容器具有随机访问功能.

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi、XCode、Eclipse…...

智享AI直播三代系统,马斯克旗下AI人工智能直播工具,媲美DeepSeek!

智享AI直播三代系统&#xff0c;马斯克旗下AI人工智能直播工具,媲美DeepSeek&#xff01; 在科技飞速发展的当下&#xff0c;人工智能正以前所未有的态势重塑着各个行业的格局。直播领域&#xff0c;作为信息传播与商业交互的前沿阵地&#xff0c;也在AI技术的赋能下迎来了颠覆…...

2.19学习记录

Web easyupload3.0 这是一道构造.htaccess文件的传马 如下&#xff1a; <FilesMatch "jpg">SetHandler application/x-httpd-php </FilesMatch>.htaccess文件可以作为一个解释器&#xff0c;可以将传进去的图片马改为php马上传之后再传个图片马&#…...

RT-Thread+STM32L475VET6实现呼吸灯

文章目录 前言一、板载资源资源说明二、具体步骤1.新建rt_thread项目2. 打开PWM设备驱动3. 在Stm32CubeMX配置定时器3.1打开Stm32CubeMX3.2 使用外部高速时钟&#xff0c;并修改时钟树3.3打开定时器1&#xff0c;并配置通道一为PWM输出模式(定时器根据自己需求调整)3.4 打开串口…...

SpringBoot 项目配置动态数据源

目录 一、前言二、操作1、引入依赖2、配置默认数据库 13、定义数据源实体和 Repository4、定义动态数据源5、配置数据源6、定义切换数据源注解7、定义切面类8、使用注解切换数据源 一、前言 通过切面注解方式根据不同业务动态切换数据库 二、操作 1、引入依赖 <dependen…...

动态订阅kafka mq实现(消费者组动态上下线)

和上篇文章 动态订阅rocket mq实现(消费者组动态上下线) 目的一致&#xff0c;直接上代码 /*** Kafka topic container集合*/private static final Map<String, ConcurrentMessageListenerContainer<String, String>> topics new HashMap<>();public void r…...

Coze扣子怎么使用更强大doubao1.5模型

最近&#xff0c;豆包刚刚发布了最新的doubao1.5系列模型&#xff0c;并且加量不加价。 在性能极大进步的情况下&#xff0c;价格还与之前一致。真是业界良心了。 在同样的价格下&#xff0c;肯定要使用性能更强大的模型嘛 于是我准备把所有的智能体和工作流切换到doubao1.5…...

Zookeeper 和 Redis 哪种更好?

目录 前言 &#xff1a; 什么是Zookeeper 和 Redis &#xff1f; 1. 核心定位与功能 2. 关键差异点 (1) 一致性模型 (2) 性能 (3) 数据容量 (4) 高可用性 3. 适用场景 使用 Zookeeper 的场景 使用 Redis 的场景 4. 替代方案 5. 如何选择&#xff1f; 6. 常见误区 7. 总结 前言…...

22.4.3.2 TCP/UDP连接信息

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 通过IPGlobalProperties的方法可以获得有关TCP和UDP连接的信息&#xff1a; GetActiveTcpConnections方法获得所有的TCP连接的信息…...

【Node.js】express框架

目录 1初识express框架 2 初步使用 2.1 安装 2.2 创建基本的Web服务器 2.3 监听方法 2.3.1 监听get请求 2.3.2 监听post请求 2.4 响应客户端 2.5 获取url中的参数(get) 2.5.1 获取查询参数 2.5.2 获取动态参数 2.6 托管静态资源 2.6.1 挂载路径前缀 2.6.2 托管多…...

拦截器VS过滤器:Spring Boot中请求处理的艺术!

目录 一、拦截器&#xff08;Interceptor&#xff09;和过滤器&#xff08;Filter&#xff09;&#xff1a;都是“守门员”&#xff01;二、如何实现拦截器和过滤器&#xff1f;三、拦截器和过滤器的区别四、执行顺序五、真实的应用场景六、总结 &#x1f31f;如果喜欢作者的讲…...

分布式架构与XXL-JOB

目录 先了解什么是任务调度&#xff1f; 什么是分布式任务调度&#xff1f; 了解XXL-JOB分布式任务调度平台 如何搭建XXL-JOB&#xff1f; 分片广播 作业分片方案 最近学习在项目的媒资管理模块如何高效处理大量视频&#xff0c;上传单个视频可能涉及到转码&#xff0c…...

6121A 音频分析仪

6121A 音频分析仪 音频信号产生 音频信号分析 国产 6121A是具有音频信号产生和音频信号分析功能的测试仪器&#xff0c;适用于语音性能测试和音频功放测试等领域&#xff0c;满足电台、移动通信、音响设备和水声通信设备对频响、谐波失真和信噪比等指标的测试需求&#xff…...

什么是幂等性?

一.幂等性 什么是幂等性&#xff1f; 在计算机科学和数学领域中&#xff0c;” 幂等性 “虽然源于相同的概念&#xff0c;但其应用和具体含义有所不同 在数学中&#xff1a;幂等性是一个代数性质&#xff0c;描述的是一个操作或函数在多次应用后结果不变的特性 在分布式系统…...

2025/2/19机试准备

1.%c不忽略空格&#xff08; &#xff09; 2.启示 #include <stdio.h> #include <string.h> int main(){char str[100]{0};int x,y;int n1,n2,n3;int i;while(scanf("%s",str)!EOF){istrlen(str);if(i%30){//12446-2n1i/3;n3i/3;n2i/32;}else if(i%31){…...

【wrk】wrk 压测工具入门

1. 简介 wrk 是我无意间发现的一款简单好用的 HTTP 接口性能测试工具&#xff0c;目前在 Github 上已经有 38k 的 star 数了&#xff01; ⭐ Github地址&#xff1a;https://github.com/wg/wrk 2. 安装 环境要求&#xff1a; windows10 平台安装过 ubuntu 等 Linux 子系统 …...

12.1 Android中协程的基本使用

文章目录 前言1、导入依赖2、使用协程获取服务器中的数据2.1 定义请求回调结果的数据类2.2 网络请求 3、网络回调结构4、通过ViewModel处理网络请求数据 前言 在使用协程的时候一直没有一个具体的概念&#xff0c;只知道协程能够使得异步操作等同于同步操作&#xff0c;且不会…...