2時間分の字幕を1分で終わらせる方法を教えます

要約: この記事では、録画ファイル認識高速バージョンを使用して、字幕なしのビデオに字幕を自動的に生成する方法を紹介します。

この記事は、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. 字幕番号または位置を示すデジタルカウンター。
  2. 字幕の開始時間と終了時間。
  3. 1 行以上の字幕テキスト。
  4. 字幕の終わりを示す空白行。

コード開発

ステップ 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の最新テクノロジーについて初めて学びましょう~

{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4526289/blog/9024043