内向基金完成首轮募资
06-17
试想一下,当我们在观看视频时,如果字幕缺失,观看体验会不会大打折扣?近年来,短视频、直播等在线娱乐方式快速发展,直接刺激了旅游、电商、影视创作等行业新趋势。要呈现出好的视频效果,不仅考验良好的拍摄技术,后期处理也是重中之重。
以视频字幕为例。有字幕的视频总能流畅观看,而没有字幕的视频总感觉缺少了某种韵味。
事实上,纯手工添加字幕既费时又费力。面对长时间、批量的字幕处理,多少有些苦不堪言。
那么有没有更智能的方法呢?接下来,本文将分享如何使用录音文件识别服务为无字幕的视频自动生成字幕。 1.分析研究对无字幕的视频自动生成字幕。
其实就是先对视频文件导出的音频文件进行识别,得到识别出的文本,然后根据识别出的文本和短句的时间信息对视频srt字幕文件进行处理。在视频中将srt字幕文件导入到文件中即可得到效果。
实现思路如下: 1、使用ffmpeg从视频中提取音频 2、调用录音文件识别服务识别音频文件 3、对识别出的文本和短句的时间信息进行处理,得到视频srt字幕文件4、将同一个视频文件和srt文件命名在同一目录下,用暴风影音或者其他播放器打开即可得到带字幕的视频。二、代码开发 1、用ffmpeg从视频中提取音频的项目使用了ffmpeg依赖,需要先下载并安装,并设置环境变量。
之后就可以引入subprocess库,执行ffmpeg命令,启动一个新进程,完成音频提取。代码语言: javascript copy import subprocessdef extract_audio(video, tmpAudio):ret = subprocess.run('ffmpeg -version', shell=True)if ret.returncode != 0:print("请先安装 ffmpeg 依赖项并设置环境变量")returnret = subprocess.check_call(['ffmpeg', '-i', video, '-vn', '-ar', "0", tmpAudio], shell=False)if ret.returncode != 0 :打印(“错误:”,ret)2。
识别音频文件。我这里选择的录音文件识别服务是腾讯云ASR的录音文件识别。
通过研究,腾讯云的录音文件识别可以直接根据通话时的语句进行识别。智能断句、停顿时添加标点符号,无需调用其他接口进行分句。
同时,返回的结果数据也可以根据不同的需求进行选择,比如是否过滤脏词、是否过滤情态粒子等,具体的服务细节这里不再赘述。具体请参考官方文档和腾讯云ASR。
(1)访问腾讯云服务,需要SecertId和SecretKey。 API key可以在API key管理页面创建和查询,并可以稍后在config文件中进行配置。
作者的项目配置在tencent/config.py。代码语言:javascript copy class Config(object):OUTPUT_PATH = '/XXX/video-srt/audio/' #输出文件目录 APP_ID = '******' # 对应上面的 APPIDSECRET_ID = '***** *' # 对应上面的 SecretIdSECRET_KEY = '******' # 对应上面的 SecretKey (2) 使用官网提供的 sdk 找到腾讯云语音识别服务下录音文件识别的 API 文档,滑动到底部并找到开发者资源。
这里我选择调用Python SDK。可以看到录音文件识别是一个异步服务。
您可以通过CreateRecTask接口发送录音文件识别请求,然后通过DescribeTaskStatus接口查询识别结果。在笔者的项目中,函数create_rec和函数query_rec_task分别封装了CreateRecTask接口和DescribeTaskStatus接口。
详细介绍如下: CreateRecTask:除了需要的EngineModelType(引擎模型类型)、ChannelNum(识别通道数)、ResTextFormat(识别结果返回形式)、SourceType(语音数据源)等参数外,请求时,可以根据需要传入FilterDirty(是否过滤脏词)、FilterModal(是否过滤模态粒子)等参数。请求成功后,会返回RequestId、TaskId等信息。
代码语言:javascript copy def create_rec(engine_type, file_url):client = create_client(Config.SECRET_ID, Config.SECRET_KEY)req = models.CreateRecTaskRequest()params = {"ChannelNum": 1, "ResTextFormat": 2, "SourceType" : 0, "ConvertNumMode": 1}req._deserialize(params)req.EngineModelType = engine_typereq.Url = file_urltry:resp = client.CreateRecTask(req)logger.info(resp)requesid = resp.RequestIdtaskid = resp.Data.TaskIdreturn requesid, taskid except Exception as err:logger.info(traceback.format_exc())return None, None 这里有两个参数需要注意:一个是ResTextFormat。识别结果的返回形式有3种。
这里,作者后续生成srt文件时,也根据单句识别结果的标点符号进行了一层分离,所以我选择了“词级粒度的详细识别结果(包括标点符号、语速值)”如果不需要额外进行一层分割,直接使用“识别结果文本(含分段时间戳)”格式即可。第二个是 SourceType。
语音数据有两个来源,即语音URL和语音数据(帖子正文)。笔者这里选择的是语音URL。
具体实现是将本地音频上传到腾讯云的cos存储桶中,语音URL是固定的。地址+音频文件名即可调用。
还可以通过其他方式获取音频URL。代码语言: javascript copy import subprocessdef upload_file(tmpAudio): objectName = tmpAudio.split('/')[-1]ret = subprocess.run(['coscmd', '-s', 'upload', tmpAudio, objectName] , shell=False)if ret.returncode != 0:print("error:", ret)描述TaskStatus:请求时需要传入TaskId。
请求成功后,将返回RequestId和识别结果。代码语言: javascript copy def query_rec_task(taskid):client = create_client(Config.SECRET_ID, Config.SECRET_KEY)req = models.DescribeTaskStatusRequest()params = '{"TaskId":' + str(taskid) + '}'req. from_json_string(params)result = ""while True:try:resp = client.DescribeTaskStatus(req)resp_json = resp.to_json_string()logger.info(resp_json)resp_obj = json.loads(resp_json)if resp_obj["Data"][ "StatusStr"] == "成功":result = resp_obj["Data"]["ResultDetail"]breakif resp_obj["Data"]["Status"] == 3:return False, ""time.sleep(1) except TencentCloudSDKException as err:logger.info(err)return False, ""return True, result这里作者会根据ResultDetail信息生成srt文件,所以函数query_rec_task的返回值就是query_rec_task返回的数据中的ResultDetail描述任务状态接口。
3.对识别结果进行处理,生成srt字幕文件。除了根据调用接口已经自动分词的句子来标记时间之外,笔者这里生成的srt文件,当自动分词的句子长度较长时,还会结合当前句子的标点符号。
ResultDetail中的OffsetEndMs、StartMs、EndMs等信息将句子重新划分,避免一行显示过多字幕。代码语言:javascript copy def to_srt(src_txt):flag_word = [".", "?", "!", ","]basic_line = 15srt_txt = ""count = 1 for i in range(len(src_txt)): current_sentence = src_txt[i]["FinalSentence"] last_time = ms_to_hours(src_txt [i]["StartMs"]) len_rec = len(current_sentence) if len_rec > basic_line: start_rec = 0 last_time = ms_to_hours(src_txt[i]["StartMs"]) while(len_rec > basic_line): flag = True for j in flag_word: if j in current_sentence[start_rec:start_rec+basic_line]: loc_rec = current_sentence.index(j, start_rec, start_rec+basic_line) + 1 flag = False 中断 if flag: loc_rec = start_rec + basic_line current_txt = current_sentence[start_rec:loc_rec] + "\n" 开始时间= last_time end_time = ms_to_hours(src_txt[i]["Words"][loc_rec]["OffsetEndMs"]+src_txt[i]["StartMs"]) if current_sentence[start_rec:] != "" and current_sentence[start_rec:] != 无: srt_txt = srt_txt + str(count) + "\n" + start_time + "-->" + end_time + "\n" + current_txt + "\n" count += 1 start_rec = loc_rec last_time = end_time len_rec = len(current_sentence[loc_rec:]) current_txt = current_sentence[start_rec:] + "\n" start_time = last_time end_time = ms_to_hours(src_txt[i]["EndMs"]) 如果 current_sentence[start_rec:] != "" 且 current_sentence [start_rec:] != 无: srt_txt = srt_txt + str(count) + "\n" + start_time + "-->" + end_time + "\n&” + current_txt + "\n" 计数 += 1 否则: start_time = last_time end_time = ms_to_hours(src_txt[i]["EndMs"]) srt_txt = srt_txt + str(count) + "\n" + start_time + "- -> " + end_time + "\n" + current_sentence + "\n"+"\n" count += 1return srt_txt 这里srt文件最终生成的位置与Config文件中的OUTPUT_PATH有关 4.获取带字幕的视频。
(1)原始视频文件的名称必须与srt文件相同(2)选择打开方式(3)带字幕的视频至此,为不带字幕的视频生成字幕就已经实现了。完整的项目代码放在附录中,除了修改了一些配置。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-17
06-17
06-17
06-17
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用