摘要:本文將介紹如何使用錄音文件識別極速版給無字幕視頻自動生成字幕。
本文分享自華為云社區(qū)《利用錄音文件極速版為視頻生成字幕》,作者:戈兀。
引言
越來越多的人們使用抖音、B站等視頻app,記錄、分享日常生活,隨之互聯(lián)網(wǎng)上產(chǎn)生了大量的長、短視頻。字幕是影響視頻觀看體驗的重要因素。以日常分享為主的視頻創(chuàng)作者往往沒有時間為視頻制作字幕,在創(chuàng)作者發(fā)音不清楚的前提下,沒有字幕的視頻可能會讓觀眾困惑甚至產(chǎn)生理解偏差。而帶字幕的視頻讓觀眾有更好的觀看體驗,“一氣呵成”順暢地看完。
語音識別技術(Automatic Speech Recognition)是一種將人的語音轉(zhuǎn)換為文本的技術。隨著深度學習的發(fā)展,端到端語音識別技術也取得了巨大的突破。將原始的音頻數(shù)據(jù),經(jīng)過分幀、加窗、FFT等操作后,得到描述音頻在時、頻域信息的梅爾特征或是Fbank特征。將特征送入transformer等神經(jīng)網(wǎng)絡,輸出對應的文本信息。此外,由大量文本訓練的語言模型(language model)能夠糾正語音識別輸出文本不通順的問題,改善閱讀體驗。而熱詞技術也被用來解決語音識別的領域適配問題,如同音不同字。
本文將介紹如何使用錄音文件識別極速版給無字幕視頻自動生成字幕。
錄音文件識別極速版采用同步接口,利用GPU加速模型的推理過程。對于兩個小時內(nèi)的音、視頻文件,可以在1分鐘內(nèi)返回識別結(jié)果,滿足準實時字幕、音頻質(zhì)檢等對識別速度有要求的場景。感興趣的讀者可以點擊錄音文件識別極速版文檔,了解詳情。
注:本文同步發(fā)布至華為云AI Gallery Notebook,可以在AI Gallery上運行:利用錄音文件極速版為視頻生成字幕
原理講解
給無字幕視頻生成字幕,就是從視頻中的提取音頻流,將音頻流送入錄音文件識別極速版,得到識別文字,和對應的時間戳信息。然后將其轉(zhuǎn)換為視頻字幕文件格式,如srt文件。得到srt字幕文件后,在播放視頻時,載入字幕文件,就可以看到字幕了。
因此,整個流程如下:
1、利用ffmpeg工具,從視頻中提取音頻流
2、設置適合的參數(shù),使用錄音文件識別極速版,催音頻文件進行識別
3、對識別結(jié)果,包括文字和時間戳信息,進行處理,得到視頻字幕文件
4、將命名相同的視頻文件與 srt 文件放在同一目錄下,用播放器打開,即可得到有字幕的視頻?;蛘呃胒fmpeg,以硬字幕的形式,將字幕嵌入到視頻中。
注:SRT(SubRip 文件格式)是以 SubRip 文件格式保存的簡單字幕文件,擴展名為 .srt。每個字幕在 SRT 文件中有四個部分:
- 指示字幕編號或位置的數(shù)字計數(shù)器;
- 字幕的開始和結(jié)束時間;
- 一行或多行的字幕文本;
- 表示字幕結(jié)束的空行。
代碼開發(fā)
步驟一:提取音頻流
采用ffmpeg從視頻文件中提取音頻流,并保存為音頻文件output.wav
ffmpeg -i input.mp4 -ar 16000 -ac 1 output.wav
-ar指定保存音頻文件的采樣率,這里16000表示1秒鐘,保存16000個采樣點數(shù)據(jù);-ac指定保存音頻的通道數(shù),這里1表示保存為單通道音頻。
步驟二:安裝語音識別python SDK
在安裝python3后,用pip安裝其他依賴依賴包
pip install setuptools
pip install requests
pip install websocket-client
下載最新版python sdk源碼:https://sis-sdk-repository.obs.cn-north-1.myhuaweicloud.com/python/huaweicloud-python-sdk-sis-1.8.1.zip
進入下載的Python SDK目錄,在setup.py所在層目錄執(zhí)行 python setup.py install 命令,完成SDK安裝。
步驟三:調(diào)用錄音文件極速版
- 導入依賴包
from huaweicloud_sis.client.flash_lasr_client import FlashLasrClient from huaweicloud_sis.bean.flash_lasr_request import FlashLasrRequest from huaweicloud_sis.exception.exceptions import ClientException from huaweicloud_sis.exception.exceptions import ServerException from huaweicloud_sis.bean.sis_config import SisConfig import json
- 初始化客戶端
config = SisConfig() config.set_connect_timeout(50) config.set_read_timeout(50) client = FlashLasrClient(ak=ak, sk=sk, region=region, project_id=project_id, sis_config=config)
- 構造請求
asr_request = FlashLasrRequest() asr_request.set_obs_bucket_name(obs_bucket_name) # 設置存放音頻的桶名,必選 asr_request.set_obs_object_key(obs_object_key) # 設置OBS桶中的對象的鍵值,必選 asr_request.set_audio_format(audio_format) # 音頻格式,必選 asr_request.set_property(property) # property,比如:chinese_16k_conversation asr_request.set_add_punc('yes') asr_request.set_digit_norm('no') asr_request.set_need_word_info('yes') asr_request.set_first_channel_only('yes')
為視頻產(chǎn)生字幕文件時,不僅需要文字,也需要文字對應的時間戳信息。當一句話過長,屏幕無法完整顯示時,就需要對這句話進行切分。因此,僅僅根據(jù)每個句子的起始和截止時間,無法準確的確定切分后兩句話的起始和截止時間。因此我們需要字級別的時間信息。而將need_word_info配置為‘yes’,就可以輸出字級別的時間戳信息。如下:
"word_info": [ { "start_time": 590, "word": "哎", "end_time": 630 }, { "start_time": 830, "word": "大", "end_time": 870 }, { "start_time": 950, "word": "家", "end_time": 990 }, { "start_time": 1110, "word": "好", "end_time": 1150 }, ]
- 接下里發(fā)送識別請求
result = client.get_flash_lasr_result(asr_request)
- 拿到帶有詳細時間戳信息的識別結(jié)果result:
"result": { "score": 0.9358551502227783, "word_info": [ { "start_time": 590, "word": "哎", "end_time": 630 }, { "start_time": 830, "word": "大", "end_time": 870 }, { "start_time": 950, "word": "家", "end_time": 990 }, { "start_time": 1110, "word": "好", "end_time": 1150 }, { "start_time": 1750, "word": "我", "end_time": 1790 }, { "start_time": 1910, "word": "是", "end_time": 1950 }, { "start_time": 2070, "word": "你", "end_time": 2110 }, { "start_time": 2190, "word": "們", "end_time": 2230 }, { "start_time": 2350, "word": "的", "end_time": 2390 }, { "start_time": 2870, "word": "音", "end_time": 2910 }, { "start_time": 3030, "word": "樂", "end_time": 3070 }, { "start_time": 3190, "word": "老", "end_time": 3230 }, { "start_time": 3350, "word": "師", "end_time": 3390 }, { "start_time": 3590, "word": "康", "end_time": 3630 }, { "start_time": 3750, "word": "老", "end_time": 3790 }, { "start_time": 3950, "word": "師", "end_time": 3990 }, { "start_time": 4830, "word": "那", "end_time": 4870 }, { "start_time": 4990, "word": "么", "end_time": 5030 }, { "start_time": 5350, "word": "這", "end_time": 5390 }, { "start_time": 5550, "word": "幾", "end_time": 5590 }, { "start_time": 5750, "word": "系", "end_time": 5790 }, { "start_time": 5870, "word": "列", "end_time": 5910 }, { "start_time": 6070, "word": "呢", "end_time": 6110 }, { "start_time": 6310, "word": "我", "end_time": 6350 }, { "start_time": 6390, "word": "們", "end_time": 6470 }, { "start_time": 6510, "word": "來", "end_time": 6550 }, { "start_time": 6670, "word": "到", "end_time": 6710 }, { "start_time": 6830, "word": "了", "end_time": 6870 }, { "start_time": 7430, "word": "發(fā)", "end_time": 7470 }, { "start_time": 7630, "word": "聲", "end_time": 7670 }, { "start_time": 7830, "word": "練", "end_time": 7870 }, { "start_time": 8030, "word": "習", "end_time": 8070 }, { "start_time": 8950, "word": "三", "end_time": 8990 }, { "start_time": 9190, "word": "十", "end_time": 9230 }, { "start_time": 9350, "word": "五", "end_time": 9390 }, { "start_time": 9470, "word": "講", "end_time": 9510 } ], "text": "哎,大家好,我是你們的音樂老師康老師。那么這幾系列呢,我們來到了發(fā)聲練習三十五講。" }, "start_time": 510, "end_time": 9640 }
步驟四:將識別結(jié)果轉(zhuǎn)為srt字幕格式文件
由于視頻播放界面的寬度有限,當一句話包含的文字數(shù)過多時,會存在一行放不下的問題。因此我們在生成srt文件時,需要將文字數(shù)量過長的一句話切分為兩句話,分別在不同的時間段顯示。企切分后的第一句話的起始時間不變,截止時間為最后一個字的截止時間;第二句話的起始時間為第一個字的起始時間,截止時間不變。這樣就保證切分后兩句話的時間戳也是正確的,進而在合適的視頻幀中顯示正確的文本內(nèi)容。
def json2srt(json_result): results = "" count = 1 max_word_in_line = 15 min_word_in_line = 3 punc = ["。", "?", "!", ","] segments = json_result['flash_result'][0]['sentences'] for i in range(len(segments)): current_result = segments[i] current_sentence = current_result["result"]["text"] if len(current_result["result"]["word_info"]) > max_word_in_line: srt_result = "" srt_result_len = 0 current_segment = "" cnt = 0 start = True for i in range(len(current_sentence)): if current_sentence[i] not in punc: if start: start_time = current_result["result"]["word_info"][cnt]['start_time'] start = False else: end_time = current_result["result"]["word_info"][cnt]['end_time'] current_segment += current_sentence[i] srt_result_len += 1 cnt += 1 else: if srt_result_len < min_word_in_line: srt_result += current_segment + current_sentence[i] current_segment = "" else: srt_result += current_segment + current_sentence[i] current_segment = "" start_time = time_format(start_time) end_time = time_format(end_time) if srt_result[-1] == ",": srt_result = srt_result[:-1] results += str(count) + "\n" + start_time + "-->" + end_time + "\n" + srt_result + "\n" + "\n" count += 1 start = True srt_result = "" else: start_time = time_format(current_result["start_time"]) end_time = time_format(current_result["end_time"]) if current_sentence[-1] == ",": current_sentence = current_sentence[:-1] results += str(count) + "\n" + start_time + "-->" + end_time + "\n" + current_sentence + "\n" + "\n" count += 1 return results
得到srt格式的字幕文件
步驟五:播放視頻,載入字幕
修改文件名,保證srt文件和原始視頻文件命名相同,然后用播放器播放視頻:
步驟六:使用ffmpeg給視頻添加硬字幕(可選)
ffmpeg -i input.mp4 -vf subtitles=subtitle.srt output_srt.mp4
注:?硬字幕是將字幕渲染到視頻的紋理上,然后將其編碼成獨立于視頻格式的一個完整視頻。硬字幕與視頻是一個整體,不能更改或刪除。
?文章來源:http://www.zghlxwxcb.cn/news/detail-458699.html
點擊關注,第一時間了解華為云新鮮技術~文章來源地址http://www.zghlxwxcb.cn/news/detail-458699.html
到了這里,關于教你1分鐘搞定2小時字幕的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!