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

news2024/11/16 21:52:10

【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.coloradmin.cn/o/1713832.html

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

相关文章

认识NoSql

SQL是结构化的,NoSql是非结构化的 SQL是关联的: Nosql是无关联的: SQL采用的是SQL查询: 语法固定,好处是:只要是关系型数据库(Mysql,Oracle),都能够使用相同的语句进行查…

Re73 读论文:ULMFiT Universal Language Model Fine-tuning for Text Classification

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名:Universal Language Model Fine-tuning for Text Classification 模型简称:ULMFiT 模型全名:Universal Language Model Fine-tuning ArXiv网址:https…

Three.js 入门介绍与环境搭建

Three.js 入门介绍与环境搭建 一、引言 Three.js 是一个强大的用于在网页上创建和展示 3D 图形的 JavaScript 库。艾斯视觉作为ui设计和前端开发服务商在这里很高兴能与你共同探讨学习:它使得开发者能够轻松地构建令人惊叹的 3D 场景和交互体验。在这篇文章中&…

Type ‘null‘ is not assignable to type ‘T‘. - ArkTSCheck

设置泛型将参数配置为 null 时抛出了如下异常: Type null is not assignable to type T. T could be instantiated with an arbitrary type which could be unrelated to null. <ArkTSCheck> 解决办法 在 null 后面添加 ! 即可,以表示该值不会为 null data: T null! 以…

python-web框架应用程序-Django环境搭建

python-web应用程序-Django环境搭建 一、Django入门 使用Django&#xff08;http://djangoproject.com/&#xff09;来开发一个名为“学习笔记”&#xff08;Learning Log&#xff09;的项目&#xff0c;这是一个在线日志系统&#xff0c;让你能够记录所学习的有关特定主题的知…

leetcode - 20.有效的括号(LinkedHashMap)

leetcode题目有效的括号&#xff0c;分类是easy&#xff0c;但是博主前前后后提交了几十次才通过&#xff0c;现在记录一下使用Java语言的写法。 题目链接: 20.有效的括号 题目描述&#xff1a; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&…

SAP 生产订单报工函数BAPI_PRODORDCONF_CREATE_TT不返回报错信息

最近财务一直反馈MES报工的数据都没有成本,然后去查看原因发现是财务当月的KP26的价格没有进行维护,导致没有收集到工单的报工成本。 但是在前台操作CO11 报工的时候,系统会给出报错的信息 但是我们在调用函数BAPI_PRODORDCONF_CREATE_TT的时候,系统并没有返回报错的信息…

Windows电脑高颜值桌面便利贴,便签怎么设置

在这个看颜值的时代&#xff0c;我们不仅在衣着打扮上追求时尚与美观&#xff0c;就连电脑桌面也不愿放过。一张唯美的壁纸&#xff0c;几款别致的小工具&#xff0c;总能让我们的工作空间焕发出不一样的光彩。如果你也热衷于打造高颜值的电脑桌面&#xff0c;那么&#xff0c;…

下一代 CI/CD:利用 Tekton 和 ArgoCD 实现云原生自动化

一、回顾目标 背景&#xff1a; ​ 部门业务上云&#xff0c;之前服务采用传统的部署方式&#xff0c;这种方式简单&#xff0c;但是不能为应用程序定义资源使用边界&#xff0c;很难合理地分配计算资源&#xff0c;而且程序之间容易产生影响。随着互联网时代的到来&#xff…

Leetcode - 131双周赛

一&#xff0c;3158. 求出出现两次数字的 XOR 值 本题是一道纯模拟题&#xff0c;直接暴力。 代码如下&#xff1a; class Solution {public int duplicateNumbersXOR(int[] nums) {int ans 0;long t 0;for(int x : nums){if(((t>>x)&1) 1){ans ^ x;}else{t | (…

图片去水印工具(低调用哦)

一、简介 1、它是一款专业的图像编辑工具&#xff0c;旨在帮助用户轻松去除照片中不需要的元素或修复照片中的缺陷。无论是修复旧照片、消除拍摄时的不良构图&#xff0c;还是删除照片中的杂乱元素&#xff0c;都能帮助用户快速实现这些目标。其功能强大且操作简单&#xff0c…

代码随想录算法训练营第36期DAY43

DAY43 343整数拆分 注意&#xff1a;当几个数的数值相近&#xff0c;乘积才会尽可能地大&#xff08;好想&#xff1a;数一大一小&#xff0c;最大当然是自己乘以自己&#xff09; 代码随想录官方题解&#xff1a; class Solution {public: int integerBreak(int n) { …

在outlook的邮件中插入HTML;HTML模板获取

本文介绍如何在outlook发送邮件时&#xff0c;在邮件中插入HTML&#xff0c;此HTML可以从获取模板自行进行修改。 文章目录 一、下载HTML模板&#xff08;或自己制作好HTML文件&#xff09;二、outlook新增宏三、新建邮件&#xff0c;插入HTML 一、下载HTML模板&#xff08;或自…

某烟草企业数字化转型物流信息化咨询项目规划方案(117页PPT)

方案介绍&#xff1a; 烟草企业数字化转型物流信息化咨询项目规划方案将为企业带来多方面的价值&#xff0c;包括提升物流运营效率、降低物流成本、优化供应链管理、增强企业竞争力和促进可持续发展等。这些价值的实现将有助于企业在激烈的市场竞争中保持领先地位并实现可持续…

5292A 物联网信号分析仪

5292A 物联网信号分析仪 —— 10MHz&#xff5e;6GHz —— 简述 5292A物联网信号分析仪是一款通用的矢量信号分析仪&#xff0c;频率范围覆盖 10MHz&#xff5e;6GHz&#xff0c;具有良好的频率、功率测量精度和稳定度&#xff1b;支持模拟与数字调制信号、全制式的通信标准…

【408真题】2009-23

“接”是针对题目进行必要的分析&#xff0c;比较简略&#xff1b; “化”是对题目中所涉及到的知识点进行详细解释&#xff1b; “发”是对此题型的解题套路总结&#xff0c;并结合历年真题或者典型例题进行运用。 涉及到的知识全部来源于王道各科教材&#xff08;2025版&…

OpenCV:入门(四)

形态学操作 形态学&#xff0c;即数学形态学&#xff08;Mathematical Morphology&#xff09;&#xff0c;是图像处理过程中一个非常重要的研 究方向。形态学主要从图像内提取分量信息&#xff0c;该分量信息通常对于表达和描绘图像的形状具有 重要意义&#xff0c;通常是图像…

花钱学谢宁DOE培训,投入产出比到底如何?

在当今这个快速发展的时代&#xff0c;无论是职场人士还是创业者&#xff0c;都渴望通过不断学习来提升自我能力&#xff0c;以便在竞争激烈的市场中脱颖而出。其中&#xff0c;谢宁DOE培训因其独特的理念和方法&#xff0c;吸引了众多求学者的目光。然而&#xff0c;面对不菲的…

从零开始利用MATLAB进行FPGA设计(六)用ADC采集信号教程1

黑金的教程做的实在太拉闸了&#xff0c;于是自己摸索信号采集模块的使用方法。 ADC模块&#xff1a;AN9238 FPGA开发板&#xff1a;AX7020&#xff1b;Xilinx 公司的 Zynq7000 系列的芯片XC7Z020-2CLG400I&#xff0c;400引脚 FBGA 封装。 往期回顾&#xff1a; 从零开始利…

Vue项目运行页面禁止缩放【移动端和PC端都禁止缩放】解决方案

Vue项目运行页面禁止缩放【移动端和PC端都禁止缩放】解决方案&#xff0c;有的人手很J,总喜欢放大缩小&#xff0c;从而会导致页面错乱&#xff0c;以下是解决方案&#xff0c;简单有效 效果图PC&#xff1a;滚轮缩放和其他缩放都会禁止 移动端效果图&#xff1a;各种手机平板…