python 视频转mp3

今天分享一个 Python 脚本,这个 Python脚本借助moviepyFFmpeg,将指定的视频文档转码为mp3文档。

Python脚本借助Everything的强大搜索能力,在协助用户搜索和定位视频文件方面提供了极大的便利。

Python脚本默认将转码的文件与源视频文件存放于相同中路径中,如果遇到写入权限不足的情况,会提示用户另行指定其它存放路径。

Python脚本保存转码文件时,将根据用户指定的文档格式,在源文件名的基础上追加新的后缀名作为新的文件名,例如:<源视频文档名>.用户指定的新后缀名

Python脚本在进行视频文档转码时,提供了默认了编解码器,同时亦允许用户指定新的编解码器。

Python 脚本

Python脚本比较简单,逻辑也比较清晰。截图如下:

20240515095950

如👆上图所示,脚本首先定义了一个命令行入参的类,用于管理和解析命令行传入的参数。
然后定义了两个小的函数,这两个函数并不是核心功能,仅用于对比两个指定的字符串中的差异,以及协助在需要时调用TotalCommander打开指定的路径(如果电脑上不存在在TotalCommander,则会使用默认的资源管理器打开指定路径)。

在主程序中(if __name__ == '__main__'部分),脚本首先解析了来自命令行的参数;
然后定义了一个Everything搜索接口对象(该Everything搜索接口对象提供了基于Everything的搜索功能),用于协助用户快速的搜索定位兴趣文档。

关于如何配置Everythinghttp服务,相关的教程资料比较多,大家可以自行搜索哈。

在功能逻辑循环体中,首先引导用户搜索定位待转码的视频文档;然后与用户交互确定转码的目标格式;最后借助 moviepy这个Python包完成视频转码操作;转码操作完成后,脚本会询问是否要打开目标文档所在的路径,脚本可以为用户打开这些目标文档的路径以供用户进行后续的操作。

以上,脚本逻辑清晰自然,贴出Python代码如下👇。

# -*- coding:UTF-8 -*-
"""
@author: dyy
@contact: douyaoyuan@126.com
@time: 2024/5/10 21:40
@file: 视频转码.py
@desc: xxxxxx
"""

# region 引入必要的依赖
import os
import subprocess

模块名 = 'DebugInfo'
try:
    from DebugInfo.DebugInfo import *
except ImportError as impErr:
    print(f"尝试导入 {模块名} 依赖时检测到异常:{impErr}")
    print(f"尝试安装 {模块名} 模块:")
    try:
        os.system(f"pip install {模块名}")
    except OSError as osErr:
        print(f"尝试安装模块 {模块名} 时检测到异常:{osErr}")
        exit(0)
    else:
        try:
            from DebugInfo.DebugInfo import *
        except ImportError as impErr:
            print(f"再次尝试导入 {模块名} 依赖时检测到异常:{impErr}")
            exit(0)

模块名 = 'difflib'
try:
    import difflib  # 需要安装 difflib 模块,以支持字符差异对比操作
except ImportError as impErr:
    print(f"尝试导入 {模块名} 依赖时检测到异常:{impErr}")
    print(f"尝试安装 {模块名} 模块:")
    try:
        os.system(f"pip install {模块名}")
    except OSError as osErr:
        print(f"尝试安装模块 {模块名} 时检测到异常:{osErr}")
        exit(0)
    else:
        try:
            import difflib
        except ImportError as impErr:
            print(f"再次尝试导入 {模块名} 依赖时检测到异常:{impErr}")
            exit(0)

模块名 = 'moviepy'
try:
    from moviepy.editor import VideoFileClip  # 需要引入 moviepy 模块,以支持视频转码的操作
except ImportError as impErr:
    print(f"尝试导入 {模块名} 依赖时检测到异常:{impErr}")
    print(f"尝试安装 {模块名} 模块:")
    try:
        os.system(f"pip install {模块名}")
    except OSError as osErr:
        print(f"尝试安装模块 {模块名} 时检测到异常:{osErr}")
        exit(0)
    else:
        try:
            from moviepy.editor import VideoFileClip
        except ImportError as impErr:
            print(f"再次尝试导入 {模块名} 依赖时检测到异常:{impErr}")
            exit(0)
# endregion

# 定义一个 命令行参数类,用于解析和记录命令行参数
class 命令行参数类(入参基类):
    def __init__(self):
        super().__init__()
        self._添加参数('搜索关键字', str, '指定文档搜索的关键字')
        self._添加参数('everything服务端口', str, 'everything HTTP 服务端口', '22')

    # region 访问器
    @property
    def jsonCfg(self) -> str:
        if 'jsonCfg' in self._参数字典:
            return self._参数字典['jsonCfg'].else:
            return ''

    @jsonCfg.setter
    def jsonCfg(self,: str):
        if 'jsonCfg' in self._参数字典:
            self._参数字典['jsonCfg'].= str()

    @property
    def 搜索关键字(self) -> str:
        if '搜索关键字' in self._参数字典:
            return self._参数字典['搜索关键字'].else:
            return ''

    @搜索关键字.setter
    def 搜索关键字(self,: str):
        if '搜索关键字' in self._参数字典:
            self._参数字典['搜索关键字'].= str()

    @property
    def everything服务端口(self) -> str:
        if 'everything服务端口' in self._参数字典:
            return self._参数字典['everything服务端口'].else:
            return ''

    @everything服务端口.setter
    def everything服务端口(self,: str):
        if 'everything服务端口' in self._参数字典:
            self._参数字典['everything服务端口'].= str()
    # endregion

# 标注两个字符串的差异项
def 差异标注(字串1: str, 字串2: str) -> tuple[str, str]:
    字串1 = str(字串1 if 字串1 else '').strip()
    字串2 = str(字串2 if 字串2 else '').strip()

    # region 原文档变动对齐
    # 使用SequenceMatcher()类计算两个字符串的相似度
    匹配器 = difflib.SequenceMatcher(None, 字串1, 字串2)
    差异 = 匹配器.get_opcodes()

    # 差异标注
    字串1差异标注: str = ''
    字串2差异标注: str = ''
    for opcode, i1, i2, j1, j2 in 差异:
        if opcode == 'equal':
            字串1差异标注 = 字串1差异标注 + 字串1[i1:i2]
            字串2差异标注 = 字串2差异标注 + 字串2[j1:j2]
        elif opcode == 'delete':
            字串1差异标注 = 字串1差异标注 + 红字(字串1[i1:i2])
        elif opcode == 'insert':
            字串2差异标注 = 字串2差异标注 + 绿字(字串2[j1:j2])
        elif opcode == 'replace':
            字串1差异标注 = 字串1差异标注 + 红字(字串1[i1:i2])
            字串2差异标注 = 字串2差异标注 + 绿字(字串2[j1:j2])

    return 字串1差异标注, 字串2差异标注

def 通过totalCommander打开指定路径(路径: str, 搜索接口: 搜索接口类 = None, 画板: 打印模板 = False):
    画板 = 画板 if isinstance(画板, 打印模板) else 打印模板()
    画板.执行位置(通过totalCommander打开指定路径)

    路径 = str(路径 if 路径 else '').strip()
    if not os.path.isdir(路径):
        if os.path.isfile(路径):
            路径 = os.path.abspath(路径)
        else:
            return None

    TOTALCMD64 = os.getenv('TOTALCMD64')
    if not TOTALCMD64:
        # 如果 TOTALCMD64 变量不存在,则尝试搜索 TOTALCMD64.exe 程序
        if isinstance(搜索接口, 搜索接口类) and 搜索接口.可用:
            搜索结果 = 搜索接口.搜索(搜索关键字='TOTALCMD64.EXE',
                                     搜文档=True,
                                     搜路径=False,
                                     画板=画板.副本)
            if 搜索结果.总数 > 0:
                for 结果 in 搜索结果.结果列表:
                    if 结果.lower().endswith('totalcmd64.exe'):
                        TOTALCMD64 = 结果
                        break

    if TOTALCMD64 and TOTALCMD64.lower().endswith('totalcmd64.exe') and os.path.isfile(TOTALCMD64):
        # 尝试使用 totalcommander 来打开路径
        shell指令: str = f'"{TOTALCMD64}" /O /T /R="{路径}"'
        subprocess.Popen(shell指令)
    else:
        # 使用系统默认程序打开路径
        if 在nt系统中():
            os.startfile(路径)
        else:
            画板.提示错误('不受支持的操作系统')

if __name__ == '__main__':
    画板 = 打印模板(False)
    画板.执行位置(__file__)

    # region 解析入参
    入参 = 命令行参数类()
    入参.解析Json(画板=画板.副本.缩进())
    入参.解析入参(画板=画板.副本.缩进())
    if 画板.正在调试:
        入参.展示(画板=画板.副本.缩进())

    搜索关键字: str = 入参.搜索关键字 if 入参.搜索关键字 else ''
    # endregion

    # region 定义搜索接口
    本地搜索: 搜索接口类 = 搜索接口类()
    if 在nt系统中():
        if 入参.everything服务端口:
            本地搜索.everything服务端口 = int(入参.everything服务端口)
        else:
            画板.提示错误('入参.everything服务端口 参数无效')
            exit(1)
    # endregion

    已经打开的目标视频文档路径: list[str] = []
    # region 开始逻辑循环
    while True:
        def 文档排除规则(文档: str) -> bool:  # 排除一些不必要的干扰文档
            if not 文档:  # 空文档不要
                return True
            if '\\recent\\' in 文档.lower():  # recent 文档夹内的文档不要
                return True
            if 文档.lower().endswith('.lnk'):  # *.lnk 文档不要
                return True

        # region 引导用户选择需要转码的视频文档
        while True:
            原视频文档列表 = 交互接口类.指定选择文档(输入提示='请输入关键字以定位视频文档(0: 退出程序):',
                                                 搜索接口=本地搜索,
                                                 搜索关键字=搜索关键字,
                                                 候选项上限=-1,
                                                 排除规则=文档排除规则,
                                                 多选=True,
                                                 画板=画板.副本.缩进())
            if '0' in 原视频文档列表:
                # 用户要求退出程序
                exit(0)

            if 原视频文档列表:
                画板.消息('您选择的文档列出如下:')
                for 文档 in 原视频文档列表:
                    画板.消息(绿字(文档))
                break
        # endregion

        目标视频文档列表: list[str]
        目标视频文档存在性列表: list[bool]
        # region 目标格式信息交互
        while True:
            目标视频文档列表 = []
            目标视频文档存在性列表 = []
            目标格式后缀名: str = 交互接口类.发起文本交互(输入提示='请输入视频目标格式(0: 退出程序):',
                                                          画板=画板.副本.缩进())
            if '0' == 目标格式后缀名:
                # 用户要求退出程序
                exit(0)

            if 目标格式后缀名.startswith('。'):
                目标格式后缀名 = f'.{目标格式后缀名[1:]}'
            if not 目标格式后缀名.startswith('.'):
                目标格式后缀名 = f'.{目标格式后缀名}'

            if not 目标格式后缀名.strip('.'):
                # 如果后缀名是空的,则重新要求输入
                continue

            # 后缀名统一转换成小写格式
            目标格式后缀名 = 目标格式后缀名.lower()

            # 合成目标文档名:
            for 文档 in 原视频文档列表:
                目标视频文档列表.append(f'{文档}{目标格式后缀名}')
                目标视频文档存在性列表.append(os.path.isfile(f'{文档}{目标格式后缀名}'))

            # 打印并提示用户确认转换方式
            画板.消息(黄字('即将启动的转码过程如下:'))
            画板.准备表格(对齐控制串='rl')
            for 序号 in range(len(原视频文档列表)):
                原文档,目标文档 = 差异标注(原视频文档列表[序号],目标视频文档列表[序号])
                画板.添加一行(原文档, 洋红字('->'), 目标文档, 红字('已存在') if 目标视频文档存在性列表[序号] else 绿字('待转码'))
            画板.展示表格(列间距=[0,0])

            转码确认: str = 交互接口类.发起文本交互(输入提示=f'是否确认转码?({绿字("y: 确认")}; {黄字("m: 修改目标格式")}; {红字("0: 退出程序")})',
                                                    限定范围='YyMm0',
                                                    画板=画板.副本.缩进()).lower()
            if '0' == 转码确认:
                # 用户要求退出
                exit(0)
            elif 'y' == 转码确认:
                # 用户确认转码
                break
            else:
                # 用户输入了 m,要求重新修改目标格式
                pass
        # endregion

        目标视频文档路径列表: list[str] = [] # 用户记录目标视频文档的存放路径
        # region 开始视频转码
        编解码格式: str = ''
        for 序号 in range(len(原视频文档列表)):
            视频切片 = VideoFileClip(原视频文档列表[序号])
            while not 目标视频文档存在性列表[序号]:
                if not 目标格式后缀名.endswith('gif'):
                    # 如果不是要求转成 gif, 则需要指定编码格式
                    if not 编解码格式:
                        if 目标格式后缀名.endswith('mp3'):
                            # 如果要求转成 mp3 音频,则不需要指定编码格式
                            pass
                        elif 目标格式后缀名.endswith('wav'):
                            # 如果是要求转换成音频是 wav
                            编解码格式 = 交互接口类.发起文本交互(
                                输入提示=f'默认 codec 参数是 pcm_s32le, 输入 {绿字("y 以确认")}; '
                                         f'或者您可以输入其它编码格式({红字("0")}: {红字("退出程序")}):',
                                画板=画板.副本.缩进()).lower()
                            if 'y' == 编解码格式:
                                # 用户确认使用 pcm_s32le 作为 codec 参数
                                编解码格式 = 'pcm_s32le'
                        else:
                            编解码格式 = 交互接口类.发起文本交互(
                                输入提示=f'默认 codec 参数是 libx264, 输入 {绿字("y 以确认")}; '
                                         f'或者您可以输入其它编码格式({红字("0")}: {红字("退出程序")}):',
                                画板=画板.副本.缩进()).lower()
                            if 'y' == 编解码格式:
                                # 用户确认使用 libx264 作为 codec 参数
                                编解码格式 = 'libx264'
                    if '0' == 编解码格式:
                        # 用户要求退出程序
                        exit(0)

                try:
                    if 目标格式后缀名.endswith('gif'):
                        # 转成gif图片
                        视频切片.write_gif(filename=目标视频文档列表[序号])
                    elif 目标格式后缀名.endswith('wav'):
                        # 转成 wav 音频
                        视频切片.audio.write_audiofile(filename=目标视频文档列表[序号], codec=编解码格式)
                    elif 目标格式后缀名.endswith('mp3'):
                        # 转成 mp3 音频
                        视频切片.audio.write_audiofile(filename=目标视频文档列表[序号])
                    elif 编解码格式:
                        # 根据指定的编码格式转成目标格式的视频文档
                        视频切片.write_videofile(filename=目标视频文档列表[序号], codec=编解码格式)
                    else:
                        # 不指定编码格式,尝试转成目标目标格式的视频文档
                        视频切片.write_videofile(filename=目标视频文档列表[序号])
                except Exception as exp:
                    画板.提示错误('视频转码遇到异常如下:')
                    画板.消息(exp.__str__())

                    if 'Permission denied' in exp.__str__():
                        # 这可能是遇到了写入权限问题,此时需要引导用户指定新的目标视频存放地址
                        指定视频文档存放位置: str = 交互接口类.指定选择路径(输入提示=f'请指定视频转码文档的存放位置, 输入关键字以辅助定位路径:',
                                                                            候选项上限=-1,
                                                                            搜索接口=本地搜索,
                                                                            画板=画板.副本.缩进())
                        if '0' == 指定视频文档存放位置:
                            # 用户要求退出程序
                            exit(0)
                        else:
                            当前目标视频存放位置: str = os.path.split(目标视频文档列表[序号])[0]
                            # 把 目标视频文档列表 中指向 当前目标视频存在位置 的目标视频文档命名重定向到新的指定的存放位置
                            for 子序号 in range(序号,len(目标视频文档列表)):
                                视频文档路径,视频文档名 = os.path.split(目标视频文档列表[子序号])
                                if 视频文档路径 == 当前目标视频存放位置:
                                    目标视频文档列表[子序号] = os.path.join(指定视频文档存放位置,视频文档名)
                                    目标视频文档存在性列表[子序号] = os.path.isfile(目标视频文档列表[子序号])

                            # 打印更新后的视频转码情况
                            画板.消息(黄字('转码过程更新如下:'))
                            画板.准备表格(对齐控制串='rl')
                            for 子序号 in range(len(原视频文档列表)):
                                原文档, 目标文档 = 差异标注(原视频文档列表[子序号], 目标视频文档列表[子序号])
                                画板.添加一行(
                                    原文档, 洋红字('->'), 目标文档,
                                    红字('已存在') if 目标视频文档存在性列表[子序号] else 绿字('待转码'))
                            画板.展示表格(列间距=[0, 0])
                        # 目标视频文档列表更新完成后, 重新尝试转码
                    else:
                        # 清除 codec 参数,重新发起交互
                        编解码格式 = ''

                    continue
                else:
                    # 如果转码顺利完成,则关闭 视频切片,开始下一段视频的处理
                    视频切片.close()
                    目标视频文档路径: str = os.path.abspath(目标视频文档列表[序号])
                    if 目标视频文档路径 not in 目标视频文档路径列表:
                        # 目标视频文档路径列表.append(目标视频文档路径)
                        目标视频文档路径列表.append(目标视频文档路径)
                    break
        # endregion

        # region 确认是否协助用户打开目标视频文档路径
        需要协助打开的路径列表: list[str] = [路径 for 路径 in 目标视频文档路径列表 if 路径 not in 已经打开的目标视频文档路径]
        if 需要协助打开的路径列表:
            用户决策: str = 交互接口类.发起文本交互(输入提示=f"是否需要打开目标文件夹?({绿字('y:确认打开')};"
                                                             f"{红字('n:不打开')};"
                                                             f"{红字('0:退出程序')})",
                                                    限定范围='YyNn0',
                                                    画板=画板.副本.缩进()).lower()
            if 'y' == 用户决策:
                for 路径 in 需要协助打开的路径列表:
                    通过totalCommander打开指定路径(路径=路径,
                                                   搜索接口=本地搜索,
                                                   画板=画板.副本.缩进())
                    已经打开的目标视频文档路径.append(路径)
            elif '0' == 用户决策:
                # 用户要求退出程序
                exit(0)
        # endregion
    # endregion

使用演示

👉第一步,脚本首先引导用户搜索和定位视频文件,我们可以输入视频文件名信息以定位视频文档,然后参过序号选择目标文档;如下👇:
20240515101343

👉第二步,脚本询问我们需要将视频文档转换为什么样的目标格式,我们输入目标文档的后缀名,然后再一次确认脚本的问询;如下👇:
20240515101610
在这一步中,我们输入目标格式为 mp3,此时脚本列出了我们每个文件的转码预测,以及目标mp3是否已经存在,如果目标mp3文件已经存在,则脚本后续的转码过程中,就不会对该文件进行重复转码了。

👉第三步,脚本会询问用户是否确认转码,在获取用户确认后,脚本会对指定的视频文件逐一进行转码。如下👇:
20240515101912

👉第四步,脚本完成转码后,会询问用户是否需要打开目标文件路径,根据用户的决策结果来为用户打开目标文件路径,以便用户继续后续的操作。

以上👆脚本交互完成后,脚本即开始了视频转码过程,我们耐心等待转码完成即可,如下👇:
20240515102210

懒人包

以上 Python脚本,对应的bat调用脚本,和对应的cfg参数文档,统一进行了打包,见:Python 视频转mp3脚本。
获取用户确认后,脚本会对指定的视频文件逐一进行转码。如下👇:
[外链图片转存中…(img-Z1ZnaJ9L-1715740037940)]

👉第四步,脚本完成转码后,会询问用户是否需要打开目标文件路径,根据用户的决策结果来为用户打开目标文件路径,以便用户继续后续的操作。

以上👆脚本交互完成后,脚本即开始了视频转码过程,我们耐心等待转码完成即可,如下👇:
[外链图片转存中…(img-qAAfCgPH-1715740037940)]

懒人包

以上 Python脚本,对应的bat调用脚本,和对应的cfg参数文档,统一进行了打包,见:Python 视频转mp3脚本。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ORACLE ODAX9-2的一个误告警Affects: /SYS/MB的分析处理

在运维的多套ORACLE ODAX9-2版本&#xff0c;都遇到了一个计算节点的告警&#xff1a;Description: The service Processor poweron selftest has deteced a problem. Probabity;:100, UulD:cd1ebbdf-f099-61de-ca44-ef646defe034, Resource:/SYS/MB,&#xff1b;此告警从描述上…

Go系列:git status 高级技巧

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

单片机片上资源——串口讲解

串口模式图 SBUF&#xff1a;串口数据缓存寄存器&#xff0c;物理上是两个独立的寄存器&#xff0c;但占用相同的地址。写操作时&#xff0c;写入的是发送寄存器&#xff0c;读操作时&#xff0c;读出的是接收寄存器

【全开源】JAVA红娘婚恋相亲交友系统源码支持微信小程序+微信公众号+H5+APP

红娘婚恋相亲交友系统&#xff1a;遇见你的命中注定 在快节奏的现代生活中&#xff0c;许多单身男女都在寻找一个平台&#xff0c;希望能遇见那个能与自己携手共度一生的伴侣。红娘婚恋相亲交友系统正是为了满足这一需求而诞生的&#xff0c;它旨在为广大单身男女提供一个安全…

7.学习STL中的string类:版本、组件、构造、操作及应用

目录 1. 什么是STL 2. STL的版本 3. STL的六大组件 1. 为什么学习string类&#xff1f; 1.1 C语言中的字符串 2. 标准库中的string类 2.1 string类(了解) 2.2 string类的常用接口说明 1. string类对象的常见构造 2. string类对象的容量操作 reserve 3. string类对象…

百面算法工程师 | python解释器基础问答

本文给大家带来的百面算法工程师是深度学习python解释器面试总结&#xff0c;文章内总结了常见的提问问题&#xff0c;旨在为广大学子模拟出更贴合实际的面试问答场景。在这篇文章中&#xff0c;我们还将介绍一些常见的python用法&#xff0c;并提供参考的回答及其理论基础&…

【Flask框架】

6.Flask轻量型框架 6.1Flask简介 python提供的框架中已经写好了一个内置的服务器&#xff0c;服务器中的回应response行和头已经写好&#xff0c;我们只需要自己写显示在客户端&#xff0c;的主体body部分。 ---------------------------------------------------------- Fla…

OpenAI新模型GPT-4o“炸裂登场” 响应速度堪比真人 关键还免费!

GPT-4o模型基于来自互联网的大量数据进行训练&#xff0c;更擅长处理文本和音频&#xff0c;并且支持50种语言。更值得一提的是&#xff0c;GPT-4o最快可以在232毫秒的时间内响应音频输入&#xff0c;几乎达到了人类的响应水平。 GPT-4o有多“炸裂”&#xff1f;核心能力有三 G…

Web前端学习路线

本文发表于入职啦(公众号: ruzhila) 大家可以访问入职啦学习更多的编程实战。整理了一份关于前端学习的指南&#xff0c;希望对大家有所帮助。 为什么需要学习前端&#xff1f; 本文讲的前端是指Web开发前端&#xff0c;不包括Android、iOS、小程序等移动端开发。 当前的浏览…

【面试必看】MySQL部分

MySQL 1. 基础 1. 什么是关系型数据库&#xff1f; 一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系&#xff08;一对一、一对多、多对多&#xff09;。各种表中&#xff08;比如用户表&#xff09;&#xff0c;表中的每一行就存放着一条…

工具:资源包提取

1.提取unity资源包的工具 一定要通过文件夹的方式选择unity文件否则导出来后的资源不完整

python:merge的用法

目录 1.merge基本语法 2.参数说明 3.示例 在Python的Pandas库中&#xff0c;merge函数是一种常用的工具&#xff0c;用于根据一个或多个键将两个或多个DataFrame对象合并在一起。以下是merge函数的基本用法和参数解释&#xff1a; 1.merge基本语法 pd.merge(left, right, …

BFS和DFS优先搜索算法

1. BFS与DFS 1.1 BFS DFS即Depth First Search&#xff0c;深度优先搜索。它是一种图遍历算法&#xff0c;它从一个起始点开始&#xff0c;逐层扩展搜索范围&#xff0c;直到找到目标节点为止。 这种算法通常用于解决“最短路径”问题&#xff0c;比如在迷宫中找到从起点到终…

Char类型、转义及字符集:Java中的字符串奥秘

在Java的8中基本数据类型中&#xff0c;char类型是较难掌握&#xff0c;处理char类型本身的用法之外&#xff0c;还要理解其与字符串的关系、转义序列、字符集。 本文将从基础概念出发&#xff0c;逐步深入探讨这些主题&#xff0c;并通过实例演示来巩固理解。 一、Char类型&…

【leetcode面试经典150题】-27. 移除元素

88.合并两个有序数组 1 题目介绍1 个人解题思路1.1 解题代码1.2 思路解析 2、分析官方题解2.1 单侧双指针2.2 双侧双指针 1 题目介绍 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外…

C++自定义脚本文件执行

FunctionCall.h&#xff1a; #include <sstream> #include <string> #include <vector> // 函数调用 class FunctionCall { public: FunctionCall(); ~FunctionCall(); std::string call(const st…

天锐绿盾和bitlocker有啥区别?

#绿盾文档加密系统# 天锐绿盾和BitLocker是两种不同的数据加密解决方案&#xff0c;它们各自有不同的重点和应用场景&#xff0c;以下是它们之间的主要区别&#xff1a; PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 移动…

每日一题:最大加号标志

在一个 n x n 的矩阵 grid 中&#xff0c;除了在数组 mines 中给出的元素为 0&#xff0c;其他每个元素都为 1。mines[i] [xi, yi]表示 grid[xi][yi] 0 返回 grid 中包含 1 的最大的 轴对齐 加号标志的阶数 。如果未找到加号标志&#xff0c;则返回 0 。 一个 k 阶由 1 组…

永磁同步电机的脉振高频注入无速度传感器simulink仿真模型

整理了永磁同步电机的脉振高频注入无速度传感器simulink仿真模型&#xff0c;该模型高频注入仿真pmsm&#xff0c;无感控制&#xff0c;解决0速转矩输出问题&#xff0c;插入式永磁同步电机&#xff0c;凸极&#xff0c;高频注入。MATLAB/simulink仿真&#xff0c;适合研究学习…

深度学习面试问题 | 降维

本文给大家带来的百面算法工程师是深度学习降维面试总结&#xff0c;文章内总结了常见的提问问题&#xff0c;旨在为广大学子模拟出更贴合实际的面试问答场景。在这篇文章中&#xff0c;我们还将介绍一些常见的深度学习面试问题&#xff0c;并提供参考的回答及其理论基础&#…