Sistema inteligente de reconocimiento de voz y recomendación de subtítulos basado en la API de reconocimiento de voz de Baidu: aplicación de algoritmo de aprendizaje profundo (incluido todo el código fuente del proyecto) + conjunto de datos de prueba


inserte la descripción de la imagen aquí

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.

inserte la descripción de la imagen aquí

Diagrama de flujo del sistema

El flujo del sistema se muestra en la figura.

inserte la descripción de la imagen aquí

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 mainfunciones. 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_KEYSECRET_KEY

inserte la descripción de la imagen aquí

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.

inserte la descripción de la imagen aquí

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.

inserte la descripción de la imagen aquí

Haga clic en la figura a continuación para ver los detalles de la aplicación para obtener APP_ID, API_KEYy SECRET_KEYpara 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.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

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.

inserte la descripción de la imagen aquí

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 moviepypara 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 listVer para confirmar que falta la biblioteca, que se puede conda install tqdmdescargar 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 AudioSegmentpara 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.

inserte la descripción de la imagen aquí

Figura 1 Vídeo a reconocer

inserte la descripción de la imagen aquí

Figura 2 Idioma de los subtítulos

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.

inserte la descripción de la imagen aquí

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.

inserte la descripción de la imagen aquí

Genere un archivo de subtítulos .srt, como se muestra en la figura.

inserte la descripción de la imagen aquí

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.

inserte la descripción de la imagen aquí

Vea el efecto de agregar archivos de subtítulos al video, el video original sin subtítulos, como se muestra en la figura.

inserte la descripción de la imagen aquí

Agregue el video después de generar los subtítulos, como se muestra en la figura.

inserte la descripción de la imagen aquí

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.

Supongo que te gusta

Origin blog.csdn.net/qq_31136513/article/details/132205049
Recomendado
Clasificación