Recotte Studioのプロジェクトファイルからキャラの掛け合いのみ抽出するPythonスクリプト

Recotte Studioのプロジェクトファイルからキャラの掛け合いのみ抽出するPythonスクリプトです。

実行時に指定したフォルダ配下のプロジェクトファイルを取得し、キャラのセリフを時系列で抽出、プロジェクト名+実行年月日の形でテキストファイルを出力します。
出力は実行フォルダ配下にフォルダ生成され、そちらに出力されます。

 output_dialoguesフォルダ ・・ キャラ掛け合いの結果ファイル
debug_logsフォルダ ・・デバッグ用。基本は不要です。


Recotte Studio自体がキャラの掛け合いを主目的としたソフトですが、作った動画ってキャラなにしゃべっていたかな、、というのを後からさっと確認するために自分向けに作ったツールです。

バージョン1.8.1.4で生成されたプロジェクトファイル(.ccproj)で動作確認済みです。ファイルを壊すようなものではないですが、極力プロジェクトファイルを別フォルダにコピーして、そちらを処理対象としてください。

import json
import os
from datetime import datetime

def process_ccproj_files(input_directory, output_directory, debug_directory):
    # 指定フォルダ内のすべての.ccprojファイルを取得
    ccproj_files = [f for f in os.listdir(input_directory) if f.endswith('.ccproj')]

    if not ccproj_files:
        print("No .ccproj files found in the specified directory.")
        return

    for ccproj_file in ccproj_files:
        input_path = os.path.join(input_directory, ccproj_file)
        process_single_ccproj(input_path, output_directory, debug_directory)

def process_single_ccproj(json_file, output_dir, debug_dir):
    with open(json_file, 'r', encoding='utf-8') as f:
        data = json.load(f)
    
    # JSONのプロジェクト名を取得
    project_name = data.get('setting', {}).get('project-name', 'UnknownProject')
    
    # 実行時刻を取得
    current_time = datetime.now().strftime("%Y%m%d%H%M%S")
    
    # 出力ファイル名を生成
    output_file = f"{output_dir}/{project_name}_{current_time}.txt"
    debug_file = f"{debug_dir}/{project_name}_{current_time}_debug.txt"
    
    dialogues = []
    debug_info = []
    
    # layers 配下で type が Speaker の要素を抽出
    for layer in data.get('layers', []):
        if layer.get('type') == 'Speaker':
            layer_name = layer.get('name', 'Unknown Speaker')
            debug_info.append(f"Speaker Layer Found: {layer_name}")
            for obj in layer.get('layer-objects', []):
                if obj.get('type') == 'Speaker Voice':  # 'Speaker Voice'のみ対象
                    start_time = obj.get('start-time', None)
                    properties = obj.get('properties', {})
                    
                    # VoiceroidText の p-value を取得
                    voiceroid_text_data = properties.get('VoiceroidText', {})
                    voiceroid_text = voiceroid_text_data.get('p-value', '').strip() if isinstance(voiceroid_text_data, dict) else ''
                    
                    # デバッグ情報を記録
                    debug_info.append(f"Start Time: {start_time}, VoiceroidText: {voiceroid_text}, Speaker: {layer_name}")
                    
                    if start_time is not None and voiceroid_text:
                        dialogues.append((start_time, layer_name, voiceroid_text))
    
    # 開始時間順にソート
    dialogues.sort(key=lambda x: x[0])
    
    # テキストファイルにセリフを出力
    with open(output_file, 'w', encoding='utf-8') as f:
        # ファイル冒頭にプロジェクト名の説明文を追加
        f.write(f"このファイルは「{project_name}」の動画の掛け合いセリフとなります。\n\n")
        for _, speaker, dialogue in dialogues:  # start_time は出力せず
            f.write(f"{speaker}{dialogue}」\n")
    
    # デバッグ情報を別ファイルに出力
    with open(debug_file, 'w', encoding='utf-8') as f:
        f.write("\n".join(debug_info))
    
    print(f"Processed: {json_file}")
    print(f"Output written to {output_file}")
    print(f"Debug information written to {debug_file}")

# 入力フォルダ、出力フォルダ、デバッグ情報フォルダ
input_directory = './input_ccproj'  # ccprojファイルが格納されているディレクトリ
output_directory = './output_dialogues'  # セリフの出力ディレクトリ
debug_directory = './debug_logs'  # デバッグ情報の出力ディレクトリ

# 必要に応じて出力ディレクトリを作成
os.makedirs(output_directory, exist_ok=True)
os.makedirs(debug_directory, exist_ok=True)

# ccprojファイルを一括処理
process_ccproj_files(input_directory, output_directory, debug_directory)

実行結果のサンプルはこんな感じ。対象となる動画はつぎのヤツです

「」の前のキャラ名はレイヤーの名前をそのまま引っ張ってきています。

このファイルは「根室9」の動画の掛け合いセリフとなります。

自転車の六花さん 「はーい、それではこのあたりからは 私が前に出ますねー」
自転車のあかりさん 「どうしよう」
自転車のあかりさん 「リッカサンのジャージがかっこ悪いんだが!?」
話者2 「わかってくれるかおじゃこよ」
自転車のあかりさん 「こやつ直接脳内に!?」
話者2 「みんなあのジャージほめるんだ」
自転車のあかりさん 「そもそも小樽から自転車自走で高校生来てたらなんだって褒めそうな気がするけど」
話者2 「そんなもんか?」
自転車のあかりさん 「そんなもんもん」
自転車のあかりさん 「そもそもあれは自前? たまたまあれしかなかったとか?」
話者2 「ざんねんだがじまえのじさくだ」
話者2 「ろごもじぶんでいれている」
自転車のあかりさん 「それはモー情熱だね、牛だけに」
話者2 「さす」
自転車のあかりさん 「いやだい」
話者2 「あれはびてきせんすてきにどうかとおもうんだ」
自転車のあかりさん 「ハチも美的センスが必要なのか。。」
話者2 「ウチのすではびてきせんすがようきゅうされる」
自転車のあかりさん 「ハチもたいへんやな」
話者2 「とりあえずほんのりときづかせてほしいぞ」
自転車のあかりさん 「うぇーい」
自転車のあかりさん 「あー、リッカサン」
自転車のあかりさん 「そのジャージ」
自転車の六花さん 「あ、こんなかわいいって褒めてくれるんですよ!」
自転車のあかりさん 「ああ、そうだね!」
自転車の六花さん 「またあかりさんに文字の画像ファイル送りますね!」
自転車の六花さん 「作ってヨーグルト部を広めましょう!」
自転車のあかりさん 「ああ、ありがとう!」
話者2 「よわい」
話者2 「やっぱりおじゃこはおじゃこだな」
メインのあかりさん 「むー」
メインのあかりさん 「はっちゃん先生たのんます」
話者2 「まかせろ」
話者2 「おだんごよ」
自転車の六花さん 「あ、そうそう。明日以降は釧路から帯広に行くから、おいしそうなお店をピックアップしておいてー」
話者2 「おー、おびひろたのしみだぞ!」
話者2 「すまほでさがしておくぞ」
自転車の六花さん 「買ってあげたTシャツちゃんと着てね!」
話者2 「わかってるぞ。きょうはちょっとさむいからまたこんど」
自転車のあかりさん 「弱い」
話者2 「さす」
自転車のあかりさん 「いやだい」
自転車のあかりさん 「買ってもらったTシャツって何?」
話者2 「くわしくきいてはいけない」
自転車のあかりさん 「アッハイ」
自転車のあかりさん 「これはあれだ。二人がかりでやればなんとかなるのでは?」
話者2 「なるほど」
話者2 「おじゃこもなかなかいいこというな」
自転車のあかりさん 「ありがたき幸せカタクチイワシ」
自転車のあかりさん 「あー、リッカサンや」
話者2 「おだんごよ」
自転車の六花さん 「あ、そうそう。道東おいしいヨーグルトマップを作ったので、また送りますね!」
自転車のあかりさん 「おお、たすかるー」
話者2 「さすがおだんごはヨーグルトのことだけは しっかりしているな!」
自転車の六花さん 「うふふっ」
自転車のあかりさん 「諦めようか」
話者2 「そうだな」
自転車のあかりさん 「リッカサンにはリッカサンの自由があるから」
話者2 「そうだな」
話者2 「いやじぶんはしゃつもらったんだが!?」
自転車のあかりさん 「それはそれでよしなに」
話者2 「はぁー、おじゃこはやっぱりおじゃこだ」
自転車のあかりさん 「ありがたき幸せウルメイワシ」
自転車のあかりさん 「この話、オチはないのかい?」
話者2 「じゃこがじゃこなのがオチだぞ」
自転車のあかりさん 「精一杯頑張っておりまカタクチイワシ」
メインのあかりさん 「それでは根室編6日目後編始めてまいりましょう」
メインのあかりさん 「現在は厚岸を超えて釧路町、北太平洋シーサイドラインを通行中です。」
メインのあかりさん 「前回に引き続き、難読地名が続く地区を登ったり下ったり登ったりしながら行きましょう」
メインのあかりさん 「下りはそこそこの速度で走っていますが、すぐ登りが来るので勢い付けないと」
メインのあかりさん 「釧路につくのが三日後とかになりそうです。」
メインのあかりさん 「しかしここに来ての看板」
メインのあかりさん 「もう何書いているかわかりません。」
メインのあかりさん 「なお前回コメントで教えていただきましたが、これらの看板、2023年1月現在で継続して」
メインのあかりさん 「立て替えが進んでいるようで、説明書きもぺっかぺかの新品になっているようです。」
メインのあかりさん 「これは再走不可避」
メインのあかりさん 「右にふと空き地が見えてきましたが、 ここもこんぶの干し場所ですね」
メインのあかりさん 「現在標高150メートルぐらいの高さの場所のため、最初この光景を見たときは、なぜ山の中に」
メインのあかりさん 「広い駐車場のような場所だけがあるのかと思いましたが、海沿いの平坦な土地があまりないため」
メインのあかりさん 「丘を登った場所に昆布干しの場所を設けているようです。」
メインのあかりさん 「まーたもいもいと登っていますが、この道、細かいアップダウンが多い」
メインのあかりさん 「根室から160km、最大高度200メートルぐらいですが、獲得標高1600メートルなので」
メインのあかりさん 「細かいアップダウンがたんまりあるコースです」
メインのあかりさん 「今回は車体・荷物合わせて22kg程度の 荷物のため、登坂は問題ありませんが、」
メインのあかりさん 「キャンプ装備で30kg超える場合はそこそこ心が折られることがあるので注意しましょう」
りっかさん 「こちらははっちゃんか15kgほどあるんですが それは。。。」
メインのあかりさん 「いがいと重いな!?」
レイヤ億のはっちゃん 「ふところにはちみつがたくさんあるからな!」
メインのあかりさん 「さすがやで」
メインのあかりさん 「そしてまた山の中の昆布干し場所」
メインのあかりさん 「ここも定点観測ポイント」
メインのあかりさん 「くしろバスの車体を利用した物置? です」
メインのあかりさん 「みどころさんとしては電気メーターが 取り付けられており、」
メインのあかりさん 「物置だけでない活用がされていそうな点です」
メインのあかりさん 「ここで昆布が干されている映像は手持ちには ありませんが、ストリートビューでは昆布ほしを」
メインのあかりさん 「されている様子が確認できました。」
メインのあかりさん 「だんだん流れ作業になる地名紹介」
メインのあかりさん 「トマチセ」
メインのあかりさん 「見える! 説明書きが見える!」
メインのあかりさん 「昭和49年に作られた昆布森タコ踊のレコードに この近辺のタコ岩の写真が使われたとのこと」
メインのあかりさん 「たこ踊りはYoutubeのリンクを 説明欄に張っときます。」
メインのあかりさん 「はいつぎ、キトウシ」
メインのあかりさん 「ここはキトウシ野営場というキャンプ場がちょっと有名ですね」
メインのあかりさん 「海岸線のワイルドなキャンプ場です。」
メインのあかりさん 「だいたいここから釧路空港までで45kmぐらいなので、昼イチの飛行機であれば、」
メインのあかりさん 「東京羽田からぴょーいと飛んできて、そのままここのキャンプ場に泊まることも不可能では」
メインのあかりさん 「ないです」
メインのあかりさん 「問題はキャンプ場に風呂シャワーはない上に、今の画面のようにキャンプ場までに坂があるので、」
メインのあかりさん 「街中でお風呂なり入ってきても坂で汗をかく点でしょうか?」
メインのあかりさん 「その場合は諦めてキャンプ場で水かぶりましょう。」
メインのあかりさん 「なお、この動画の2021年は流行り病のため キトウシ野営場はクローズされていましたが、」
メインのあかりさん 「2022年はオープンしていたようです。」
メインのあかりさん 「そして釧路までの最後の町、昆布森」
メインのあかりさん 「文明の町に戻ってきた感があります。」
メインのあかりさん 「昆布森はその名の通り昆布が有名ですが、それとともに昆布を食べて育ったウニも有名です。」
メインのあかりさん 「ただ、昆布森のウニは2021年に赤潮の影響で壊滅、2023年1月現在はウニの継続的な」
メインのあかりさん 「放流にて資源の回復を図られている段階です。」
メインのあかりさん 「ここも継続して状況はウォッチしていきたいと思います。」
メインのあかりさん 「そしてそろそろ難読地名ゾーンも終わりに近づいてまいりました。」
メインのあかりさん 「マタイトキ」
メインのあかりさん 「「また来なさいやー」的に聞こえなくもないですね」
レイヤ億のはっちゃん 「またごはんのときにもみえるぞ」
メインのあかりさん 「あかり一族として正しい解釈やでぇ」
メインのあかりさん 「ずっと逆光ですが、その逆光の中に釧路の町が見えてきました。」
メインのあかりさん 「釧路、中標津、根室を、ただ単にクルッと まわった旅もそろそろ終わりが近いです。」
メインのあかりさん 「今日は割と森ばっかり見てきたので、人家の密集している景色が新鮮に感じますね」
りっかさん 「小樽よりも全体的になだらかな坂が多かったですね」
りっかさん 「坂成分としては弱いものの、継続して坂が接種できる道だったかと思います。」
メインのあかりさん 「坂ソムリエッカさん、コメントありがとうございます」
メインのあかりさん 「三日目に徒歩でとほとほ歩いた坂とロータリーを 今度は自転車で下る形になります。」
メインのあかりさん 「釧路や旭川のロータリーですが、侵入する車両が優先、道に特に信号や停止線がないため、」
メインのあかりさん 「基本的にそのまま侵入すれば問題ありません。」
メインのあかりさん 「特に自転車侵入禁止でもないため、そのまま走って侵入してもよいですが、ちょっと怖いですね」
りっかさん 「左側が見えないのがちょっと怖いですね」
メインのあかりさん 「真ん中の車線に放り出されるので、 そこんところだけ要注意です」
メインのあかりさん 「ええ感じに左車線に車線を変えましょう。」
メインのあかりさん 「最後の幣舞橋ストレート」
メインのあかりさん 「釧路に帰ってきた感があります。」
メインのあかりさん 「釧路駅からの駅前通りは廃墟が多いといわれてますが、まだまだ車両の通りは多いですね」
メインのあかりさん 「そして親の顔より見た釧路駅」
りっかさん 「もっと親の顔見て」
メインのあかりさん 「昔から変わらない建物である一方、ちょっとずつ中のテナントが」
メインのあかりさん 「変わったり減ったりしているのが 気になるところです。」
メインのあかりさん 「ということで本日の走行は以上です。 お疲れさまでした。」
メインのあかりさん 「おはようございまーす」
りっかさん 「ウチのお兄ちゃんです」
メインのあかりさん 「おはようございまーす」
りっかさん 「あーいや、こちらは前話してたあかりさん」
メインのあかりさん 「お兄さま、なかなか大きくて ムキムキで強そうですねー」
メインのあかりさん 「強大な兄妹ですね!」
メインのあかりさん 「クールジョークです」
りっかさん 「えーっと、はっちゃんの、、、なに?」
メインのあかりさん 「オリジナル?」
話者2 「むむ」
話者2 「じぶんがおりじなるだぞ」
メインのあかりさん 「むむ、あかりさんがオリジナル」
話者2 「むむむ」
メインのあかりさん 「むむむ」
メインのあかりさん 「むー」
話者2 「むむー」
メインのあかりさん 「ふっ、あかりさんに勝てるとでも!?」
りっかさん 「うん、とりあえず今日は釧路空港に寄ってから帯広ぐらいまでは行くから、」
りっかさん 「適当に帯広現地集合で」
メインのあかりさん 「それでは我々は釧路空港まで行きましょう」
メインのあかりさん 「おっと、あれは日本製紙 釧路工場ですね」
メインのあかりさん 「動画撮影日時は2021年8月15日、 日本製紙 釧路工場は8月16日に」
メインのあかりさん 「生産を終了するため、工場が稼働するのはこの 映像の日が最終日となっています。」
メインのあかりさん 「さて、それではいつものラーメンさんぱちの看板を左に、初日に通った釧路阿寒自転車道を」
メインのあかりさん 「逆に走って空港に向かいましょう」
メインのあかりさん 「そういえば、この旅でなんどもタンチョウ様を 見かけました(実数で30羽ぐらい)が、」
メインのあかりさん 「優雅に空を飛ぶタンチョウさまをお伝え出来なかった点は若干残念ではあります。」
メインのあかりさん 「まぁ、草むらで地面をつんつんしている姿が タンチョウ様の日常なので、そういう意味では」
メインのあかりさん 「タンチョウさまの日常をお届けできたのかとは思います。」
りっかさん 「そういうもんでしょうか?」
メインのあかりさん 「そういうもんもん」
メインのあかりさん 「この帰るときのゆったりとした走行も悪くないものです」
メインのあかりさん 「ここのおうまさまは割といつも自転車道のそばに いらっしゃいますね」
メインのあかりさん 「やぁやぁお馬様、また会おう」
メインのあかりさん 「釧路阿寒自転車道、道端には少し注意ですね」
メインのあかりさん 「キツネさま、シマリスさまも道端にいらっしゃることがあるため、道の横にも注意です。」
メインのあかりさん 「おっと、この辺りでは珍しい。地元住民さまの姿が向こうに見えますね」
メインのあかりさん 「ん?」
メインのあかりさん 「地元住民さまの前にタンチョウ様が!」
メインのあかりさん 「そして後ろから2羽目も!」
メインのあかりさん 「飛んだー!」
メインのあかりさん 「飛んだー!」
メインのあかりさん 「飛んだー!」
メインのあかりさん 「最後の最後に皆様にお見せすることができました」
メインのあかりさん 「自転車道に左右見ずに飛び出して 通行中の地元住民の方にびっくりして」
メインのあかりさん 「優雅に空を舞うタンチョウ様の姿」
メインのあかりさん 「実に優雅でした」
メインのあかりさん 「あれは抗議の鳴き声でしょうか」
メインのあかりさん 「自宅の庭で鳴かれるには ちょっと声のボリュームが大きいですね」
メインのあかりさん 「タンチョウさまは割とどこでも飛び出してくるので、自転車の方も車・バイクの方も」
メインのあかりさん 「お気を付けください」
りっかさん 「なんだか一般的な自転車旅動画の優雅さと違って、あかりさんの旅はどこかシュールギャグ要素が」
りっかさん 「入るのは気のせいでしょうか?」
レイヤ億のはっちゃん 「じゃこだからしかたがない」
メインのあかりさん 「いやぁ、実にあかりさんらしい クールな出来事でした」
メインのあかりさん 「ん?」
メインのあかりさん 「なんかあったのアッチョロベツ」
メインのあかりさん 「ちょっとオンボロ鳥の羽」
メインのあかりさん 「おそらくタンチョウ様の羽ですね」
メインのあかりさん 「タンチョウ様など国内希少野生動植物種に関しては「種の保存法」で羽も含めた譲渡は」
メインのあかりさん 「禁止されているため、売買、譲渡はできませんが、落ちている羽を自分用に拾うには」
メインのあかりさん 「問題ないので、記念に持っていきましょう」
メインのあかりさん 「時期的にほかの鳥の子育て時期も終わっているので、羽が巣材として使われることもないでしょう」
メインのあかりさん 「夏よりも前だと羽は鳥の巣材として使われることがあるので、そこだけは要注意ですね」
メインのあかりさん 「さて、自転車道から離脱して、このまままっすぐで空港です」
りっかさん 「我々は空港ちょっと見てから帯広に向かいますね」
メインのあかりさん 「うん、海沿いをぐいーといって、十勝川のところでぺっかり曲がればつくと思うよ」
りっかさん 「はい、ぽっこり曲がりますね」
メインのあかりさん 「ぴっこり曲がってね」
メインのあかりさん 「おっと」
メインのあかりさん 「北海道らしい牛様と、、、キツネさま」
メインのあかりさん 「そして釧路空港前の坂です」
メインのあかりさん 「80メートルぐらいは登るので、最後の最後で 力尽きないようにしましょう」
メインのあかりさん 「それでは旅の最後のサイクルステーションに 到着です。」
メインのあかりさん 「はい釧路空港にゴーール」
メインのあかりさん 「今回の旅の走行は以上です。お疲れさまでした。」
メインのあかりさん 「それではリッカサンありがとう、 ここからも気を付けてね」
りっかさん 「また小樽に来てくださいね」
メインのあかりさん 「はっちゃんはあまりおいたをしないように」
話者2 「おうがんばれよ!」
メインのあかりさん 「時間があるならごはんだけでも 一緒にたべようたべよう」
話者2 「おごりか、おごりなのか!?」
メインのあかりさん 「まかしんしゃい!」
メインのあかりさん 「さてとりあえず釧路空港といえばこれ」
メインのあかりさん 「たんちょうスパゲティですね」
メインのあかりさん 「これはたんちょうさまのたまごがトッピング」
メインのあかりさん 「、、ではなく、レストランたんちょうさんが出している」
メインのあかりさん 「タンチョウさまの巣をモチーフとしたスパゲティです」
メインのあかりさん 「それではしばし釧路からのお別れです」
メインのあかりさん 「V1」
メインのあかりさん 「回転!」
メインのあかりさん 「オホ神へ、釧路土産があるので 取りに来てください」
オホ神 「オホ神へ、釧路土産があるので 取りに来てください」
オホ神 「ってだれもいない」
オホ神 「さすがに10月でこたつはまだ早い気はしますね」
オホ神 「っと、きりちゃんのあたまだけが。 お昼寝中でしょうか。。」
オホ神 「あかりさんは留守でしょうか?」
オホ神 「きりちゃーん、きましたよー」
ズラのあかりさん 「きりちゃんです」
オホ神 「ひぃー」
ズラのあかりさん 「あかりさんはそこですね」
ズラのあかりさん 「オホ神もあかりさんゲットだぜ」
オホ神 「あかりさん。。」
オホ神 「最近ちょっと自転車車載としての心意気を忘れていないでしょうか?」
オホ神 「前回のギャグマンガ飛びは忘れていませんよ、」
オホ神 「ネタに走ってシリーズを始めたときの初心を 忘れていないでしょうか?」
ズラのあかりさん 「初心、、、」
ズラのあかりさん 「初手荒木さん宅バス停」
ズラのあかりさん 「なんかうろうろした挙句画面から消える」
ズラのあかりさん 「世界の終わり」
ズラのあかりさん 「冷静に見ると今の方がマシな気がしますね」
オホ神 「ともかく!」
オホ神 「バツとしてオホーツク知床の刑です」
ズラのあかりさん 「そんな、、次シリーズとしてオホーツク知床を 再送しろだなんて!」
オホ神 「ちゃんとオホーツクをぞんぶんに取り上げるように」
ズラのあかりさん 「かーわーいーいー」
ズラのあかりさん 「おっときりたんぬ師匠!」
ズラのあかりさん 「どうも、きずなあかりたんです」
ズラのあかりさん 「こっちはオホ神たん」
オホたん 「ゴロが悪い!」
きりたんぬ1916 「どうも、東北19:16たんです」
きりたんぬ1916 「あ、ぜんぜん、きにしていませんよ19:16」
きりたんぬ1916 「特に問題はありま19:16」
メインのあかりさん 「いこうか?」

いいなと思ったら応援しよう!