無料版Davinchi Resolveで字幕生成システムを作る #4 | 字幕挿入

最終回です。長かった。。。

最初に作ろうとしたシステムは下図のようなものでしたが、指定のトラックへ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 [字幕データ]

sam

sam

流山おおたかの森Techブログの管理人です。 お仕事のご依頼などはmail or Twitter[https://twitter.com/sam_sumario]で連絡頂けると反応出来ます。
Previous post OBS Studioのプラグインの作り方 #3 フィルタのプロパティ作成
Next post OBS Studioのプラグインの作り方 #4 カラーフィルタ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です