要約: この記事では、録画ファイル認識高速バージョンを使用して、字幕なしのビデオに字幕を自動的に生成する方法を紹介します。
この記事は、HUAWEI CLOUD コミュニティ「録画ファイルの高速バージョンを使用してビデオの字幕を生成する」(著者: Ge Wu) から共有されたものです。
序章
Douyin や Station B などのビデオ アプリを使用して日常生活を記録し共有する人が増えており、インターネット上には長尺および短尺のビデオが多数登場しています。字幕はビデオ視聴体験に影響を与える重要な要素です。日常的な共有に重点を置いている動画クリエイターは、動画に字幕を付ける時間がない場合が多く、クリエイターの発音が不明瞭であることを前提として、字幕なしの動画は視聴者を混乱させたり、誤解を招いたりする可能性があります。また、字幕付きのビデオにより、視聴者はより良い視聴体験を得ることができ、スムーズに「一気に」視聴することができます。
自動音声認識(Automatic Speech Recognition)は、人間の音声をテキストに変換する技術です。ディープラーニングの発展により、エンドツーエンドの音声認識技術は大きな進歩を遂げました。元の音声データにフレーミング、ウィンドウ処理、FFT などの演算を施した後、時間領域と周波数領域で音声情報を記述するメル特徴量または Fbank 特徴量が得られます。特徴量をトランスフォーマーなどのニューラルネットワークに送信し、対応するテキスト情報を出力します。さらに、大量のテキストによってトレーニングされた言語モデル (言語モデル) により、音声認識出力テキストが滑らかではないという問題が修正され、読書体験が向上します。ホットワード技術は、発音の違いなど、音声認識のドメイン適応問題を解決するためにも使用されます。
この記事では、Recording File Recognition Express を使用して、字幕なしのビデオに字幕を自動的に生成する方法を紹介します。
録音ファイル認識 Extreme Edition は同期インターフェイスを採用し、GPU を使用してモデルの推論プロセスを高速化します。2 時間以内の音声およびビデオ ファイルの場合、認識結果は 1 分以内に返されるため、準リアルタイム字幕、音声品質検査、および認識速度が必要なその他のシナリオの要件を満たします。興味のある読者は、記録ファイルをクリックして、スピード バージョンのドキュメントを確認して詳細を確認してください。
注: この記事は Huawei Cloud AI Gallery Notebook に同期的に公開され、AI Gallery で実行できます:録画ファイルの高速バージョンを使用してビデオの字幕を生成する
原理説明
字幕なしビデオの字幕を生成するには、ビデオからオーディオ ストリームを抽出し、そのオーディオ ストリームを録画ファイルに送信して高速バージョンを識別し、認識されたテキストと対応するタイムスタンプ情報を取得します。次に、srt ファイルなどのビデオ字幕ファイル形式に変換します。srt 字幕ファイルを取得した後、ビデオを再生するときに字幕ファイルを読み込むと、字幕が表示されます。
全体の流れは次のようになります。
1. ffmpeg ツールを使用してビデオからオーディオ ストリームを抽出します
2. 適切なパラメータを設定し、録音ファイルを使用して速度バージョンを識別し、オーディオ ファイルに識別を求めるプロンプトを表示します。
3. テキストとタイムスタンプ情報を含む認識結果を処理して、ビデオ字幕ファイルを取得します
4. 同じ名前のビデオ ファイルと srt ファイルを同じディレクトリに置き、プレーヤーで開くと、字幕付きのビデオを取得できます。または、ffmpeg を使用して、ハード字幕の形式でビデオに字幕を埋め込みます。
注: SRT (SubRip ファイル形式) は、拡張子 .srt を持つ SubRip ファイル形式で保存された単純な字幕ファイルです。各サブタイトルには、SRT ファイル内に 4 つのセクションがあります。
- 字幕番号または位置を示すデジタルカウンター。
- 字幕の開始時間と終了時間。
- 1 行以上の字幕テキスト。
- 字幕の終わりを示す空白行。
コード開発
ステップ 1: オーディオ ストリームを抽出する
ffmpeg を使用してビデオ ファイルからオーディオ ストリームを抽出し、オーディオ ファイル output.wav として保存します。
ffmpeg -i input.mp4 -ar 16000 -ac 1 output.wav
-ar はオーディオ ファイルを保存するためのサンプリング レートを指定します (16000 は 1 秒を意味し、16000 のサンプリング ポイント データを保存します)。 -ac はオーディオを保存するためのチャネル数を指定します (1 はシングル チャネル オーディオとして保存することを意味します)。
ステップ 2: 音声認識 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 が配置されているレイヤー ディレクトリで python setup.py install コマンドを実行して、SDK のインストールを完了します。
ステップ 3: 録音ファイルに Express Edition を呼び出します。
- 依存関係をインポートする
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')
動画の字幕ファイルを生成する場合、テキストだけでなく、テキストに対応するタイムスタンプ情報も必要となります。文が長すぎて画面に完全に表示できない場合は、文を分割する必要があります。したがって、各文の開始時間と終了時間のみに基づいて、分割後の 2 つの文の開始時間と終了時間を正確に決定することはできません。したがって、単語レベルでの時間情報が必要になります。そして、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
},
]
- 次に、本人確認リクエストを送信します
result = client.get_flash_lasr_result(asr_request)
- 詳細なタイムスタンプ情報を含む認識結果結果を取得します。
"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": "发",
"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": "哎,大家好,我是你们的音乐老师康老师。那么这几系列呢,我们来到了发声练习三十五讲。"
},
"start_time": 510,
"end_time": 9640
}
ステップ 4: 認識結果を srt 字幕形式ファイルに変換する
ビデオ再生インターフェイスの幅には制限があるため、文章に文字数が多すぎると、1 行に収まらない問題が発生します。そのため、srt ファイルを生成する際には、テキストが長すぎる文を 2 つの文に分割し、異なる時間帯で表示する必要があります。企業分割後の最初の文の開始時間は変更されず、カットオフ時間は最後の単語のカットオフ時間、2 番目の文の開始時間は最初の単語の開始時間、カットオフ時間はオフタイムは変わりません。このようにして、最後の 2 つの文のタイムスタンプも正しいことが保証され、正しいテキスト コンテンツが適切なビデオ フレームに表示されます。
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形式の字幕ファイルを取得する
ステップ 5: ビデオを再生して字幕を読み込む
ファイル名を変更して srt ファイルと元のビデオ ファイルの名前が同じになるようにし、プレーヤーを使用してビデオを再生します。
ステップ 6: ffmpeg を使用してビデオにハード字幕を追加します (オプション)
ffmpeg -i input.mp4 -vf subtitles=subtitle.srt output_srt.mp4
注: ハード字幕はビデオのテクスチャにレンダリングされ、ビデオ形式に関係なく完全なビデオにエンコードされます。ハード字幕はビデオの不可欠な部分であり、変更したり削除したりすることはできません。
クリックしてフォローして、Huawei Cloudの最新テクノロジーについて初めて学びましょう~