dedecms手机网站制作/百度销售推广
目录
- 前言
- 总体设计
- 系统整体结构图
- 系统流程图
- 运行环境
- 模块实现
- 1. 数据预处理
- 2. 翻译
- 3. 格式转换
- 4. 音频切割
- 5. 语音识别
- 6. 文本切割
- 7. main函数
- 系统测试
- 工程源代码下载
- 其它资料下载
前言
本项目基于百度语音识别API,结合了语音识别、视频转换音频识别以及语句停顿分割识别等多种技术,从而实现了高效的视频字幕生成。
首先,我们采用百度语音识别API,通过对语音内容进行分析,将音频转换成文本。这个步骤使得我们能够从语音中提取出有意义的文本信息。
其次,我们运用视频转换音频识别技术,将视频中的音频部分提取出来,并进行同样的文本识别操作。这样,我们就可以对视频中的声音内容进行准确的文字化。
另外,我们还引入了语句停顿分割识别,用于识别语音中的语句边界和停顿,从而更准确地切分出每个语句的内容。
综合上述技术,我们成功地实现了视频字幕的生成。通过对视频中的语音内容进行逐帧识别、转换和分割,我们能够准确地将语音内容转化为文本,并在视频上生成相应的字幕。
本项目不仅能够为视频内容提供字幕,也为内容创作者提供了方便,使得他们能够更好地将视频内容传达给观众。同时,这也为包括听障人士在内的用户提供了更友好的观看体验。
总体设计
本部分包括系统整体结构图和系统流程图。
系统整体结构图
系统整体结构如图所示。
系统流程图
系统流程如图所示。
运行环境
在Windows环境下完成Python 3所需的配置,并运行代码即可。
模块实现
本项目包括7个模块:数据预处理、翻译、格式转换、音频切割、语音识别、文本切割和main
函数,下面分别给出各模块的功能介绍及相关代码。
1. 数据预处理
基于百度语音API得到所需要的APP_ID
、API_KEY
、SECRET_KEY
。进入百度语音官网地址为http://yuyin.baidu.com,在右上角单击“控制台”按钮,登录百度账号,如图所示。
在控制台左端单击“产品服务”-“语音技术”进入语音识别界面,如图所示。
进入后,可能会提示需要实名认证,填入相关信息,完成认证即可。
单击“创建应用”,根据需求填写项目名称、类型、所需接口、语音包名、应用描述等信息后即可创建成功,如图所示。
按下图,查看应用详情即可得到APP_ID
、API_KEY
、SECRET_KEY
供后续调用,在此界面也可查看调用量限制等信息,如下两图所示。
注意:如果API接口状态为待开通付费的话,需要在左边“概览”页中,选择需要开通的API接口,进行开通。如下图所示。
本项目使用百度语音识别API接口,采用以下两种方法调用,最终采用后者。
(1) 下载使用SDK
根据pip工具使用pip install baidu-aip
下载。
调用代码为:
from aip import AipSpeech
APP_ID = 'XXXXXXX'
API_KEY = '****************'
SECRET_KEY = '*********************'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
#读取文件
def get_file_content(file_path):with open(file_path, 'rb') as fp:return fp.read()
result=client.asr(get_file_content('test2.wav'),'wav',16000,{'dev_pid': 1537,
})
print(type(result))
print(result)
(2)不需要下载SDK
首先,根据文档组装.url获取token;其次,处理本地音频以JSON格式POST到百度语音识别服务器,获得返回结果。
#合成请求token的URLurl = baidu_server + "grant_type=" + grant_type + "&client_id=" + client_id + "&client_secret=" + client_secret#获取tokenres = urllib.request.urlopen(url).read()data = json.loads(res.decode('utf-8'))token = data["access_token"]print(token)
下载配置所需要的库相关操作如下:
(1)安装moviepy库
moviepy用于视频编辑Python库:切割、拼接、标题插入、视频合成、视频处理。moviepy依赖库有numpy、imageio、decorator、 tqdm。
在cmd使用命令pip install moviepy
安装moviepy库。
安装时可能存在的问题:发生报错导致下载安装停止时,查看报错信息可能为依赖库的缺失。
如Anaconda中的Python未安装tqdm发生报错,使用conda list
查看确认缺失该库,可通过conda install tqdm
下载安装,其他库缺失问题也可依照类似方法解决。
(2)安装js2py库
爬虫时很多网站使用js加密技术,js2py可以在Python环境下运行Java代码,摆脱Java环境的瓶颈。制作中英文字幕时,涉及百度语音识别英文输出,需将其翻译为中文,因此,安装is2py库 爬虫调用百度翻译的JavaScript脚本。
(3)安装pydub库
根据音频的静默检测语句停顿,进行合理断句识别,pydub库使用pip工具安装,在cmd命令行输入pip insall pydub
。
使用pydub)库 from pydub import AudioSegment
, 验证安装是否成功可通过例程检测,若报错没有pydub库,则安装失败。
2. 翻译
将识别的英文结果使用爬虫调用百度翻译,得到对应的中文翻译。
class baidu_Translate():def __init__(self):self.js = js2py.eval_js('''var i = null;function n(r, o) {for (var t = 0; t < o.length - 2; t += 3) {var a = o.charAt(t + 2);a = a >= "a" ? a.charCodeAt(0) - 87 : Number(a),a = "+" === o.charAt(t + 1) ? r >>> a: r << a,r = "+" === o.charAt(t) ? r + a & 4294967295 : r ^ a}return r}var hash = function e(r,gtk) {var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);if (null === o) {var t = r.length;t > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr( - 10, 10))} else {for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++)"" !== e[C] && f.push.a pply(f, a(e[C].split(""))),C !== h - 1 && f.push(o[C]);var g = f.length;g > 30 && (r = f.slice(0, 10).join("")+f.slice(Math.floor(g/ 2) - 5, Math.floor(g / 2) + 5).join("") + f.slice( - 10).join(""))}var u = void 0,u = null !== i ? i: (i = gtk || "") || "";for (var d = u.split("."), m = Number(d[0]) || 0, s = Number(d [1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) {var A = r.charCodeAt(v);128 > A ? S[c++] = A: (2048 > A ? S[c++] = A >> 6 | 192 : (55296 ===(64512 & A) && v + 1 < r.length && 56320 ===(64512&r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)), S[c++] = A >> 18 | 240, S[c++] = A >> 12 &63 | 128) : S[c++] = A >> 12 | 224,S[c++] = A >> 6 & 63 | 128), S[c++] = 63 & A | 128)}for (var p = m,F = "+-a^+6", D = "+-3^+b+-f", b = 0;b < S.length; b++) p += S[b],p = n(p, F);return p = n(p, D),p ^= s,0 > p && (p = (2147483647 & p) + 2147483648),p %= 1e6,p.toString() + "." + (p ^ m)}''')headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36', }self.session = requests.Session()self.session.get('https://fanyi.baidu.com', headers=headers)response = self.session.get('https://fanyi.baidu.com', headers=headers)self.token = re.findall("token: '(.*?)',", response.text)[0]self.gtk = '320305.131321201' # re.findall("window.gtk = '(.*?)';", response.text, re.S)[0]def translate(self, query, from_lang='en', to_lang='zh'):#语言检测self.session.post('https://fanyi.baidu.com/langdetect', data={'query': query})#单击事件self.session.get('https://click.fanyi.baidu.com/?src=1&locate=zh&actio n=query&type=1&page=1')#翻译data = {'from': from_lang,'to': to_lang,'query': query,'transtype': 'realtime','simple_means_flag': '3','sign': self.js(query, self.gtk),'token': self.token}response = self.session.post('https://fanyi.baidu.com/v2transapi', data=data)json = response.json()if 'error' in json:pass#return 'error: {}'.format(json['error'])else:return response.json()['trans_result']['data'][0]['dst']
3. 格式转换
百度语音识别API有严格的参数要求,使用moviepy库完成从视频中提取音频工作。
def separate_audio(file_path, save_path):
#视频转音频,音频编码要求:.wav格式、采样率 16000、16bit 位深、单声道audio_file = save_path + '\\tmp.wav'audio = AudioFileClip(file_path)audio.write_audiofile(audio_file, ffmpeg_params=['-ar', '16000', '-ac', '1'], logger=None)return audio_file
4. 音频切割
使用pydub库,利用停顿时的音频分贝降低作为判定断句标准,设置停顿时的分贝阈值,拆分后的小音频不短于0.5s,不长于5s。
def cut_point(path, dbfs=1.25): #音频切割函数sound = AudioSegment.from_file(path, format="wav")tstamp_list = detect_silence(sound, 600, sound.dBFS * dbfs, 1)timelist = []for i in range(len(tstamp_list)):if i == 0:back = 0else:back = tstamp_list[i - 1][1] / 1000timelist.append([back, tstamp_list[i][1] / 1000])min_len = 0.5 #切割所得音频不短于0.5s,不长于5smax_len = 5result = []add = 0total = len(timelist)for x in range(total):if x + add < total:into, out = timelist[x + add]if out-into>min_len and out-into<max_len and x + add +1 < total:add += 1out = timelist[x + add][1]result.append([into, out])elif out - into > max_len:result.append([into, out])else:breakreturn result
5. 语音识别
调用百度语音识别API进行操作,填写申请App所得信息,上传待识别音频,进行中文或英文识别,返回所得文本。
class baidu_SpeechRecognition(): #调用百度语音识别API进行操作def __init__(self, dev_pid):Speech_APP_ID = '19712136'Speech_API_KEY = 'Loo4KbNtagchc2BLdCnHEnZl'Speech_SECRET_KEY = 'DO4UlSnw7FzpodU2G3yXQSHLv6Q2inN8'self.dev_pid = dev_pidself.SpeechClient = AipSpeech(Speech_APP_ID, Speech_API_KEY, Speech_SECRET_KEY)self.TranslClient = baidu_Translate()def load_audio(self, audio_file): #读取加载音频文件self.source = AudioSegment.from_wav(audio_file)def speech_recognition(self, offset, duration, fanyi):
#语音识别,根据要求的参数进行设置data = self.source[offset * 1000:duration * 1000].raw_dataresult = self.SpeechClient.asr(data, 'wav', 16000, {'dev_pid': self.dev_pid, })fanyi_text = ''if fanyi: try:fanyi_text = self.TranslClient.translate(result['result'][0])
#调用translate()函数,将识别文本翻译或直接输出except:passtry:return [result['result'][0], fanyi_text] #返回所得文本except:#print('错误:',result)return ['', '']
6. 文本切割
断句,避免同一画面内出现过多文字影响观感,将38设为阈值,小于38时正常显示,大于则切割,分段显示。
def cut_text(text, length=38): #文本切割,即断句,一个画面最多单语言字数不超过38,否则将多出的加入下一画面newtext = ''if len(text) > length:while True:cutA = text[:length]cutB = text[length:]newtext += cutA + '\n'if len(cutB) < 4:newtext = cutA + cutBbreakelif len(cutB) > length:text = cutBelse:newtext += cutBbreakreturn newtextreturn text
7. main函数
让模块(函数)可以自己单独执行,构造调用其他函数的入口,设置简单的交互功能,用户根据需要选择语言类型、字幕类型以及是否将字幕直接加入视频中,并可观察当前工作进度、推算所需时间、文件格式错误时报错。
if __name__ == '__main__':def StartHandle(timeList, save_path, srt_mode=2, result_print=False):index = 0total = len(timeList)a_font = r'{\fn微软雅黑\fs14}' #中、英字幕字体设置b_font = r'{\fn微软雅黑\fs10}'fanyi = False if srt_mode == 1 else Truefile_write = open(save_path, 'a', encoding='utf-8')for x in range(total):into, out = timelist[x]timeStamp=format_time(into - 0.2) +'--> '+ format_time(out- 0.2)result=baidufanyi.speech_recognition(into+0.1,out - 0.1, fanyi)if result_print:if srt_mode == 0:print(timeStamp, result[0])else:print(timeStamp, result)else:progressbar(total, x, '识别中...&& - {0}/{1}'.format('%03d' % (total), '%03d' % (x)), 44)#将切割后所得的识别文本结果按顺序写入,中、英、中英双语不同if len(result[0]) > 1:index += 1text = str(index) + '\n' + timeStamp + '\n'if srt_mode == 0: # 仅中文text += a_font + cut_text(result[1])elif srt_mode == 1: # 仅英文text += b_font + cut_text(result[0])else: #中文+英文text+=a_font+cut_text(result[1])+'\n'+b_font + result[0]text = text.replace('\u200b', '') + '\n\n'file_write.write(text)file_write.close()if not result_print:progressbar(total,total,'识别中...&&-{0}/{1}'.format('%03d'% (total), '%03d' % (total)), 44)os.system('cls')wav_path = os.environ.get('TEMP')#语音模型,1536为普通话+简单英文,1537为普通话,1737为英语,1637为粤语,1837川话,1936普通话远场pid_list = 1536, 1537, 1737, 1637, 1837, 1936#设置参数print('[ 百度语音识别字幕生成器 - by Teri ]\n')__line__print__('1 模式选择')input_dev_pid = input('请选择识别模式:\n''\n (1)普通话,''\n (2)普通话+简单英语,''\n (3)英语,''\n (4)粤语,''\n (5)四川话,''\n (6)普通话-远场''\n\n请输入一个选项(默认3):')__line__print__('2 字幕格式')input_srt_mode = input('请选择字幕格式:\n''\n (1)中文,''\n (2)英文,''\n (3)中文+英文,''\n\n请输入一个选项(默认3):')__line__print__('3 实时输出')input_print = input('是否实时输出结果到屏幕? (默认:否/y:输出):').upper()#处理参数,根据用户输入给出相应参数dev_pid = int(input_dev_pid) if input_dev_pid else 3dev_pid -= 1srt_mode = int(input_srt_mode) if input_srt_mode else 3srt_mode -= 1re_print = True if input_print == 'Y' else False#输入文件__line__print__('4 打开文件')input_file = input('请拖入一个文件或文件夹并按回车:').strip('"')video_file = []if not os.path.isdir(input_file):video_file = [input_file]else:file_list = file_filter(input_file)for a, b in file_list:video_file.append(a + '\\' + b)#执行确认select_dev = ['普通话', '普通话+简单英语', '英语', '粤语', '四川话', '普通话-远场']select_mode = ['中文', '英文', '中文+英文']__line__print__('5 确认执行')input('当前的设置:\n识别模式: {0}, 字幕格式: {1}, 输出结果: {2}\n当前待处理文件 {3} 个\n请按下回车开始处理...'.format(select_dev[dev_pid],select_mode[srt_mode],'是' if re_print else '否',len(video_file)))#批量处理,调用所设函数进行处理工作total_file = len(video_file)total_time = time.time()baidufanyi = baidu_SpeechRecognition(pid_list[dev_pid])for i in range(total_file): #在所给文件范围内循环运行item_time = time.time() #项目时间file_name = video_file[i].split('\\')[-1]print('\n>>>>>>>> ...正在处理音频... <<<<<<<<', end='')audio_file = separate_audio(video_file[i], wav_path) #视频转音频timelist = cut_point(audio_file, dbfs=1.15) #音频切割if timelist:print('\r>>>>>>>> 当前:{} 预计:{} <<<<<<<<'.format('%03d' % (i),countTime(len(timelist) * 5, now=False)))srt_name = video_file[i][:video_file[i].rfind('.')] + '.srt' #根据时间将输出循环写入字幕文件baidufanyi.load_audio(audio_file) StartHandle(timelist, srt_name, srt_mode, re_print)print('\n{} 处理完成, 本次用时{}'.format(file_name, countTime(item_time)))else:print('音频参数错误')#执行完成,统计所用时间input('全部完成, 处理了{}个文件, 全部用时{}'.format(total_file, countTime(total_time)))
#本部分包括活动类、模块的相关函数、主函数代码
from moviepy.editor import AudioFileClip
from pydub import AudioSegment
from pydub.silence import detect_silence
from aip import AipSpeech
import os
import time
import re
import requests
import js2py
class baidu_Translate():def __init__(self):self.js = js2py.eval_js('''var i = null;function n(r, o) {for (var t = 0; t < o.length - 2; t += 3) {var a = o.charAt(t + 2);a = a >= "a" ? a.charCodeAt(0) - 87 : Number(a),a = "+" === o.charAt(t + 1) ? r >>> a: r << a,r = "+" === o.charAt(t) ? r + a & 4294967295 : r ^ a}return r}var hash = function e(r,gtk) {var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);if (null === o) {var t = r.length;t > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr( - 10, 10))} else {for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++)"" !== e[C] && f.push.apply(f, a(e[C].split(""))),C !== h - 1 && f.push(o[C]);var g = f.length;g > 30 && (r = f.slice(0, 10).join("") + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join("") + f.slice( - 10).join(""))}var u = void 0,u = null !== i ? i: (i = gtk || "") || "";for (var d = u.split("."), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) {var A = r.charCodeAt(v);128 > A ? S[c++] = A: (2048 > A ? S[c++] = A >> 6 | 192 : (55296 === (64512 & A) && v + 1 < r.length && 56320 === (64512 & r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)), S[c++] = A >> 18 | 240, S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224, S[c++] = A >> 6 & 63 | 128), S[c++] = 63 & A | 128)}for (var p = m,F = "+-a^+6", D = "+-3^+b+-f", b = 0;b < S.length; b++) p += S[b],p = n(p, F);return p = n(p, D),p ^= s,0 > p && (p = (2147483647 & p) + 2147483648),p %= 1e6,p.toString() + "." + (p ^ m)}''')headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36', }self.session = requests.Session()self.session.get('https://fanyi.baidu.com', headers=headers)response = self.session.get('https://fanyi.baidu.com', headers=headers)self.token = re.findall("token: '(.*?)',", response.text)[0]self.gtk = '320305.131321201' # re.findall("window.gtk = '(.*?)';", response.text, re.S)[0]def translate(self, query, from_lang='en', to_lang='zh'):#语言检测self.session.post('https://fanyi.baidu.com/langdetect', data={'query': query})#单击事件 self.session.get('https://click.fanyi.baidu.com/?src=1&locate=zh&action=query&type=1&page=1')#翻译data = {'from': from_lang,'to': to_lang,'query': query,'transtype': 'realtime','simple_means_flag': '3','sign': self.js(query, self.gtk),'token': self.token}response =self.session.post('https://fanyi.baidu.com/v2transapi', data=data)json = response.json()if 'error' in json:pass#return 'error: {}'.format(json['error'])else:return response.json()['trans_result']['data'][0]['dst']
class baidu_SpeechRecognition():def __init__(self, dev_pid):#百度语音识别APISpeech_APP_ID = '19712136'Speech_API_KEY = 'Loo4KbNtagchc2BLdCnHEnZl'Speech_SECRET_KEY = 'DO4UlSnw7FzpodU2G3yXQSHLv6Q2inN8'self.dev_pid = dev_pidself.SpeechClient = AipSpeech(Speech_APP_ID, Speech_API_KEY, Speech_SECRET_KEY)self.TranslClient = baidu_Translate()def load_audio(self, audio_file):self.source = AudioSegment.from_wav(audio_file)def speech_recognition(self, offset, duration, fanyi):data = self.source[offset * 1000:duration * 1000].raw_dataresult = self.SpeechClient.asr(data, 'wav', 16000, {'dev_pid': self.dev_pid, })fanyi_text = ''if fanyi:try:fanyi_text = self.TranslClient.translate(result['result'][0])except:passtry:return [result['result'][0], fanyi_text]except:#print('错误:',result)return ['', '']
def cut_point(path, dbfs=1.25):sound = AudioSegment.from_file(path, format="wav")tstamp_list = detect_silence(sound, 600, sound.dBFS * dbfs, 1)timelist = []for i in range(len(tstamp_list)):if i == 0:back = 0else:back = tstamp_list[i - 1][1] / 1000timelist.append([back, tstamp_list[i][1] / 1000])min_len = 0.5max_len = 5result = []add = 0total = len(timelist)for x in range(total):if x + add < total:into, out = timelist[x + add]if out-into>min_len and out - into < max_len and x + add + 1 < total:add += 1out = timelist[x + add][1]result.append([into, out])elif out - into > max_len:result.append([into, out])else:breakreturn result
def cut_text(text, length=38):newtext = ''if len(text) > length:while True:cutA = text[:length]cutB = text[length:]newtext += cutA + '\n'if len(cutB) < 4:newtext = cutA + cutBbreakelif len(cutB) > length:text = cutBelse:newtext += cutBbreakreturn newtextreturn text
def progressbar(total, temp, text='&&', lenght=40): #定义进度栏content = '\r' + text.strip().replace('&&', '[{0}{1}]{2}%')percentage = round(temp / total * 100, 2)a = round(temp / total * lenght)b = lenght - aprint(content.format('■' * a, '□' * b, percentage), end='')
def format_time(seconds): #定义时间格式sec = int(seconds)m, s = divmod(sec, 60)h, m = divmod(m, 60)fm = int(str(round(seconds, 3)).split('.')[-1])return "%02d:%02d:%02d,%03d" % (h, m, s, fm)
def separate_audio(file_path, save_path): #定义音频间隔audio_file = save_path + '\\tmp.wav'audio = AudioFileClip(file_path)audio.write_audiofile(audio_file, ffmpeg_params=['-ar', '16000', '-ac', '1'], logger=None)return audio_file
def file_filter(path, alldir=False): #定义文件过滤key = ['mp4', 'mov']if alldir:dic_list = os.walk(path)else:dic_list = os.listdir(path)find_list = []for i in dic_list:if os.path.isdir(i[0]):header = i[0]file = i[2]for f in file:for k in key:if f.rfind(k) != -1:find_list.append([header, f])else:for k in key:if i.rfind(k) != -1:find_list.append([path, i])if find_list:find_list.sort(key=lambda txt: re.findall(r'\d+', txt[1])[0])return find_list
def countTime(s_time, now=True): #定义累计时间if now: s_time = (time.time() - s_time)m, s = divmod(int(s_time), 60)return '{}分{}秒'.format('%02d' % (m), '%02d' % (s))
def __line__print__(txt='-' * 10): #定义打印print('\n' + '-' * 10 + ' ' + txt + ' ' + '-' * 10 + '\n')
if __name__ == '__main__': #主函数def StartHandle(timeList, save_path, srt_mode=2, result_print=False):index = 0total = len(timeList)a_font = r'{\fn微软雅黑\fs14}'b_font = r'{\fn微软雅黑\fs10}'fanyi = False if srt_mode == 1 else Truefile_write = open(save_path, 'a', encoding='utf-8')for x in range(total):into, out = timelist[x]timeStamp = format_time(into - 0.2) + ' --> ' + format_time(out - 0.2)result = baidufanyi.speech_recognition(into + 0.1, out - 0.1, fanyi)if result_print:if srt_mode == 0:print(timeStamp, result[0])else:print(timeStamp, result)else:progressbar(total, x, '识别中...&& - {0}/{1}'.format('%03d' % (total), '%03d' % (x)), 44)if len(result[0]) > 1:index += 1text = str(index) + '\n' + timeStamp + '\n'if srt_mode == 0: #仅中文text += a_font + cut_text(result[1])elif srt_mode == 1: #仅英文text += b_font + cut_text(result[0])else: #中文+英文text += a_font + cut_text(result[1]) + '\n' + b_font + result[0]text = text.replace('\u200b', '') + '\n\n'file_write.write(text)file_write.close()if not result_print:progressbar(total, total, '识别中...&& - {0}/{1}'.format('%03d' % (total), '%03d' % (total)), 44)os.system('cls')wav_path = os.environ.get('TEMP')#语音模型pid_list = 1536, 1537, 1737, 1637, 1837, 1936#设置参数print('[ 百度语音识别字幕生成器 - by 谷健&任家旺 ]\n')__line__print__('1 模式选择')input_dev_pid = input('请选择识别模式:\n''\n (1)普通话,''\n (2)普通话+简单英语,''\n (3)英语,''\n (4)粤语,''\n (5)四川话,''\n (6)普通话-远场''\n\n请输入一个选项(默认3):')__line__print__('2 字幕格式')input_srt_mode = input('请选择字幕格式:\n''\n (1)中文,''\n (2)英文,''\n (3)中文+英文,''\n\n请输入一个选项(默认3):')__line__print__('3 实时输出')input_print = input('是否实时输出结果到屏幕? (默认:否/y:输出):').upper()#处理参数dev_pid = int(input_dev_pid) if input_dev_pid else 3dev_pid -= 1srt_mode = int(input_srt_mode) if input_srt_mode else 3srt_mode -= 1re_print = True if input_print == 'Y' else False#输入文件__line__print__('4 打开文件')input_file = input('请拖入一个文件或文件夹并按回车:').strip('"')video_file = []if not os.path.isdir(input_file):video_file = [input_file]else:file_list = file_filter(input_file)for a, b in file_list:video_file.append(a + '\\' + b)#执行确认select_dev = ['普通话', '普通话+简单英语', '英语', '粤语', '四川话', '普通话-远场']select_mode = ['中文', '英文', '中文+英文']__line__print__('5 确认执行')input('当前的设置:\n识别模式: {0}, 字幕格式: {1}, 输出结果: {2}\n当前待处理文件 {3} 个\n请按下回车开始处理...'.format(select_dev[dev_pid],select_mode[srt_mode],'是' if re_print else '否',len(video_file)))#批量处理total_file = len(video_file)total_time = time.time()baidufanyi = baidu_SpeechRecognition(pid_list[dev_pid])for i in range(total_file):item_time = time.time()file_name = video_file[i].split('\\')[-1]print('\n>>>>>>>> ...正在处理音频... <<<<<<<<', end='')audio_file = separate_audio(video_file[i], wav_path)timelist = cut_point(audio_file, dbfs=1.15)if timelist:print('\r>>>>>>>> 当前:{} 预计:{} <<<<<<<<'.format('%03d' % (i),countTime(len(timelist) * 5, now=False)))srt_name = video_file[i][:video_file[i].rfind('.')] + '.srt'baidufanyi.load_audio(audio_file)StartHandle(timelist, srt_name, srt_mode, re_print)print('\n{} 处理完成, 本次用时{}'.format(file_name, countTime(item_time)))else:print('音频参数错误')#执行完成input('全部完成, 处理了{}个文件, 全部用时{}'.format(total_file, countTime(total_time)))
系统测试
运行Python代码,根据提示进行交互选择。选择待识别视频语言,如图1所示;选择需要的字幕语言,如图2所示。
选择是否实时输出字幕结果,选择文件路径: (需要在英文输入法下使用双引号)确认需求,如图所示。
本次运行的设置:
识别模式英语(3),字幕格式为中文+英文(3)是否实时输出字幕为(y) 。结果:实时查看字幕输出,如图所示。
生成.srt字幕文件,如图所示。
在播放器中选择打开或关闭字幕,当生成多个字幕文件(如英文/中文/英文+中文)时也可在播放器中设置更换字幕文件。
使用记事本打开字幕文件,如图所示。
查看字幕文件加入视频的效果,原无字幕视频,如图所示。
加入生成字幕后的视频,如图所示。
工程源代码下载
详见本人博客资源下载页
其它资料下载
如果大家想继续了解人工智能相关学习路线和知识体系,欢迎大家翻阅我的另外一篇博客《重磅 | 完备的人工智能AI 学习——基础知识学习路线,所有资料免关注免套路直接网盘下载》
这篇博客参考了Github知名开源平台,AI技术平台以及相关领域专家:Datawhale,ApacheCN,AI有道和黄海广博士等约有近100G相关资料,希望能帮助到所有小伙伴们。
相关文章:

基于百度语音识别API智能语音识别和字幕推荐系统——深度学习算法应用(含全部工程源码)+测试数据集
目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理2. 翻译3. 格式转换4. 音频切割5. 语音识别6. 文本切割7. main函数 系统测试工程源代码下载其它资料下载 前言 本项目基于百度语音识别API,结合了语音识别、视频转换音频识别以及语句停顿…...

数字万用表测量基础知识--使用DMM测量电流
概览 DMM(即数字万用表)是一种电气测试和测量仪器,可测量直流和交流信号的电压、电流和电阻。本文介绍如何正确使用和理解数字万用表(DMM)。 使用DMM测量电流 另一个常见的测量功能是直流和交流电流测量。电压是通过与电路并联进行测量&am…...

【BASH】回顾与知识点梳理(二十)
【BASH】回顾与知识点梳理 二十 二十. 十六至十九章知识点总结及练习20.1 总结20.2 练习 该系列目录 --> 【BASH】回顾与知识点梳理(目录) 二十. 十六至十九章知识点总结及练习 20.1 总结 shell script 是利用 shell 的功能所写的一个『程序 (prog…...

Arduino驱动SGP40空气质量传感器(气体传感器篇)
目录 1、传感器特性 2、硬件原理图 3、控制器和传感器连线图 4、驱动程序 SGP40空气质量传感器是业内知名的瑞士公司Sensirion推出的新一代SGP40数字VOC传感器芯片。基于Sensirion的CMOSens技术,SGP40在单个芯片上提供了完整的传感器系统,包括温控微加热板和室内空气质量…...

识别和应对内存抖动
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、导读二、概览三、案例分析3.1 使用memory-profiler3.2 使用 cp…...

3.3用于共享数据保护的替代工具
用于共享数据保护的替代工具 虽然互斥元是最通用的机制,但提到保护共享数据时,它们并不是唯一的选择;还有别的替代品,可以在特定情况下提供更恰当的保护。 一个特别极端(但却相当常见)的情况,…...

探索数据之美:初步学习 Python 柱状图绘制
文章目录 一 基础柱状图1.1 创建简单柱状图1.2 反转x和y轴1.3 数值标签在右侧1.4 演示结果 二 基础时间线柱状图2.1 创建时间线2.2 时间线主题设置取值表2.3 演示结果 三 GDP动态柱状图绘制3.1 需求分析3.2 数据文件内容3.3 列表排序方法3.4 参考代码3.5 运行结果 一 基础柱状图…...

647. 回文子串
boolean默认类型是false class Solution {public int countSubstrings(String s) {if(s null) return 0;int result 0;int length s.length();boolean[][] dp new boolean[length][length];for(int j0;j<length;j){for(int i0;i<j;i){if(s.charAt(i) s.charAt(j)){i…...

cmake (更新中)
概述 关于 CMake CMake 是一个可扩展的开源系统,以一种与操作系统和编译器无关的方式来管理构建过程。与许多跨平台系统不同,CMake 被设计为与本机构建环境配合使用。在每个源代码目录中放置简单的配置文件(称为 CMakeLists.txt 文件…...

【go语言基础】指针数组和数组指针
1.概念 (1)指针数组: 存储指针的数组,也叫存储地址的数组,简单说就是存储地址的。 首先它是一个数组,数组中的元素都是指针(地址)。 (2)数组指针…...

ModaHub魔搭社区——Milvus Cloud向量数据库
向量数据库:在AI时代的快速发展与应用 摘要: 随着人工智能技术的不断进步,向量数据库在处理大规模数据方面发挥着越来越重要的作用。本文介绍了向量数据库的基本概念、应用场景和技术挑战,并详细阐述了Milvus Cloud作为典型的向量数据库产品的技术特点、性能优化和应用案例…...

【Java】常用Stream API
常见 Stream 流表达式 总体结构图 一、两大类型 中间操作(Intermediate Operations) 中间操作是指在Stream上执行的操作, 它们返回一个新的Stream, 允许你链式地进行多个中间操作. 终端操作(Terminal Operations) 对Stream进行最终处理的操作, 当调用终端操作时, Stream会开始执…...

P1941 [NOIP2014 提高组] 飞扬的小鸟
代码部分前有一千六百字了 P1941 [NOIP2014 提高组] 飞扬的小鸟 考察对背包 dp 算法过程理解的透彻性。过程透彻性也是解决所有问题的关键(建立在算法已学的基础上)。 n , m n,m n,m 的范围足够我们 O ( n m ) O(nm) O(nm) 的遍历整个地图。设 f i , …...

Vue3+Element plus+pageHelper实现分页
安装element plus npm install element-plus --save引入 修改main.js: import { createApp } from vue import App from ./App.vue import ElementPlus from element-plus import element-plus/dist/index.cssconst app createApp(App) app.use(ElementPlus) ap…...
外贸路上那些哭笑不得的事情
前几天一个老顾客在软件上联系,说自己上次的订货体验很满意,货物的质量很好,而且服务和回复也很及时, 比起他之前的供货商要好很多,他之前的供货商虽然货物的质量也很好,但是每次询问问题都是要等好久才给…...

双端列表 —— Deque 接口概述,使用ArrayDeque实现队列和双端队列数据结构
Deque接口简介 Deque译为双端队列,在双向都能作为队列来使用,同时可用作栈。Deque接口的方法是对称成比例的。 Deque接口继承Queue接口,因此具有Queue,Collection,Iterable的方法属性。 双端队列的工作原理 在常规队…...

构建可观测架构,从这5个方面着手
随着系统复杂度的提升,“可观测性”(Observability)成为架构建设的重要原则之一。那么构建一个可观测的系统架构需要做哪些工作呢?本文将从以下5个方面介绍构建可观测架构的主要考虑: 1.定义指标和度量,明确关键业务指标需求 首先要确定核心业务指标,比如请求响应…...

前端面试的性能优化部分(7)每天10个小知识点
目录 系列文章目录前端面试的性能优化部分(1)每天10个小知识点前端面试的性能优化部分(2)每天10个小知识点前端面试的性能优化部分(3)每天10个小知识点前端面试的性能优化部分(4)每天…...

【云原生】kubernetes中容器的资源限制
目录 1 metrics-server 2 指定内存请求和限制 3 指定 CPU 请求和限制 资源限制 在k8s中对于容器资源限制主要分为以下两类: 内存资源限制: 内存请求(request)和内存限制(limit)分配给一个容器。 我们保障容器拥有它请求数量的…...

java Long型数据返回到前端失进度问题解决
直接在springmvc配置中增加信息转换。亲测可用。简单粗暴 Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {MappingJackson2HttpMessageConverter jackson2HttpMessageConverter new MappingJackson2HttpMessageCo…...

【设计模式】-策略模式:优雅处理条件逻辑
Java 策略模式之优雅处理条件逻辑 前言 在软件开发中,我们经常会遇到根据不同的条件执行不同逻辑的情况。这时,策略模式是一种常用的设计模式,能够使代码结构清晰、易于扩展和维护。 本文将详细介绍策略模式的概念及其在Java中的应用&#x…...

SpringBoot整合多数据源
SpringBoot整合多数据源 在实际企业项目开发中,我们经常会在SpringBoot项目中配置多数据源,一方面可以减缓数据库压力,另一方面可以也是业务需求的场景 下面就来看看如何在SpringBoot项目中配置多数据源 POM 在配置多数据源之前ÿ…...

CLIP论文精度
CLIP论文精度 Zero-shot CLIP多模态模型 Image Endecoder是一个图片编码器,既可以是ResNet,也可以是Vision Transformer. Text Encoder和Image Encoder产生的两组特征进行对比学习(无监督训练) 分类头?“分类头” 是指网络结…...

LouvainMethod分布式运行的升级之路
1、背景介绍 Louvain是大规模图谱的谱聚类算法,引入模块度的概念分二阶段进行聚类,直到收敛为止。分布式的代码可以在如下网址进行下载。 GitHub - Sotera/spark-distributed-louvain-modularity: Spark / graphX implementation of the distri…...

【Node.js】低代码平台源码
一、低代码简介 低代码管理系统是一种通过可视化界面和简化的开发工具,使非专业开发人员能够快速构建和管理应用程序的系统。它提供了一套预先定义的组件和模块,使用户可以通过拖放操作来设计应用程序的界面和逻辑。低代码管理系统还提供了自动化的工作…...

docker 部署 xxl-job-admin
1、先安装mysql docker pull mysql 2、运行mysql 容器 ( 端口 3306 容器名称 mysql 密码 123456 ) docker run -d --name mysql -e MYSQL_ROOT_PASSWORD123456 -p 3306:3306 mysql 3、将tables_xxl_job.sql文件(官网地址:http…...

c++(空间配置器)[32]
空间配置器 一级空间配置器 || 二级空间配置器 默认先走二级然后判断 二级空间配置器 一个指针指向start_free然后start_free向后移动,相当于哈希桶的头删和头插 8byte:切大补小 C的二级空间配置器按照8字节(或者更大的倍数)切分…...

Linux系列之解压文件
一.欢迎来到我的酒馆 使用命令解压Linux文件。 目录 一.欢迎来到我的酒馆二.使用命令解压文件 二.使用命令解压文件 2.1解压 .tar.gz文件: tar -zxvf 文件名.tar.gz.tar,gz这种文件是tar文件的压缩文件,因此可以使用tar命令进行解压 -zxvf命令参数&…...

为什么重写equals方法时必须重写hashcode方法
与 equals的区别 如果两个引用类型变量使用运算符,那么比较的是地址,它们分别指向的是否是同一地址的对象,结果一定是false,因为两个对象地址必然不同。 不能实现比较对象的值是否相同。 所有对象都有equals方法,默认…...

java导入excel图片处理
直接看代码吧,主要逻辑吧excel的图片拿到 压缩上传获取url // 将文件转成XSSFWorkbook工作簿XSSFWorkbook wb new XSSFWorkbook(uploadFile);// 获取工作薄中第一个excel表格XSSFSheet sheet wb.getSheetAt(0);// 核心:::获取ex…...