最終回です。長かった。。。
最初に作ろうとしたシステムは下図のようなものでしたが、指定のトラックへTextやText+をセットする方法が難しすぎたので結局は字幕ファイルをインポートする方法に変えました。
(FusionCompのindex1をToolListから取得するってなんやねん。。。)
DFXPファイル形式で字幕をインポートすると文字の色や縁取りなどをサポート出来るそうですが、色々試行錯誤してもDaVinchi Resolve(の無料版)では読み込めなかった為にSRTフォーマットで吐き出すようにしました。
処理内容の概要
- 前回出力したCSVファイルを読み込む
- SRTフォーマットへ変更
- DaVinchi ResolveのメディアプールへSRTファイルを挿入
スクリプトのファイル名は「my_insert_subtitle.py」として、DaVinchi Resolveのスクリプトフォルダ「C:\ProgramData\Blackmagic Design\DaVinci Resolve\Fusion\Scripts\Utility」下に保存して使うことを想定しています。
変数の用意
import os
# ここを適切なファイルパスに変更
BASE_DIR = '自分の作業ディレクトリ'
SUBTITLE_CSV = '読み込むCSVファイル名'
SRT_NAME = '出力SRTファイル名'
SRT_ARROW = '-->'
# DaVinci Resolveのインスタンスを取得
project_manager = resolve.GetProjectManager()
project = project_manager.GetCurrentProject()
timeline = project.GetCurrentTimeline()
media_pool = project.GetMediaPool()
# TL情報の取得
FPS = timeline.GetSetting("timelineFrameRate")
CSVの読み込み
字幕の表示開始時間と表示長さを取得していきます。
def read_csv():
result_list = []
with open(BASE_DIR + SUBTITLE_CSV, 'r', encoding='utf_8') as f:
lines = f.readlines()
for idx, line in enumerate(lines):
if idx > 0:
#line = line.replace(os.linesep, '')
data = line.split(',')
item = {'id': idx, 'time': data[0], 'duration': data[1], 'text': data[2]}
result_list.append(item)
return result_list
SRTフォーマットへ変更
下記のような構造のファイルを作成します。
1
01:00:01,000 –> 01:00:04,000
この映画はフィクションです。2
01:00:05,000 –> 01:00:14,000
すべての登場人物、団体等は架空のものです。
ざっくりとwrite_srt関数で書き込みますが、時間の変換が必要なのでconvert_seconds_to_srt_formatで変換します。
def write_srt(subtitle_list):
with open(BASE_DIR + SRT_NAME, 'w', encoding='utf_8') as file:
for item in subtitle_list:
start = convert_seconds_to_srt_format(int(item['time']))
end = convert_seconds_to_srt_format(int(item['time']) + float(item['duration']) * FPS)
line = f"{item['id']}\n{start} {SRT_ARROW} {end}\n" + item['text'] + '\n'
file.writelines(line)
音声認識で書き出した開始時間はフレームで出力されるので、先ずはそれを時間フォーマット[00:00:00,000]形式に変換させます。
表示時間はsecで出力されるので一旦フレームに変換してからconvert_seconds_to_srt_format関数へ入れます。
(当初構想のスクリプトが作れなかったので設計をミスっています。。。)
def convert_seconds_to_srt_format(frame):
seconds = frame / FPS
# Calculate the hours, minutes, and the remaining seconds
hours = int(seconds // 3600)
minutes = int((seconds % 3600) // 60)
seconds_left = seconds % 60
# Split the seconds to get milliseconds
seconds_int = int(seconds_left)
milliseconds = int((seconds_left - seconds_int) * 1000)
# Format the output string
formatted_time = f"{hours:02}:{minutes:02}:{seconds_int:02},{milliseconds:03}"
return formatted_time
メディアプールへSRTファイルを挿入
TLに字幕トラックが無い場合はまずトラックを挿入し、media_pool.ImportMedia関数で生成したSRTファイルを挿入します。
def import_srt():
if timeline.GetTrackCount('subtitle') == 0:
timeline.AddTrack('subtitle')
import_result = media_pool.ImportMedia(BASE_DIR + SRT_NAME)
if import_result:
print(f"ファイル '{BASE_DIR + SRT_NAME}' が正常にインポートされました。")
else:
print(f"ファイル '{BASE_DIR + SRT_NAME}' のインポートに失敗しました。")
SRTファイルの挿入に成功するとコンソールにメッセージが流れ、Media Pool内にファイルが置かれます。
最後にSRTファイルを右クリックし、タイムコードを使って字幕を挿入の項目を選択するとTLのSubtitleトラックに字幕が展開されます。
以上で一応自動字幕システムの完成です。(最後の方は自動と呼ぶには手作業が多いですが…)
最終的なプロジェクト構成
C:/ProgramData/Blackmagic Design/DaVinci Resolve/Fusion/Scripts/Utility/
├my_auto_subtitle.py [TLから音声データを収集]
└ my_insert_subtitle.py [TLに字幕データを展開]
作業フォルダ/
├davinchi_voice_recognition.py [音声認識]
├utils_vad.py
└ result_data/
├voice-recognition-result.csv [音声認識結果保存]
└ voice-recognition-result.srt [字幕データ]