一键智能视频语音转文本——基于PaddlePaddle语音识别与Python轻松提取视频语音并生成文案

前言

如今进行入自媒体行业的人越来越多,短视频也逐渐成为了主流,但好多时候是想如何把视频里面的语音转成文字,比如,录制会议视频后,做会议纪要;比如,网课教程视频,想要做笔记;比如,需要提取视频中文案使用;比如,需要给视频加个字幕;这时候,只要把视频转文字就好。
对于不是视频编辑专业人员,处理起来还是比较麻烦的,但网上也有好多可以用的小工具,这些工具大多数都标榜有自己技术和模型,但都是在线模型或者使用过一段时间之后就无法再使用了,这些工具实际上都是基于一些大公司提供的接口衍生出来的AI工具,使用效果也不错。但在处理的过程中,处理的文件要上传到大公司的服务器进行处理,这里可能会涉及到一些数据的安全问题。这些数据很大一部分有可能会涉及到数据泄露与安全的问题。
这个项目的核心算法是基于PaddlePaddle的语音识别加Python实现,使用的模型可以有自己训练,支持本地部署,支持GPU与CPU推理两种文案,可以处理短语音识别、长语音识别、实现输入的语音识别。

一、视频语音提取

想要把视频里面的语音进行识别,首先要对视频里面的语音进行提取,提取视频里的语音有很多用办法,可以借助视频编辑软件(如Adobe Premiere Pro、Final Cut Pro)中提取音频轨道,然后将其导出为音频文件。 也可以借助工具如FFmpeg或者moviepy,通过命令行将视频中的音频提取出来。
这里使用moviepy对视频里面的语音进行提取,MoviePy是一个功能丰富的Python模块,专为视频编辑而设计。使用MoviePy,可以轻松执行各种基本视频操作,如视频剪辑、视频拼接、标题插入等。此外,它还支持视频合成和高级视频处理,甚至可以添加自定义高级特效。这个模块可以读写绝大多数常见的视频格式,包括GIF。无论使用的是Mac、Windows还是Linux系统,MoviePy都能无缝运行,可以在不同平台上使用它。
MoviePy与FFmpeg环境安装:

pip install moviepy
pip install ffmpeg

因为使用moviepy提取出视频里面的音轨的比特率不是16000,不能直接输入到语音识别模型里面,这里还要借助FFmpeg的命来把音频采样率转成16000
在这里插入图片描述
提取音轨:

def video_to_audio(video_path,audio_path):video = VideoFileClip(video_path)audio = video.audioaudio_temp = "temp.wav"if os.path.exists(audio_path):os.remove(audio_temp)audio.write_audiofile(audio_temp)audio.close()if os.path.exists(audio_path):os.remove(audio_path)cmd = "ffmpeg -i " + audio_temp + " -ac 1 -ar 16000 " + audio_pathsubprocess.run(cmd,shell=True)

在这里插入图片描述

二、语音识别

1.PaddleSpeech语音识别

PaddleSpeech是一款由飞浆开源全能的语音算法工具箱,其中包含多种领先国际水平的语音算法与预训练模型。它提供了多种语音处理工具和预训练模型供用户选择,支持语音识别、语音合成、声音分类、声纹识别、标点恢复、语音翻译等多种功能。在这里可以找到基于PaddleSpeech精品项目与训练教程:https://aistudio.baidu.com/projectdetail/4692119?contributionType=1

语音识别(Automatic Speech Recognition, ASR) 是一项从一段音频中提取出语言文字内容的任务。
在这里插入图片描述
目前 Transformer 和 Conformer 是语音识别领域的主流模型,关于这方面的教程可以看飞浆官方发的课程:飞桨PaddleSpeech语音技术课程

2.环境依赖安装

我当前的环境是win10,GPU是N卡3060,使用cuda 11.8,cudnn 8.5,为了之后方便封装,使用conda来安装环境,如果没有GPU,也可以装cpu版本:

conda create -n video_to_txt python=3.8
python -m pip install paddlepaddle-gpu==2.5.1 -i https://pypi.tuna.tsinghua.edu.cn/simple

3. 模型下载

可以从官方git上下载到合适自己的模型:https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/README_cn.md
转换模型:

import argparse
import functoolsfrom ppasr.trainer import PPASRTrainer
from ppasr.utils.utils import add_arguments, print_argumentsparser = argparse.ArgumentParser(description=__doc__)
add_arg = functools.partial(add_arguments, argparser=parser)
add_arg('configs',          str,   'models/csfw/configs/conformer.yml',    '配置文件')
add_arg("use_gpu",          bool,  True,                       '是否使用GPU评估模型')
add_arg("save_quant",       bool,  False,                      '是否保存量化模型')
add_arg('save_model',       str,   'models',                  '模型保存的路径')
add_arg('resume_model',     str,   'models/csfw/models', '准备导出的模型路径')
args = parser.parse_args()
print_arguments(args=args)# 获取训练器
trainer = PPASRTrainer(configs=args.configs, use_gpu=args.use_gpu)# 导出预测模型
trainer.export(save_model_path=args.save_model,resume_model=args.resume_model,save_quant=args.save_quant)

4.语音识别

使用模型进行短语音识别:

 def predict(self,audio_data,use_pun=False,is_itn=False,sample_rate=16000):# 加载音频文件,并进行预处理audio_segment = self._load_audio(audio_data=audio_data, sample_rate=sample_rate)audio_feature = self._audio_featurizer.featurize(audio_segment)input_data = np.array(audio_feature).astype(np.float32)[np.newaxis, :]audio_len = np.array([input_data.shape[1]]).astype(np.int64)# 运行predictoroutput_data = self.predictor.predict(input_data, audio_len)[0]# 解码score, text = self.decode(output_data=output_data, use_pun=use_pun, is_itn=is_itn)result = {'text': text, 'score': score}return result

看看识别结果,是全部整成一块,并没有短句与加标点符号:
在这里插入图片描述

5.断句与标点符号

可以基于飞浆的ERNIE训练标点行号模型:
在这里插入图片描述
添加标点符号代码:

import json
import os
import reimport numpy as np
import paddle.inference as paddle_infer
from paddlenlp.transformers import ErnieTokenizer
from ppasr.utils.logger import setup_loggerlogger = setup_logger(__name__)__all__ = ['PunctuationPredictor']class PunctuationPredictor:def __init__(self, model_dir, use_gpu=True, gpu_mem=500, num_threads=4):# 创建 configmodel_path = os.path.join(model_dir, 'model.pdmodel')params_path = os.path.join(model_dir, 'model.pdiparams')if not os.path.exists(model_path) or not os.path.exists(params_path):raise Exception("标点符号模型文件不存在,请检查{}和{}是否存在!".format(model_path, params_path))self.config = paddle_infer.Config(model_path, params_path)# 获取预训练模型类型pretrained_token = 'ernie-1.0'if os.path.exists(os.path.join(model_dir, 'info.json')):with open(os.path.join(model_dir, 'info.json'), 'r', encoding='utf-8') as f:data = json.load(f)pretrained_token = data['pretrained_token']if use_gpu:self.config.enable_use_gpu(gpu_mem, 0)else:self.config.disable_gpu()self.config.set_cpu_math_library_num_threads(num_threads)# enable memory optimself.config.enable_memory_optim()self.config.disable_glog_info()# 根据 config 创建 predictorself.predictor = paddle_infer.create_predictor(self.config)# 获取输入层self.input_ids_handle = self.predictor.get_input_handle('input_ids')self.token_type_ids_handle = self.predictor.get_input_handle('token_type_ids')# 获取输出的名称self.output_names = self.predictor.get_output_names()self._punc_list = []if not os.path.join(model_dir, 'vocab.txt'):raise Exception("字典文件不存在,请检查{}是否存在!".format(os.path.join(model_dir, 'vocab.txt')))with open(os.path.join(model_dir, 'vocab.txt'), 'r', encoding='utf-8') as f:for line in f:self._punc_list.append(line.strip())self.tokenizer = ErnieTokenizer.from_pretrained(pretrained_token)# 预热self('近几年不但我用书给女儿儿压岁也劝说亲朋不要给女儿压岁钱而改送压岁书')logger.info('标点符号模型加载成功。')def _clean_text(self, text):text = text.lower()text = re.sub('[^A-Za-z0-9\u4e00-\u9fa5]', '', text)text = re.sub(f'[{"".join([p for p in self._punc_list][1:])}]', '', text)return text# 预处理文本def preprocess(self, text: str):clean_text = self._clean_text(text)if len(clean_text) == 0: return Nonetokenized_input = self.tokenizer(list(clean_text), return_length=True, is_split_into_words=True)input_ids = tokenized_input['input_ids']seg_ids = tokenized_input['token_type_ids']seq_len = tokenized_input['seq_len']return input_ids, seg_ids, seq_lendef infer(self, input_ids: list, seg_ids: list):# 设置输入self.input_ids_handle.reshape([1, len(input_ids)])self.token_type_ids_handle.reshape([1, len(seg_ids)])self.input_ids_handle.copy_from_cpu(np.array([input_ids]).astype('int64'))self.token_type_ids_handle.copy_from_cpu(np.array([seg_ids]).astype('int64'))# 运行predictorself.predictor.run()# 获取输出output_handle = self.predictor.get_output_handle(self.output_names[0])output_data = output_handle.copy_to_cpu()return output_data# 后处理识别结果def postprocess(self, input_ids, seq_len, preds):tokens = self.tokenizer.convert_ids_to_tokens(input_ids[1:seq_len - 1])labels = preds[1:seq_len - 1].tolist()assert len(tokens) == len(labels)text = ''for t, l in zip(tokens, labels):text += tif l != 0:text += self._punc_list[l]return textdef __call__(self, text: str) -> str:# 数据batch处理try:input_ids, seg_ids, seq_len = self.preprocess(text)preds = self.infer(input_ids=input_ids, seg_ids=seg_ids)if len(preds.shape) == 2:preds = preds[0]text = self.postprocess(input_ids, seq_len, preds)except Exception as e:logger.error(e)return text

推理结果:
在这里插入图片描述

6.长音频识别

长音频识别要通过VAD分割音频,再对短音频进行识别,拼接结果,最终得到长语音识别结果。 VAD也就是语音端点检测技术,是Voice Activity Detection的缩写。它的主要任务是从带有噪声的语音中准确的定位出语音的开始和结束点。

    def get_speech_timestamps(self, audio, sampling_rate):self.reset_states()min_speech_samples = sampling_rate * self.min_speech_duration_ms / 1000min_silence_samples = sampling_rate * self.min_silence_duration_ms / 1000speech_pad_samples = sampling_rate * self.speech_pad_ms / 1000audio_length_samples = len(audio)speech_probs = []for current_start_sample in range(0, audio_length_samples, self.window_size_samples):chunk = audio[current_start_sample: current_start_sample + self.window_size_samples]if len(chunk) < self.window_size_samples:chunk = np.pad(chunk, (0, int(self.window_size_samples - len(chunk))))speech_prob = self(chunk, sampling_rate).item()speech_probs.append(speech_prob)triggered = Falsespeeches: List[dict] = []current_speech = {}neg_threshold = self.threshold - 0.15temp_end = 0for i, speech_prob in enumerate(speech_probs):if (speech_prob >= self.threshold) and temp_end:temp_end = 0if (speech_prob >= self.threshold) and not triggered:triggered = Truecurrent_speech['start'] = self.window_size_samples * icontinueif (speech_prob < neg_threshold) and triggered:if not temp_end:temp_end = self.window_size_samples * iif (self.window_size_samples * i) - temp_end < min_silence_samples:continueelse:current_speech['end'] = temp_endif (current_speech['end'] - current_speech['start']) > min_speech_samples:speeches.append(current_speech)temp_end = 0current_speech = {}triggered = Falsecontinueif current_speech and (audio_length_samples - current_speech['start']) > min_speech_samples:current_speech['end'] = audio_length_samplesspeeches.append(current_speech)for i, speech in enumerate(speeches):if i == 0:speech['start'] = int(max(0, speech['start'] - speech_pad_samples))if i != len(speeches) - 1:silence_duration = speeches[i + 1]['start'] - speech['end']if silence_duration < 2 * speech_pad_samples:speech['end'] += int(silence_duration // 2)speeches[i + 1]['start'] = int(max(0, speeches[i + 1]['start'] - silence_duration // 2))else:speech['end'] = int(min(audio_length_samples, speech['end'] + speech_pad_samples))speeches[i + 1]['start'] = int(max(0, speeches[i + 1]['start'] - speech_pad_samples))else:speech['end'] = int(min(audio_length_samples, speech['end'] + speech_pad_samples))return speeches

进行长语音识别:

    def predict_long(self,audio_data,use_pun=False,is_itn=False,sample_rate=16000):self.init_vad()# 加载音频文件,并进行预处理audio_segment = self._load_audio(audio_data=audio_data, sample_rate=sample_rate)# 重采样,方便进行语音活动检测if audio_segment.sample_rate != self.configs.preprocess_conf.sample_rate:audio_segment.resample(self.configs.preprocess_conf.sample_rate)# 获取语音活动区域speech_timestamps = self.vad_predictor.get_speech_timestamps(audio_segment.samples, audio_segment.sample_rate)texts, scores = '', []for t in speech_timestamps:audio_ndarray = audio_segment.samples[t['start']: t['end']]# 执行识别result = self.predict(audio_data=audio_ndarray, use_pun=False, is_itn=is_itn)score, text = result['score'], result['text']if text != '':texts = texts + text if use_pun else texts + ',' + textscores.append(score)logger.info(f'长语音识别片段结果:{text}')if texts[0] == ',': texts = texts[1:]# 加标点符号if use_pun and len(texts) > 0:if self.pun_predictor is not None:texts = self.pun_predictor(texts)else:logger.warning('标点符号模型没有初始化!')result = {'text': texts, 'score': round(sum(scores) / len(scores), 2)}return result

推理结果:
在这里插入图片描述
断句结果:

有些大宝贝,我是真的不知道你们是咋想的?我给一对单身男女叫我对象,男女都是同岁的二十八岁女方是幼儿园老师,这个南方是工程师,上个月初两人是第一次见面,互相印象都不错呀,于是又安排见了三四次,就这么断断续续地认识了一个多月,昨天晚上两人又见了面啊,吃了饭之后呢…

三、UI与保存

1. UI界面

为了方便应用,这里使用Gradio这个库,Gradio是一个开源的Python库,用于快速构建机器学习和数据科学演示的应用。它可以帮助你快速创建一个简单漂亮的用户界面,以便向客户、合作者、用户或学生展示你的机器学习模型。此外,还可以通过自动共享链接快速部署模型,并获得对模型性能的反馈。在开发过程中,你可以使用内置的操作和解释工具来交互式地调试模型。Gradio适用于多种情况,包括为客户/合作者/用户/学生演示机器学习模型、快速部署模型并获得性能反馈、以及在开发过程中使用内置的操作和解释工具交互式地调试模型。

pip install gradio
#可以使用清华镜像源来更快的安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple gradio

import os
from moviepy.editor import *
import subprocess
import gradio as gr
from ppasr.predict import PPASRPredictor
from ppasr.utils.utils import add_arguments, print_argumentsconfigs = "models/csfw/configs/conformer.yml"
pun_model_dir = "models/pun_models/"
model_path = "models/csfw/models"predictor = PPASRPredictor(configs=configs,model_path=model_path,use_gpu=True,use_pun=True,pun_model_dir=pun_model_dir)def video_to_audio(video_path):file_name, ext = os.path.splitext(os.path.basename(video_path))video = VideoFileClip(video_path)audio = video.audioaudio_temp = "temp.wav"audio_name = file_name + ".wav"if os.path.exists(audio_temp):os.remove(audio_temp)audio.write_audiofile(audio_temp)audio.close()if os.path.exists(audio_name):os.remove(audio_name)cmd = "ffmpeg -i " + audio_temp + " -ac 1 -ar 16000 " + audio_namesubprocess.run(cmd,shell=True)return audio_namedef predict_long_audio(wav_path):result = predictor.predict_long(wav_path, True, False)score, text = result['score'], result['text']return text# 短语音识别
def predict_audio(wav_path):result = predictor.predict(wav_path, True, False)score, text = result['score'], result['text']return textdef video_to_text(video,operation):audio_name = video_to_audio(video)if operation == "短音频":text = predict_audio(audio_name)elif operation == "长音频":text = predict_long_audio(audio_name)else:text = ""print("视频语音提取识别完成!")return textch = gr.Radio(["短音频","长音频"],label="选择识别音频方式:")demo = gr.Interface(fn=video_to_text,inputs=[gr.Video(), ch],outputs="text")demo.launch()

执行结果:

视频语音提取并转文字

2. 保存识别结果

四、优化与升级

1.优化

该项目目前能识别的语音的词错率为0.083327,对一些语音相近的词语并不能联系上下文进行修改,比如这句

“这个南方是工程师”

这里通过上下文联想,正确的应该是:

“这个男方是工程师”

这样的识别错误并不是很多,还有一些断句没有断好的,如果要优化可以加LLM(大语言模型)来进行一次错误的筛选,这个接入LLM的代码在训练和测试阶段。

2.升级

项目可升级:

  1. 当前项目只针对中文语音,之后会加多语言支持。
  2. 视频没有字幕可以给视频添加字幕生成模块。
  3. 视频有字幕,读取视频画面的字幕并使用OCR识别与语音识别相互验证。
  4. 添加支持web版本。
  5. 可选段对视频语音进行提取识别。
  6. 对多人对话的场景的视频,可以加入声纹识别后格式化识别。
  7. 把生成的文字输出到word并进行排版。

3. 项目源码

源码:https://download.csdn.net/download/matt45m/88386353
模型:

源码配置:

conda create -n video_to_txt python=3.8
python -m pip install paddlepaddle-gpu==2.5.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
cd VideoToTxt
pip install -r requirements.txt
python video_txt.py

然后用浏览器打开:http://127.0.0.1:7860/ ,就可以使用了。

4.备注

如果对该项目感兴趣或者在安装的过程中遇到什么错误的的可以加我的企鹅群:487350510,大家一起探讨。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/148690.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【软件设计师-中级——刷题记录6(纯干货)】

目录 管道——过滤器软件体系结构风格优点&#xff1a;计算机英语重点词汇&#xff1a;单元测试主要检查模块的以下5个特征&#xff1a;数据库之并发控制中的事务&#xff1a;并发产生的问题解决方案:封锁协议原型化开发方法&#xff1a; 每日一言&#xff1a;持续更新中... 个…

CocosCreator3.8研究笔记(二十五)CocosCreator 动画系统-2d骨骼动画spine

大家都知道&#xff0c;在游戏中 一般用帧动画或者骨骼动画&#xff0c;实现 人物的行走、奔跑、攻击等动作。 帧动画&#xff0c;在上一篇已经做了介绍&#xff0c;感兴趣的朋友可以前往阅读&#xff1a; CocosCreator3.8研究笔记&#xff08;二十四&#xff09;CocosCreator …

linux入门---信号的保存和捕捉

目录标题 信号的一些概念信号的保存pending表block表handler表 信号的捕捉内核态和用户态信号的捕捉 信号的一些概念 1.进程会收到各种各样的信号&#xff0c;那么程序对该信号进行实际处理的动作叫做信号的递达。 2.我们之前说过当进程收到信号的时候可能并不会立即处理这个信…

计算机考研 | 2016年 | 计算机组成原理真题

文章目录 【计算机组成原理2016年真题44题-9分】【第一步&#xff1a;信息提取】【第二步&#xff1a;具体解答】 【计算机组成原理2016年真题45题-14分】【第一步&#xff1a;信息提取】【第二步&#xff1a;具体解答】 【计算机组成原理2016年真题44题-9分】 假定CPU主频为5…

51单片机可调幅度频率波形信号发生器( proteus仿真+程序+原理图+报告+讲解视频)

51单片机可调幅度频率信号发生器( proteus仿真程序原理图报告讲解视频&#xff09; 讲解视频1.主要功能&#xff1a;2.仿真3. 程序代码4. 原理图4. 设计报告5. 设计资料内容清单&&下载链接***[资料下载链接](https://docs.qq.com/doc/DS1daV1BKRXZMeE9u)*** 51单片机可…

软件工程与计算总结(三)示例项目描述

本节介绍一个标准的项目描述&#xff0c;大家可以作为蓝本学习~ 目录 一.背景 二.目标 三.系统用户 四.用户访谈要点 1.收银员 2.客户经理 3.总经理 4.系统管理员 五.项目实践过程 一.背景 A是一家刚刚发展起来的小型连锁商店&#xff0c;其前身是一家独立的小百货门面…

算法-数学-斜率-直线上最多的点数

算法-数学-斜率-直线上最多的点数 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/max-points-on-a-line/ 1.2 题目描述 给你一个数组 points &#xff0c;其中 points[i] [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。 2 暴力搜索斜率…

虚拟机VMware的使用流程以及出现的问题附解决方法

虚拟机VMware的使用流程以及出现的问题附解决方法 下载安装 略。。。 创建虚拟机 虚拟机的设置如下&#xff1a;注意网络适配器为NAT 如果出现ip addr 命令&#xff1a;不显示IP地址的话&#xff1a; 解决方式如下&#xff1a; 首先设置网卡&#xff1a;先查看一下onboot是…

OpenCV读取图像时按照BGR的顺序HWC排列,PyTorch按照RGB的顺序CHW排列

OpenCV读取RGB图像 在OpenCV中&#xff0c;读取的图片默认是HWC格式&#xff0c;即按照高度、宽度和通道数的顺序排列图像尺寸的格式。我们看最后一个维度是C&#xff0c;因此最小颗粒度是C。 例如&#xff0c;一张形状为2562563的RGB图像&#xff0c;在OpenCV中读取后的格式…

【Java 进阶篇】JDBC 管理事务详解

在数据库操作中&#xff0c;事务是一个非常重要的概念。事务可以确保一系列的数据库操作要么全部成功执行&#xff0c;要么全部失败回滚&#xff0c;以保持数据库的一致性和完整性。在 Java 中&#xff0c;我们可以使用 JDBC 来管理事务。本文将详细介绍 JDBC 管理事务的方法和…

Leetcode1071. 字符串的最大公因子(三种方法,带详细解析)

Leetcode1071. 字符串的最大公因子 对于字符串 s 和 t&#xff0c;只有在 s t … t&#xff08;t 自身连接 1 次或多次&#xff09;时&#xff0c;我们才认定 “t 能除尽 s”。 给定两个字符串 str1 和 str2 。返回 最长字符串 x&#xff0c;要求满足 x 能除尽 str1 且 x 能…

【面试总结大纲】

面试 1. springSpring AOP的具体实现核心概念分别指的是什么?基于注解的切面实现主要包括以下几个步骤&#xff1a;两个切面&#xff0c;它们之间的顺序是怎么控制的 springmvc的工作流程设计模式原则Spring 框架中用到了哪些设计模式&#xff1f; 2. Java-锁2.1锁的分类可重入…

开发调试管理系统遇到的问题大全错误解决大全收集

问题大全错误解决大全 多模块项目依赖中&#xff0c;项目启动失败-org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException报错&#xff1a;Error: The project seems to require yarn but it‘s not installednpm ERR! fatal: Could not read fro…

动态规划-状态机(188. 买卖股票的最佳时机 IV)

状态分类&#xff1a; f[i,j,0]考虑前i只股票&#xff0c;进行了j笔交易&#xff0c;目前未持有股票 所能获得最大利润 f[i,j,1]考虑前i只股票&#xff0c;进行了j笔交易&#xff0c;目前持有股票 所能获得最大利润 状态转移&#xff1a; f[i][j][0] Math.max(f[i-1][j][0],f[…

Linux高性能服务器编程 学习笔记 第十章 信号

信号是由用户、系统、进程发送给目标进程的信息&#xff0c;以通知目标进程某个状态的改变或系统异常。Linux信号可由以下条件产生&#xff1a; 1.对于前台进程&#xff0c;用户可通过输入特殊终端字符来给它发送信号&#xff0c;如输入CtrlC通常会给进程发送一个中断信号。 2…

视频讲解|基于DistFlow潮流的配电网故障重构代码

目录 1 主要内容 2 视频链接 1 主要内容 该视频为基于DistFlow潮流的配电网故障重构代码讲解内容&#xff0c;对应的资源下载链接为基于DistFlow潮流的配电网故障重构(输入任意线路)&#xff0c;对该程序进行了详尽的讲解&#xff0c;基本做到句句分析和讲解&#xff08;讲解…

双重差分模型(DID)论文写作指南与操作手册

手册链接&#xff1a;双重差分模型&#xff08;DID&#xff09;论文写作指南与操作手册https://www.cctalk.com/m/group/90983583?xh_fshareuid60953990 简介&#xff1a; 当前&#xff0c;对于准应届生们来说&#xff0c;毕设季叠加就业季&#xff0c;写作时间显得十分宝贵…

Polygon Miden zkRollup中的UTXO+账户混合状态模型

1. 引言 本文重点讨论Polygon Miden所设计的UTXO账户混合状态模型&#xff0c;以实现某些有趣的属性。 Miden的目标是&#xff1a;【即越具有隐私性&#xff0c;其可扩展性越好】 构建可扩展去中心化的rollup采用支持隐私的架构 Miden支持灵活的交易模式&#xff1a; 公开…

QT实现TCP服务器客户端的实现

ser&#xff1a; widget.cpp&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//实例化一个服务器server new QTcpServer(this);// 此时&#xf…

软件设计师_计算机网络_学习笔记

文章目录 4.1 网路技术标准与协议4.1.1 协议4.1.2 DHCP4.1.3 DNS的两种查询方式 4.2 计算机网络的分类4.2.1 拓扑结构 4.3 网络规划与设计4.3.1 遵循的原则4.3.2 逻辑网络设计4.3.3 物理网络设计4.3.4 分层设计 4.4 IP地址与子网划分4.4.1 子网划分4.4.2 特殊IP 4.5 HTML4.6 无…