【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.视频文件和字幕文件命名一样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值