本文正在参与「金石计划 . 分割6万现金大奖」
布景
语音辨认的干流言语中文、英文等开源语料库都很丰厚,比方说:THCHS-30、Aishell、LibriSpeech等。可是许多的国家地区的开源语料库却很少,比方:巴基斯坦、巴西、重庆话等。首要对产生这种问题的原因进行简略的剖析:语料库需求很大的人力成本需求专人去录制和标示,一般大点的语料库都是上千小时非常费时费力。那作为一个底层人员咱没钱又想整个稍微靠谱点的当当地言语料库咋整呢?
办法&思路
我就简略的构思了一下,这不短视频年代的到来了吗?Tiktok、抖音、B站等一系列短视频平台都有各种当地人群发布当当地言视频并且配字幕的。我就揣摩啊,一个视频里边字幕也有音频也有我是不是能够从里边把这个东西弄出来?说干就干,下面是我不成熟的思路:
1. 我的方针:获取字幕和对应音频
2. 判断音频开端和完毕,一般一个视频的音频和字幕为了让观众看的顺畅,在时刻上都是有对应关系。我只需求判断相同字幕开端视频帧和完毕视频帧就ok了。
3. 字幕辨认这个便是一个OCR(Optical Character Recognition,光学字符辨认),简略来说便是在视频帧上面找字然后转录成文字。
4. 最后把得到的字幕保存在抄本(Transcript.txt)文件里边,其他的以.wav方式保存
上面这个图便是大约的思路图。
完成代码
头文件导入:给大家解释一下我用的这个ocr是啥,这个是来自github上的一个开源OCR代码,这儿是链接。环境要是不会建立的话,下期再出个环境建立。
import os
from ocr import ocr
import time
import cv2
import tqdm
from moviepy.editor import *
视频流处理代码:这儿的代码是辨认每一帧的字幕,可是只保存不同文字的字幕,一起回来一帧所占时长T、字幕帧序号 time_index以及字幕data。
def video_proc(video_path):
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS) # 获取视频帧率
data = [] # 保存字幕
time_index = [] #
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 视频帧长
print('帧长:', frame_count)
for i in tqdm.tqdm(range(frame_count)): # 遍历视频一切帧
ret, frame = cap.read() # 读取每一帧,回来ret=True;frame=帧
# 当帧为Nonetype 便是没得视频的时分就完毕
if frame is None:
break
result, image_framed = ocr(frame) # 读取帧中的中英文字
if result != {}: # {}这个符号便是代表了空字典
time_index.append(i + 1)
for key in result: # 遍历字典获取结果
caption = result[key][1]
if caption not in data:
data.append(caption)
cap.release() # 开释摄像头
T = 1/fps # 获取每一帧单位时刻(s)
return data, time_index, T
视频裁剪以及音频转化代码:这儿的代码便是以字幕帧序号 time_index改变得到的时刻戳time_Stamp、视频保存途径video_path和声音存储途径voice_dir作为输入,最后得到别离后的音频文件。
def video_clip(video_path, voice_dir, time_Stamp):
print('正在出产音频数据...')
for key in time_Stamp:
voice_name = key+'.wav' # 音频姓名
video = VideoFileClip(video_path).subclip(time_Stamp[key][0], time_Stamp[key][1])
audio = video.audio
voice_path = os.path.join(voice_dir, voice_name) # 保存音频文件途径
audio.write_audiofile(voice_path) # 写入一个音频文件
抄本生成代码:这儿便是生成字幕文件的当地,因为作为抄本需求音频姓名和内容有一一对应关系,所以里边的内容是音频文件名1 字幕1\n 音频文件名2 字幕2\n…的方式。
def trans_txt_generate(caption_data, voice_dir, time_Stamp):
txt_name = 'transcript.txt'
txt_path = os.path.join(voice_dir, txt_name)
f = open(txt_path, 'a+')
i = 0
print('正在生成文本数据...')
for key in time_Stamp:
content = key + ' ' + caption_data[i] + '\n'
f.write(content)
i += 1
f.close()
最后的执行代码
if __name__ == '__main__':
t = time.time() # 开端时刻
video_path = '44.mp4'
voice_dir = './test_dataset'
caption_data, wrd_time_index, T = video_proc(video_path)
print(caption_data)
print('时刻序号:', wrd_time_index)
time_Stamp = {} # 保存时刻戳
left = wrd_time_index[0]
for i in range(1, len(wrd_time_index)):
sub = wrd_time_index[i]-wrd_time_index[i-1]
if sub != 1:
right = wrd_time_index[i-1]
time_Stamp['time_stamp%d' % (i+1)] = (left*T, right*T)
left = wrd_time_index[i]
video_clip(video_path, voice_dir, time_Stamp) # 裁剪视频并保存音频
trans_txt_generate(caption_data, voice_dir, time_Stamp) # 获取文本数据
print('空白时刻戳', time_Stamp)
# print('时刻序号长度:', len(tmp_time_index))
print('一共用时:', time.time()-t) # 一共用时
总结
我这个不成熟的主意其实还有许多吐槽的当地,比方:视频获取得到应该一样的字幕的那段时刻,可能他们每一帧字幕不一样。产生的原因:可能是ocr辨认准确度不太行(辨认错)、视频自身的视频帧有问题。今后估计还会改善吧。