利⽤百度语⾳识别接⼝将语⾳转换成⽂字教程
⼀、说明
如果有⼀个⼯具能识别⾳视中的语⾳并转换成⽂字输出,由于可以复制粘贴⽽不需要逐字逐句地打,那我们进⾏为⾳频配字幕⼯作时将会事半功倍。
其中的关键点是⾳⽂转换,⾳⽂转换其实在很多地⽅都可以看到⽐如qq,百度搜索,讯飞输⼊法等等,具体到技术⽽⾔前述的三个场景其背后的技术都是⼀样的,都是利⽤AI进⾏语⾳识别。⽽且腾讯、百度、讯飞当前都开放了⾃家的语⾳识别接⼝免费使⽤,本⽂就是利⽤的百度语⾳识别接⼝实现的转换。
其实就配字幕这种⼯作⽽⾔,当前应该可以实现通过写代码⾃动给⾳频⽂件配上字幕,复制粘贴这步都可以省了,当然这不在本⽂的实现范围。
另外AI识别有⼀定的错误率,在我们⾃⼰使⽤qq、百度、讯飞时应该都有体会,更何况开放出来的接⼝⼀般都不会是公司产品百分百的能⼒,所以肯定还是要⼈⼯介⼊修正。
⼆、⾳⽂转换程序
2.1 程序说明
官⽅⽂档:
语⾳识别接⼝:vop.baidu/server_api
接⼝要求:只接受pcm格式⾳频,请求次数不限但每个⾳视不能超过60秒
系统环境:Windows-7 X64、Python-3.6.5 X64(miniconda)。minicoda安装可参见“”第⼆⼤点,如果直接安装python⽹上搜搜教程即可。另外需要requests模块所以装完python后需要执⾏pip install requests安装⼀下。
gihub地址:。这⾥将程序和之前写的程序都放在了BaiduAI项⽬录,只管其中的vtt⽬录即可。
程序⽀持:仅⽀持mp3格式⽂件,仅⽀持英语(要⽀持普通话将post的dev_pid参数修改为1536即可,参见官⽅⽂档)
程序流程:获取video⽬录下的所有mp3⽂件并逐个进⾏处理----将当前要处理的mp3⽂件使⽤ffmpeg转换成pcm格式----将⽣成的pcm⽂件使⽤切割----将切割后的pcm⽂件逐个进⾏⾳⽂转换
运⾏操作:安装好系统环境----将压缩包解压到任意⽬录----将要转换的mp3⽂件复制到video⽂件夹下----使⽤python运⾏baiduvi.py⽂件----程序执⾏完后在video⽂件夹下会为各mp3⽂件⽣成其同名.srt⽂件
其中即是语⾳转换成的⽂字。(⾸版代码⽣成的是txt⽂件,按建议改为直接⽣成.srt格式字幕⽂件,操作等使⽤⽅式都没改变)如下所⽰
2.2 程序代码
程序⾃⼰写的只有⼀个⽂件,我这⾥命名为baiduvi.py
import base64
import json
import os
import time
import shutil
import requests
class BaiduVoiceToTxt():
# 初始化函数
def__init__(self):
# 定义要进⾏切割的pcm⽂件的位置。speech-vad-demo固定好的,没的选
self.pcm_path = ".\\speech-vad-demo\\pcm\\16k_1.pcm"
# 定义pcm⽂件被切割后,分割成的⽂件输出到的⽬录。speech-vad-demo固定好的,没的选
self.output_pcm_path = ".\\speech-vad-demo\\output_pcm\\"
# 百度AI接⼝只接受pcm格式,所以需要转换格式
# 此函数⽤于将要识别的mp3⽂件转换成pcm格式,并输出为.\speech-vad-demo\pcm\16k_1.pcm
def change_file_format(self,filepath):
file_name = filepath
# 如果.\speech-vad-demo\pcm\16k_1.pcm⽂件已存在,则先将其删除
if os.path.isfile(f"{self.pcm_path}"):
# 调⽤系统命令,将⽂件转换成pcm格式,并输出为.\speech-vad-demo\pcm\16k_1.pcm
change_file_format_command = f".\\ffmpeg\\bin\\ -y  -i {file_name}  -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {self.pcm_path}"        os.system(change_file_format_command)
# 百度AI接⼝最长只接受60秒的⾳视,所以需要切割
# 此函数⽤于将.\speech-vad-demo\pcm\16k_1.pcm切割
def devide_video(self):
# 如果切割输出⽬录.\speech-vad-demo\output_pcm\已存在,那其中很可能已有⽂件,先将其清空
# 清空⽬录的⽂件是先删除,再创建
if os.path.isdir(f"{self.output_pcm_path}"):
<(f"{self.output_pcm_path}")
time.sleep(1)
os.mkdir(f"{self.output_pcm_path}")
# 使⽤相对路径.\pcm和.\output_pcm,所以先要将当前⼯作⽬录切换到.\speech-vad-demo下不然不到⽂件
python怎么读取json文件os.chdir(".\\speech-vad-demo\\")
# 直接执⾏.\,其默认会将.\pcm\16k_1.pcm⽂件切割并输出到.\output_pcm⽬录下
devide_video_command = ".\\"
os.system(devide_video_command)
# 切换回⼯作⽬录
os.chdir("..\\")
# 此函数⽤于将.\speech-vad-demo\output_pcm\下的⽂件的⽂件名的时间格式化成0:00:00,000形式
def format_time(self, msecs):
# ⼀个⼩时毫秒数
hour_msecs = 60 * 60 * 1000
# ⼀分钟对应毫秒数
minute_msecs = 60 * 1000
# ⼀秒钟对应毫秒数
second_msecs = 1000
# ⽂件名的时间是毫秒需要先转成秒。+500是为了四舍五⼊,//是整除
# msecs = (msecs + 500) // 1000
# ⼩时
hour = msecs // hour_msecs
if hour < 10:
hour = f"0{hour}"
# 扣除⼩时后剩余毫秒数
hour_left_msecs = msecs % hour_msecs
# 分钟
minute = hour_left_msecs // minute_msecs
# 如果不⾜10分钟那在其前补0凑成两位数格式
if minute < 10:
minute = f"0{minute}"
# 扣除分钟后剩余毫秒数
minute_left_msecs = hour_left_msecs % minute_msecs
# 秒
second = minute_left_msecs // second_msecs
# 如果秒数不⾜10秒,⼀样在其前补0凑⾜两位数格式
if second < 10:
second = f"0{second}"
# 扣除秒后剩余毫秒数
second_left_msecs = minute_left_msecs % second_msecs
# 如果不⾜10毫秒或100毫秒,在其前补0凑⾜三位数格式
if second_left_msecs < 10:
second_left_msecs = f"00{second_left_msecs}"
elif second_left_msecs < 100:
second_left_msecs = f"0{second_left_msecs}"
# 格式化成00:00:00,000形式,并返回
time_format = f"{hour}:{minute}:{second},{second_left_msecs}"
return time_format
# 此函数⽤于申请访问ai接⼝的access_token
def get_access_token(self):
# 此变量赋值成⾃⼰API Key的值
client_id = 'f3wT23Otc8jXlDZ4HGtS4jfT'
# 此变量赋值成⾃⼰Secret Key的值
client_secret = 'YPPjW3E0VGPUOfZwhjNGVn7LTu3hwssj'
auth_url = 'aip.baidubce/oauth/2.0/token?grant_type=client_credentials&client_id=' + client_id + '&client_secret=' + client_secret        response_at = (auth_url)
# 以json格式读取响应结果
json_result = json.loads()
# 获取access_token
access_token = json_result['access_token']
return access_token
# 此函数⽤于将.\speech-vad-demo\output_pcm\下的单个⽂件由语⾳转成⽂件
def transfer_voice_to_srt(self,access_token,filepath):
# 百度语⾳识别接⼝
url_voice_ident = "vop.baidu/server_api"
# 接⼝规范,以json格式post数据
headers = {
'Content-Type': 'application/json'
}
# 打开pcm⽂件并读取⽂件内容
pcm_obj = open(filepath,'rb')
pcm_content_base64 = base64.b64encode(ad())
pcm_obj.close()
# 获取pcm⽂件⼤⼩
pcm_content_len = size(filepath)
# 接⼝规范,则体函义见官⽅⽂件,值得注意的是cuid和speech两个参数的写法
post_data = {
"format": "pcm",
"rate": 16000,
"dev_pid": 1737,
"channel": 1,
"token": access_token,
"cuid": "1111111111",
"len": pcm_content_len,
"speech": pcm_content_base64.decode(),
}
proxies = {
'http':"127.0.0.1:8080"
}
# 调⽤接⼝,进⾏⾳⽂转换
response = requests.post(url_voice_ident, headers=headers, data=json.dumps(post_data))
# response = requests.post(url_voice_ident,headers=headers,data=json.dumps(post_data),proxies=proxies)
if__name__ == "__main__":
# 实例化
baidu_voice_to_srt_obj = BaiduVoiceToTxt()
# ⾃⼰要进⾏⾳⽂转换的⾳视存放的⽂件夹
video_dir = ".\\video\\"
all_video_file =[]
all_file = os.listdir(video_dir)
subtitle_format = "{\\fscx75\\fscy75}"
# 只接受.mp3格式⽂件。因为其他格式没研究怎么转成pcm才是符合接⼝要求的
for filename in all_file:
if".mp3"in filename:
all_video_file.append(filename)
all_video_file.sort()
i = 0
video_file_num = len(all_video_file)
print(f"当前共有{video_file_num}个⾳频⽂件需要转换,即将进⾏处理请稍等...")
# 此层for循环是逐个mp3⽂件进⾏处理
for video_file_name in all_video_file:
i += 1
print(f"当前转换{video_file_name}({i}/{video_file_num})")
# 将⾳视翻译成的内容输出到同⽬录下同名.txt⽂件中
video_file_srt_path = f".\\video\\{video_file_name[:-4]}.srt"
# 以覆盖形式打开.txt⽂件
video_file_srt_obj = open(video_file_srt_path,'w+')
filepath = os.path.join(video_dir, video_file_name)
# 调⽤change_file_format将mp3转成pcm格式
baidu_voice_to_srt_obj.change_file_format(filepath)
# 将转换成的pcm⽂件切割成多个⼩于60秒的pcm⽂件
baidu_voice_to_srt_obj.devide_video()
# 获取token
access_token = baidu_voice_to__access_token()
# 获取.\speech-vad-demo\output_pcm\⽬录下的⽂件列表
file_dir = baidu_voice_to_srt_obj.output_pcm_path
all_pcm_file = os.listdir(file_dir)
all_pcm_file.sort()
j = 0
pcm_file_num = len(all_pcm_file)
print(f"当前所转⽂件{video_file_name}({i}/{video_file_num})被切分成{pcm_file_num}块,即将逐块进⾏⾳⽂转换请稍等...") # 此层for是将.\speech-vad-demo\output_pcm\⽬录下的所有⽂件逐个进⾏⾳⽂转换
for filename in all_pcm_file:
j += 1
filepath = os.path.join(file_dir, filename)
if (os.path.isfile(filepath)):
# 获取⽂件名上的时间
time_str = filename[10:-6]
time_str_dict = time_str.split("-")
time_start_str = baidu_voice_to_srt_obj.format_time(int(time_str_dict[0]))
time_end_str = baidu_voice_to_srt_obj.format_time(int(time_str_dict[1]))
print(f"当前转换{video_file_name}({i}/{video_file_num})-{time_start_str}-{time_end_str}({j}/{pcm_file_num})")
response_text = baidu_voice_to_ansfer_voice_to_srt(access_token, filepath)
# 以json形式读取返回结果
json_result = json.loads(response_text)
# 将⾳⽂转换结果写⼊.srt⽂件
video_file_srt_obj.writelines(f"{j}\r\n")
video_file_srt_obj.writelines(f"{time_start_str} --> {time_end_str}\r\n")
if json_result['err_no'] == 0:
print(f"{time_start_str}-{time_end_str}({j}/{pcm_file_num})转换成功:{json_result['result'][0]}")
video_file_srt_obj.writelines(f"{subtitle_format}{json_result['result'][0]}\r\n")
elif json_result['err_no'] == 3301:
print(f"{time_start_str}-{time_end_str}({j}/{pcm_file_num})⾳频质量过差⽆法识别")
video_file_srt_obj.writelines(f"{subtitle_format}⾳频质量过差⽆法识别\r\n")
else:
print(f"{time_start_str}-{time_end_str}({j}/{pcm_file_num})转换过程遇到其他错误")
video_file_srt_obj.writelines(f"{subtitle_format}转换过程遇到其他错误\r\n")
video_file_srt_obj.writelines(f"\r\n")
video_file_srt_obj.close()
参考:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。