Tabla de contenido
prefacio
Basado en la API de reconocimiento de voz de Baidu, este proyecto combina varias tecnologías, como el reconocimiento de voz, el reconocimiento de audio de conversión de video y el reconocimiento de segmentación de pausa de oración, para lograr una generación eficiente de subtítulos de video.
Primero, usamos la API de reconocimiento de voz de Baidu para convertir el audio en texto mediante el análisis del contenido del habla. Este paso nos permite extraer información textual significativa del habla.
En segundo lugar, utilizamos la tecnología de reconocimiento de audio de conversión de video para extraer la parte de audio del video y realizar la misma operación de reconocimiento de texto. De esta forma, podemos textualizar con precisión el contenido sonoro del vídeo.
Además, también presentamos el reconocimiento de segmentación de pausas de oraciones, que se utiliza para identificar los límites de las oraciones y las pausas en el habla, a fin de segmentar con mayor precisión el contenido de cada oración.
Combinando las técnicas anteriores, hemos realizado con éxito la generación de subtítulos de video. Al reconocer, convertir y segmentar el contenido de voz en el video cuadro por cuadro, podemos convertir con precisión el contenido de voz en texto y generar los subtítulos correspondientes en el video.
Este proyecto no solo proporciona subtítulos para contenido de video, sino que también brinda comodidad a los creadores de contenido, permitiéndoles transmitir mejor el contenido de video a las audiencias. Al mismo tiempo, esto también brinda una experiencia de visualización más amigable para los usuarios, incluidas las personas con discapacidad auditiva.
diseño general
Esta parte incluye el diagrama de estructura general del sistema y el diagrama de flujo del sistema.
Diagrama de estructura general del sistema
La estructura general del sistema se muestra en la figura.
Diagrama de flujo del sistema
El flujo del sistema se muestra en la figura.
entorno operativo
Complete la configuración requerida para Python 3 en el entorno de Windows y ejecute el código.
implementación del módulo
Este proyecto incluye 7 módulos: preprocesamiento de datos, traducción, conversión de formato, corte de audio, reconocimiento de voz, corte de texto y main
funciones. La introducción de funciones y los códigos relacionados de cada módulo se dan a continuación.
1. Preprocesamiento de datos
Obtenga el requerido APP_ID
, basado en Baidu Speech API . Ingrese al sitio web oficial de Baidu Voice en http://yuyin.baidu.com , haga clic en el botón "Consola" en la esquina superior derecha e inicie sesión en su cuenta de Baidu, como se muestra en la figura.API_KEY
SECRET_KEY
Haga clic en "Servicio de producto" - "Tecnología de voz" en el extremo izquierdo de la consola para ingresar a la interfaz de reconocimiento de voz, como se muestra en la figura.
Después de ingresar, es posible que se le indique que se requiere autenticación con nombre real, complete la información relevante y complete la autenticación.
Haga clic en "Crear aplicación", complete el nombre del proyecto, el tipo, la interfaz requerida, el nombre del paquete de voz, la descripción de la aplicación y otra información de acuerdo con los requisitos, y luego la creación será exitosa, como se muestra en la figura.
Haga clic en la figura a continuación para ver los detalles de la aplicación para obtener APP_ID
, API_KEY
y SECRET_KEY
para llamadas posteriores. En esta interfaz, también puede ver información como el límite de llamadas, como se muestra en las siguientes dos figuras.
Nota: Si el estado de la interfaz API está pendiente de activación, debe seleccionar la interfaz API que desea activar en la página "Descripción general" a la izquierda y activarla. Como se muestra abajo.
Este proyecto utiliza la interfaz API de reconocimiento de voz de Baidu, a la que se llama mediante los siguientes dos métodos, y finalmente se utiliza el último.
(1) Descargue y use el SDK
De acuerdo con la descarga de uso de la herramienta pip pip install baidu-aip
.
El código de llamada es:
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) No es necesario descargar SDK
Primero, ensamble el .url para obtener el token de acuerdo con el documento, segundo, procese el audio local y publíquelo en el servidor de reconocimiento de voz de Baidu en formato JSON para obtener el resultado devuelto.
#合成请求token的URL
url = baidu_server + "grant_type=" + grant_type + "&client_id=" + client_id + "&client_secret=" + client_secret
#获取token
res = urllib.request.urlopen(url).read()
data = json.loads(res.decode('utf-8'))
token = data["access_token"]
print(token)
Las operaciones relacionadas con la biblioteca necesarias para descargar la configuración son las siguientes:
(1) Instalar la biblioteca moviepy
Moviepy Biblioteca de Python para edición de video: corte, costura, inserción de títulos, composición de video, procesamiento de video. Las bibliotecas dependientes de moviepy incluyen numpy, imageio, decorator y tqdm.
Use el comando en cmd pip install moviepy
para instalar la biblioteca moviepy.
Posibles problemas durante la instalación: cuando se produce un error y la descarga y la instalación se detienen, verifique el mensaje de error y es posible que falte la biblioteca dependiente.
Si Python en Anaconda no instala tqdm y se produce un error, use conda list
Ver para confirmar que falta la biblioteca, que se puede conda install tqdm
descargar e instalar. Otros problemas de falta de biblioteca también se pueden resolver de manera similar.
(2) Instale la biblioteca js2py
Al rastrear, muchos sitios web utilizan la tecnología de cifrado js, y js2py puede ejecutar código Java en el entorno de Python para eliminar el cuello de botella del entorno de Java. Al hacer subtítulos en chino e inglés, se trata de la salida en inglés del reconocimiento de voz de Baidu, que debe traducirse al chino. Por lo tanto, instale el rastreador de bibliotecas is2py para llamar al script de JavaScript de la traducción de Baidu.
(3) Instale la biblioteca pydub
De acuerdo con el silencio del audio, detecte pausas en las oraciones y realice un reconocimiento de oraciones razonable. La biblioteca pydub se instala usando la herramienta pip y la entrada en la línea de comando cmd pip insall pydub
.
Use la biblioteca pydub) from pydub import AudioSegment
para verificar si la instalación es exitosa a través de la detección de rutina. Si se informa un error y no hay una biblioteca pydub, la instalación fallará.
2. Traducción
Use el rastreador para llamar a Baidu Translate para obtener los resultados en inglés reconocidos y obtener la traducción al chino correspondiente.
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. Conversión de formato
La API de reconocimiento de voz de Baidu tiene requisitos de parámetros estrictos, y la biblioteca moviepy se usa para completar el trabajo de extracción de audio de video.
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. Corte de audio
Use la biblioteca pydub, use la reducción de decibeles del audio cuando está en pausa como criterio para juzgar las oraciones, establezca el umbral de decibelios cuando está en pausa, y el audio pequeño después de la división no debe ser inferior a 0,5 s ni superior a 5 s .
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 = 0
else:
back = tstamp_list[i - 1][1] / 1000
timelist.append([back, tstamp_list[i][1] / 1000])
min_len = 0.5 #切割所得音频不短于0.5s,不长于5s
max_len = 5
result = []
add = 0
total = 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 += 1
out = timelist[x + add][1]
result.append([into, out])
elif out - into > max_len:
result.append([into, out])
else:
break
return result
5. Reconocimiento de voz
Llame a la API de reconocimiento de voz de Baidu para operar, complete la información obtenida al solicitar la aplicación, cargue el audio para ser reconocido, realice el reconocimiento de chino o inglés y devuelva el texto obtenido.
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_pid
self.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_data
result = 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:
pass
try:
return [result['result'][0], fanyi_text] #返回所得文本
except:
#print('错误:',result)
return ['', '']
6. Corte de texto
Segmentación, para evitar que demasiados textos en la misma pantalla afecten la percepción, configure 38 como umbral, cuando sea inferior a 38, se mostrará normalmente, si es mayor, se cortará y se mostrará en segmentos.
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 + cutB
break
elif len(cutB) > length:
text = cutB
else:
newtext += cutB
break
return newtext
return text
7. función principal
Permita que el módulo (función) se ejecute de forma independiente, construya la entrada para llamar a otras funciones y configure funciones interactivas simples. Los usuarios pueden elegir el tipo de idioma, el tipo de subtítulos y si agregar subtítulos directamente al video según sus necesidades, y pueden observe el progreso del trabajo actual y calcule los resultados. Lleva tiempo y se informa un error cuando el formato del archivo es incorrecto.
if __name__ == '__main__':
def StartHandle(timeList, save_path, srt_mode=2, result_print=False):
index = 0
total = len(timeList)
a_font = r'{\fn微软雅黑\fs14}' #中、英字幕字体设置
b_font = r'{\fn微软雅黑\fs10}'
fanyi = False if srt_mode == 1 else True
file_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 += 1
text = 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 3
dev_pid -= 1
srt_mode = int(input_srt_mode) if input_srt_mode else 3
srt_mode -= 1
re_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):
#百度语音识别API
Speech_APP_ID = '19712136'
Speech_API_KEY = 'Loo4KbNtagchc2BLdCnHEnZl'
Speech_SECRET_KEY = 'DO4UlSnw7FzpodU2G3yXQSHLv6Q2inN8'
self.dev_pid = dev_pid
self.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_data
result = 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:
pass
try:
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 = 0
else:
back = tstamp_list[i - 1][1] / 1000
timelist.append([back, tstamp_list[i][1] / 1000])
min_len = 0.5
max_len = 5
result = []
add = 0
total = 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 += 1
out = timelist[x + add][1]
result.append([into, out])
elif out - into > max_len:
result.append([into, out])
else:
break
return 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 + cutB
break
elif len(cutB) > length:
text = cutB
else:
newtext += cutB
break
return newtext
return 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 - a
print(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 = 0
total = len(timeList)
a_font = r'{\fn微软雅黑\fs14}'
b_font = r'{\fn微软雅黑\fs10}'
fanyi = False if srt_mode == 1 else True
file_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 += 1
text = 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 3
dev_pid -= 1
srt_mode = int(input_srt_mode) if input_srt_mode else 3
srt_mode -= 1
re_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)))
Prueba del sistema
Ejecute el código de Python y realice selecciones interactivas de acuerdo con las indicaciones. Seleccione el idioma del video a reconocer, como se muestra en la Figura 1; seleccione el idioma de subtítulos deseado, como se muestra en la Figura 2.
Seleccione si desea generar los resultados de los subtítulos en tiempo real, seleccione la ruta del archivo: (debe usar comillas dobles en el método de entrada en inglés) para confirmar los requisitos, como se muestra en la figura.
Configuración para esta ejecución:
El modo de reconocimiento es inglés (3), el formato de subtítulos es chino+inglés (3) si se emiten subtítulos en tiempo real (y). Resultado: vea la salida de subtítulos en tiempo real, como se muestra en la figura.
Genere un archivo de subtítulos .srt, como se muestra en la figura.
Seleccione para activar o desactivar los subtítulos en el reproductor. Al generar múltiples archivos de subtítulos (como inglés/chino/inglés+chino), también puede configurar y reemplazar los archivos de subtítulos en el reproductor.
Abra el archivo de subtítulos con el Bloc de notas como se muestra.
Vea el efecto de agregar archivos de subtítulos al video, el video original sin subtítulos, como se muestra en la figura.
Agregue el video después de generar los subtítulos, como se muestra en la figura.
Descarga del código fuente del proyecto
Consulte la página de descarga de recursos de mi blog para obtener más información.
Descarga de otra información
Si desea continuar aprendiendo sobre rutas de aprendizaje y sistemas de conocimiento relacionados con la inteligencia artificial, bienvenido a leer mi otro blog " Pesado | Ruta de aprendizaje de conocimiento básico de aprendizaje de inteligencia artificial completa, todos los materiales se pueden descargar directamente desde el disco de la red sin pagar atención a las rutinas "
Este blog se refiere a la conocida plataforma de código abierto de Github, la plataforma de tecnología de IA y expertos en campos relacionados: Datawhale, ApacheCN, AI Youdao y Dr. Huang Haiguang, etc. Hay alrededor de 100G de materiales relacionados, y espero ayuda a todos tus amigos.