【class19】人工智能初步---语音识别(5)

【class19】

上节课,我们学习了:
语音识别模型的结构和原理,同时调用创建好的AipSpeech客户端实现了语音转文字功能。

本节课,我们将初识字幕,学习这些知识点:
1. srt字幕               2. 获取时间数据                             3. 时间换算

我们先来了解一下什么是外挂字幕?这类字幕有三个特点:
1. 独立于视频的字幕文件                             2. 不破坏视频画面,可随时根据需要更换字幕语言
3. 可随时编辑字幕内容,方便修改错误

我们今天要学习和自动生成的srt字幕,就是一种外挂字幕。当你在观看视频的时候,下面的那些字幕可能就是通过srt文件播放的哦~

srt字幕

定义

srt字幕的全称是SubRip Text,是一种文本格式的外挂字幕,也是目前最常用的外挂字幕格式之一。
srt字幕制作规范简单,格式为:序号+时间+字幕,修改十分方便!

我们以文本格式(如word文档,以Unicode(UTF-8)编码方式)打开一个标准的srt字幕文件,可以看到每段字幕由三部分组成:
                 1. 序号                  2. 时间                         3. 字幕

           

学习完srt字幕的概念和内容组成之后:
我们实现“生成标准srt字幕文件”的第一步——从音频中获取时间数据

接下来,我们需要从视频中获取时间数据,以便制作srt字幕中的时间部分~
让我们一起尝试一下吧~

代码结构

将从音频文件中获取时间数据分为两部分:
part1. 导入模块
part2. 获取时间数据

分析代码:

获取时间数据

代码的作用

第12-16行,导入模块,获取语音段的时间信息;第16行,使用detect_nonsilent()获取语音段时间信息。

导入detect_nonsilent类

需要使用的是pydub.silence模块里面的detect_nonsilent类。使用from...import从pydub.silence导入detect_nonsilent类。

detect_nonsilent()

导入模块后,通过detect_nonsilent()获取语音段时间信息。
detect_nonsilent()与前面切分音频中学到的split_on_silence()传入参数和用法一样。

不同之处在于:detect_nonsilent()通过传入静音段的参数min_silence_len, silence_thresh去除静音段,来定位语音段的位置,从而获取语音段时间信息,返回值为列表。

必选参数:sound

sound为必选参数,即待提取时间信息的音频对象。

可选参数:min_silence_len

min_silence_len为可选参数,它表示的是静音段的最小长度,默认值:1000(毫秒)。
设置min_silence_len = 500,表示静音部分长度任何比这大的值将被视为静音段。

可选参数:silence_thresh

silence_thresh为可选参数,它表示的是静音段的最小声音强度,默认值:-16dbfs
设置silence_thresh = -50,表示任何比这安静(如-55)的值将被视为静音。

返回值

将获取的语音段时间信息返回值赋值给变量timestamp_list,返回值为列表。

总结:

获取时间数据
首先,使用from...import从pydub.silence导入detect_nonsilent
然后,使用detect_nonsilent()获取语音段时间信息。

获取语音段时间信息后保存至列表timestamp_list中。输出查看列表timestamp_list,结果为语音段开始时间和结束时间的二维列表

         

二维列表中的每个列表元素为单段语音段的开始时间和结束时间。时间单位为毫秒
二维列表中共12个列表元素,对应着获取的12个音频片段的开始时间的结束时间。
举例说明:图中绿色框内的数据表明,音频片段11.wav在整段音频的22640ms开始,至23048ms结束

              

以文本格式(如word文档)打开一个标准的srt字幕文件,可以看到:
在标准的srt字幕中,时间格式为【时:分:秒,毫秒】。其中,时:分:秒的位数均为两位数毫秒位数为三位数

              

获取了语音段时间数据之后,我们需要进行格式转换:
我们实现“生成标准srt字幕文件”的第二步——毫秒换算成【时:分:秒,毫秒】格式

接下来,我们通过数学计算模和余数,进行时间换算         将毫秒时间换算成【时:分:秒,毫秒】格式。
学习代码前你需要知道的:1秒=1000毫秒,1分钟=60秒,1小时=60分钟。

代码结构

将时间数据格式转换分为两部分:
part1. 毫秒、秒、分和时换算
part2. 组成【时:分:秒,毫秒】格式

分析代码:

毫秒转换

毫秒t除以1000,将毫秒t转换为秒,毫秒,整数为秒,余数为毫秒。
整数和余数分别赋值给spart和mspart。

divmod()

divmod() 函数把取整和取余运算结合起来,返回一个包含商和余数的元组。
这里返回元组为:(t
//1000 , t%1000)

秒转换

秒spart除以60,将秒spart转化为分,秒,整数为分,余数为秒。
整数和余数分别赋值给mpart和spart。

时转换

分mpart除以60,将分mpart转化为时,分,整数为时,余数为分。
整数和余数分别赋值给hpart和mpart。

【时:分:秒,毫秒】格式

通过str()函数将hpart、mpart、spart、mspart转化为字符串格式,并以字符串组成【时:分:秒,毫秒】格式。

本段代码stype的结果为【0:0:0,53】,其中时、分、秒和毫秒的位数都不满足要求。
要求为:时:分:秒的位数均为两位数毫秒位数为三位数
下节课,我们将时间格式处理为标准格式——【00:00:00,053

本节课,我们学习了srt字幕概念,获取了音频中的时间数据,并做了时间换算,初步得到字幕时间。
下节课,我们将完善【时:分:秒,毫秒】格式,以满足字幕格式要求,得到标准的srt字幕文件。

【class20】

上节课,我们学习了:
srt字幕概念,获取了音频中的时间数据,并做了时间换算,初步得到字幕时间。

                        

上节课获取了音频中的时间数据,并做了时间换算,初步得到字幕时间格式为【0:0:0.53】。
但是,时、分、秒和毫秒的位数都不满足srt字幕文件格式要求。
要求为:时:分:秒的位数均为两位数毫秒位数为三位数

本节课,我们将学习这些知识点:
1. 【时:分:秒,毫秒】格式标准化                                   2. 去除标点符号

在上节课生成的时间格式基础之上:
我们实现“标准字幕文件生成”的第一步——时间格式标准化

接下来,我们通过代码实现【时:分:秒,毫秒】格式标准化:将时、分、秒和毫秒的位数调整为srt字幕文件标准【时:分:秒,毫秒】格式。

【时:分:秒,毫秒】格式标准化

代码的作用

第8行-第18行,通过返回指定长度字符串(位数不够前面补0),将【时:分:秒,毫秒】格式标准化。

第9行,mspart返回长度为3的字符串
第11行,spart返回长度为2的字符串
第13行,mpart返回长度为2的字符串
第15行,hpart返回长度为2的字符串
第18行,组成【时:分:秒,毫秒】格式

示例代码:

...

""将毫秒t转换为时,分,秒,毫秒""

spart,mspart = divmod(t,1000)

mpart,spart = divmod(spart,60)

hpart,mpart = divmod(mpart,60)

# mspart返回长度为3的字符串,位数不够前面补0

mspart=str(mspart).zfill(3)

# spart返回长度为2的字符串,位数不够前面补0

spart=str(spart).zfill(2)

# mpart返回长度为2的字符串,位数不够前面补0

mpart=str(mpart).zfill(2)

# hpart返回长度为2的字符串,位数不够前面补0

hpart=str(hpart).zfill(2)

# 组成【时:分:秒,毫秒】格式

stype = hpart+":"+mpart+":"+spart+","+mspart

分析代码:

设置毫秒格式

使用str()函数将mspart转化为字符串,再通过zfill()函数返回长度为3的字符串,位数不够前面补0。

例如:mspart为14,位数为2,通过本行代码可变为"014"。

字符串

使用str()函数将mspart转化为字符串,mspart字符串为待处理对象。

zfill()

通过zfill()函数并传入数字参数,可返回指定长度的字符串。

Zfill()函数的用法

zfill() 是字符串对象的一个方法,用于在字符串的左侧填充指定数量的零字符('0'),直到字符串达到指定的长度。如果字符串已经达到或超过指定的长度,则不会填充任何字符。

zfill() 方法的语法如下:

str.zfill(width)

其中,str 是要操作的字符串,width 是期望的字符串长度。如果 str 的长度小于 width,则在左侧填充足够数量的零字符,直到字符串达到指定的长度。

例如:

s = "42"

padded_s = s.zfill(5)

print(padded_s)  # 输出 "00042"

在这个例子中,字符串 "42" 的长度为 2,通过 zfill(5) 方法,将在字符串左侧填充 3 个零字符,使得最终字符串的长度为 5

这个方法通常用于格式化数字字符串,以确保它们具有相同的长度,方便对齐和比较。

长度

必选参数,zfill()函数传入数字参数3,设置字符串长度为3。

设置秒格式

使用str()函数将spart转化为字符串,再通过zifill()函数返回长度为2的字符串,位数不够前面补0。

设置分格式

使用str()函数将mpart转化为字符串,再通过zifill()函数返回长度为2的字符串,位数不够前面补0。

设置时格式

使用str()函数将hpart转化为字符串,再通过zifill()函数返回长度为2的字符串,位数不够前面补0。

我们已经学会了将毫秒时间转换为【时:分:秒,毫秒】标准时间格式。
基于DRY原则,我们只需要把获取标准时间格式方法写成一个函数,方便多次调用。

编写得到标准时间的函数代码如下:

# 定义函数getTime(),传入参数t

def getTime(t):

    # 将毫秒t转换为秒,毫秒

    # 毫秒t除以1000,整数为秒,余数为毫秒

    spart,mspart = divmod(t,1000)

    # 将秒spart转化为分,秒

    # 秒spart除以60,整数为分,余数为秒

    mpart,spart = divmod(spart,60)

    # 将分mpart转化为时,分

    # 分mpart除以60,整数为时,余数为分

    hpart,mpart = divmod(mpart,60)

    # mspart返回长度为3的字符串,位数不够前面补0

    mspart=str(mspart).zfill(3)

    # spart返回长度为2的字符串,位数不够前面补0

    spart=str(spart).zfill(2)

    # mpart返回长度为2的字符串,位数不够前面补0

    mpart=str(mpart).zfill(2)

    # hpart返回长度为2的字符串,位数不够前面补0

    hpart=str(hpart).zfill(2)

    # 组成【时:分:秒,毫秒】格式

    stype = hpart+":"+mpart+":"+spart+","+mspart

    # 返回标准时间格式stype

    return stype

进行检验:

学到这里,我们已经定义了标准时间格式函数,通过遍历列表可以循环调用。
我们前面得到的时间数据列表为timestamp_list,接下来,我们通过遍历和索引的方式取出二维列表中的每个元素,并将其转换为【时:分:秒,毫秒】标准时间格式。

通过定义时间格式转换函数:
我们已经将二维列表timestamp_list中的时间数据,转换为【时:分:秒,毫秒】的标准时间格式。
接下来,我们开始分析并制作srt字幕

我们再次以文本格式(如word文档)打开一个标准的srt字幕文件,可以看到每段字幕由三部分组成:
第一行:序号,从0开始
第二行:标准时间格式,格式为:开始时间 --> 结束时间
第三行:字幕的文字部分,也就是语音识别的文字

字幕文件中需要注意的:
1.开始时间和结束时间的" --> ",箭头前后各有一个空格;
2.两段字幕之间空了两行分隔开来,方便后续修改字幕。

  

字幕文件的三部分:序号、标准时间格式和文字,我们均已获得。
接下来,我们通过代码将该三部分组合起来,实现“标准字幕文件生成”的第二步——输出标准的srt字幕

学习了如何输出标准的srt字幕之后:
基于DRY原则,我们只需要把输出srt字幕方法写成一个函数,方便多次调用。

生成字幕的函数为:

# 定义函数getsrt(),传入参数sn,start_time,end_time,text

def getsrt(sn,start_time,end_time,text):

    # 序号、开始结束时间和文字组合起来得到标准字幕

    srt_text = str(sn)+"\n"+start_time+" --> "+end_time+"\n"+text+"\n"+"\n"

    # 返回标准字幕srt_text

return srt_text

输出查看srttext的结果,可以看到:
输出的字幕文字部分包括标点符号。一般来说,电影的字幕要求十分严格,不允许加标点符号

      

接下来,我们实现“标准字幕文件生成”的第三步——去除标点符号

通过代码去除字符串中的标点符号
使得输出的字幕文字更符合电影字幕的要求。

示例代码

代码的作用

第3行-第8行,将text文字中的标点符号替换成空格。
第4行,定义常用标点符号列表
第6行,for循环遍历symbol
第8行,使用replace()函数,将text文字中的标点符号替换成空格

...

# 定义常用标点符号列表,赋值给symbol

symbol = [",","。","!","?"]

# for循环遍历symbol

for j in symbol:

    # 使用replace()函数,将text文字中的标点符号替换成空格

text = text.replace(j," ")

分析代码:

标点符号列表

定义常用标点符号列表,包括逗号、句号、感叹号和问号四种。

遍历

通过for循环遍历列表symbol,j为列表symbol中的每个元素。

replace()

使用replace() 函数,把字符串text中的标点符号替换成空格。
用法:new_str = old_str.replace(a,b),将字符串old_str中变量a的值替换为变量b的值,结果赋值给new_str,原字符串old_str不变。

去除字幕文字中的标点符号之后:
我们实现“标准字幕文件生成”的第四步——写入srt字幕文件

写入srt字幕文件函数

通过定义函数writesrt(),传入参数srt,写入标准字幕文件。
使用 with...as 配合open()函数以a方式,打开路径为srtpath的srt文件(没有就新建一个),并赋值给 fp;
使用write()函数写入文件。最后,调用函数writesrt(),写入srt字幕文件,并输出提示信息:srt字幕文件写入成功!

# 定义函数writesrt(),传入参数srtpath,srt,写入标准字幕文件

def writesrt(srtpath,srt):

    # 使用 with...as 配合open函数以a方式,打开路径为srtpath的srt文件

    with open(srtpath,"a") as fp:

        # 使用write()函数写入文件

        fp.write(srt)

       

# 序号sn

sn = 0

# 开始时间start_time,结束时间end_time

start_time = "00:00:00,537"

end_time = "00:00:02,627"

# 文字部分text

text = "看来我不应该来"

# 将以上三部分组合起来,通过换行符\n实现换行

srt_text = str(sn)+"\n"+start_time+" --> "+end_time+"\n"+text+"\n"+"\n"

# 写入文件路径

srtpath = "/Users/yequ/大话西游.srt"

# 调用函数writesrt(),写入srt字幕文件

writesrt(srtpath,srt_text)

# 输出提示信息:srt字幕文件写入成功!

print("srt字幕文件写入成功!")

至此,我们要帮助阿九实现"一键生成srt字幕文件" 的功能就全部完成啦。
我们以文本格式(如word文档)打开生成的“大话西游.srt”字幕文件,可以看到最终的效果了!

使用支持外挂字幕的播放器打开“大话西游.mp4”视频文件,就可以看到视频中的字幕了!
需要注意两点
1.视频文件和字幕文件在同一个文件夹下
2.视频文件和字幕文件命名一样

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java开发-面试题-0001-String、StringBuilder、StringBuffer的区别

Java开发-面试题-0001-String、StringBuilder、StringBuffer的区别 更多内容欢迎关注我(持续更新中,欢迎Star✨) Github:CodeZeng1998/Java-Developer-Work-Note 技术公众号:CodeZeng1998(纯纯技术文&am…

【2024.5.29数据库MYSQL史上最详细基础学习汇总】

初识数据库 什么是数据库: DB的全称是database,即数据库的意思。数据库实际上就是一个文件集合,是一个存储数据的仓库,数据库是按照特定的格式把数据存储起来,用户可以对存储的数据进行增删改查操作; 什么是关系型数据库(SQL)? 关系型数据库是依据关系模型来创建的…

如何恢复被盗的加密货币?

本世纪,网络犯罪的首要目标是加密货币。 这要归功于加密货币的日益普及和价值,网络犯罪分子已经认识到经济收益的潜力,并将重点转向利用这种数字资产中的漏洞。 在今天的文章中,我们将讨论加密货币恢复和被盗加密货币恢复。 我们…

IPFoxy Tips:海外代理IP适用的8个跨境出海业务

在当今数字化时代,互联网已经成为商业和个人生活不可或缺的一部分。IP代理作为出海业务的神器之一,备受跨境出海业务人员关注。IPFoxy动态、静态纯净代理IP也根据业务需求的不同,分为静态住宅、动态住宅、静态IPv4、静态IPv6四种类型代理。那…

【软件测试】LoadRunner参数化属性设置_单个参数

目录 为什么使用参数化属性详解Select next rowSequential(顺序)Random(随机)Unique(唯一)Same line as XXX(和XXX属性的取值方式一样) Update value onEach iteration(每…

HDTune和CrystalDiskInfo硬盘检测S.M.A.R.T.参数当前值最差值阈值

高亮颜色说明:突出重点 个人觉得,:待核准个人观点是否有误 高亮颜色超链接 文章目录 S.M.A.R.T.监控技术磁盘健康状态监测,硬盘检测硬盘检测工具 HD Tune硬盘检测工具 CrystalDiskInfo 当前值最差值阈值原始值的含义二级标题待补充待补充 开头…

RedHat9 | 配置与管理DNS服务器

一、 知识预备 1、DNS服务器的分类 主DNS服务器 主DNS服务器复制维护所管辖域的域名服务信息,它从域管理员构造的本地磁盘文件中的加载域信息。该文件包含服务器具有管理权的的一部分域结构的精确信息,配置主域服务器需要一整套配置文件: …

《QT实用小工具·六十八》基于QMenu开发的炫酷菜单栏

1、概述 源码放在文章末尾 该项目基于QMenu实现了炫酷的菜单栏效果,包含了如下功能: 1、实现了类似word菜单栏的效果,可以在菜单栏中横向添加不同的菜单 2、鼠标点击菜单可以展开菜单栏,再次点击菜单可以收起菜单栏 3、鼠标点击笑…

Chromium源码学习(1)—— 拉取源码,编译

阅读建议:先简单过一下整个文章目录结构,大致了解一下各个步骤在干什么,然后在上手操作可能会事半功倍。也许你遇到的有些问题文章中已经提及到了,但是由于你没有往下看导致卡进度。 Chromium简介 Chromium项目于2008年发布&…

postman教程-7-文件上传接口

领取资料,咨询答疑,请➕wei: June__Go 上一小节我们学习了postman发送get请求的方法,本小节我们讲解一下postman文件上传接口的请求方法。 postman文件上传的方式大概有两种,一种是form-data类型上传文件,一种是bin…

IEnumerable 、 IEnumerator,yield return

自定义迭代类 》》》using System.Collections; using System.Collections; using System.Runtime.CompilerServices;namespace ConsoleApp1 {// 可迭代对象 标记此类可迭代 继承IEnumerable 类是可以迭代public class SpecificEnumerable : IEnumerable{private readonly …

RAG 高级应用:基于 Nougat、HTML 转换与 GPT-4o 解析复杂 PDF 内嵌表格

一、前言 RAG(检索增强生成)应用最具挑战性的方面之一是如何处理复杂文档的内容,例如 PDF 文档中的图像和表格,因为这些内容不像传统文本那样容易解析和检索。前面我们有介绍过如何使用 LlamaIndex 提供的 LlamaParse 技术解析复…

GD32F103RCT6/GD32F303RCT6(10)独立看门狗/窗口看门狗实验

本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发 后续项目主要在下面该专栏中发布: 手把手教你嵌入式国产化_不及你的温柔的博客-CSDN博客 感兴趣的点个关注收藏一下吧! 电机驱动开发可以跳转: 手把手教你嵌入式国产化-实战项目-无刷电机驱动&am…

集合的综合练习

自动点名器1&#xff1a;班级里有N个学生&#xff0c;实现随机点名器 public class test {public static void main(String [] args) {ArrayList<String> listnew ArrayList<>();//创建一个集合//在集合中添加元素Collections.addAll(list, "李明",&quo…

MySQL8找不到my.ini配置文件以及报sql_mode=only_full_group_by解决方案

一、找不到my.ini配置文件 MySQL 8 安装或启动过程中&#xff0c;如果系统找不到my.ini文件&#xff0c;通常意味着 MySQL服务器没有找到其配置文件。在Windows系统上&#xff0c;MySQL 8 预期使用my.ini作为配置文件&#xff0c;而不是在某些情况下用到的my.cnf文件。 通过 …

常用的优化器汇总及keras实现

1.SGD&#xff08;Stochastic Gradient Descent&#xff09; 2.RMSprop&#xff08;Root Mean Square Propagation&#xff09; 3.Adadelta 4.Adam&#xff08;Adaptive Moment Estimation&#xff09; 5.Nadam 6.代码实现 from sklearn.compose import make_column_transforme…

Java----Maven详解

前言 Maven是Java项目的构建工具&#xff0c;通过项目对象模型&#xff08;POM&#xff09;管理项目配置信息&#xff0c;自动化构建、测试和部署过程。开发人员可定义项目结构、依赖和构建流程&#xff0c;提高开发效率和质量。本文介绍基本概念和用法&#xff0c;帮助您更好…

文本生成流程图 泰酷啦 Excalidraw Mermaid Obsidian

前言 介绍一个很酷的工具&#xff0c;Mermaid to Excalidraw 。作用是用代码生成流程图。 Mermaid 是一款强大的、轻量级的文本到图表的转换工具&#xff0c;它允许用户使用简单的Markdown风格的语法编写文本描述&#xff0c;然后通过JavaScript引擎将其转换成美观的图表。Mer…

vue3 vite title 页面标题设置

效果图&#xff1a; 1. 安装 vite-plugin-html 插件 npm install vite-plugin-html -D2. 修改 vite.config.js import {defineConfig, loadEnv} from vite import { createHtmlPlugin } from "vite-plugin-html" import {resolve} from path import vue from vitej…

生成随机数值与二维数组的探索之旅

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、随机数生成的策略 三、实现过程与代码案例 四、注意事项与扩展讨论 一、引言…