四方山話/スクリプト作業の効率化と台本出力

Last-modified: 2016-09-27 (火) 12:42:19

概要

シナリオのスクリプト化作業はプロジェクト後半に集中するため、どうしても前工程のしわ寄せを受けやすい。どれだけ効率的にスクリプト化していくかがスクリプターの腕の見せ所となる。ここではシナリオのスクリプト化作業を効率化する、シナリオコンバータを紹介する(台本も出力できるようにしてある)。*1

シナリオコンバータは大きく2つの機能を持っている。

  1. 所定の書式に従って記述したノベルゲーム用シナリオファイル(.txt)をXMLファイルに変換する
  2. このXMLファイルを元に以下のファイルを得る
    • 各種ノベルエンジン用スクリプト
      • 現状は吉里吉里2/KAG3のKAGシナリオファイルを出力できる
      • 完全なものではなく、あくまで機械的に処理できる部分のみスクリプト化したもの。これを更に手作業で修正していく
    • 台本
      • 現状はO's Editor 2とpLaTeX(動作確認はWindows版W32TeX)の台本を出力できる
    • ボイス用音声ファイル一覧表(.csv)
      • ボイス用音声ファイル名と収録されている台詞を登場人物ごとに一覧表にしたもの。確認用

ここで紹介するシナリオコンバータは「これが完成形」というモノではなく、制作チームの都合に合わせて改造・拡張することが前提になっている。*2*3

シナリオテキスト→XMLファイル化

scenario2xml.ps1はシナリオテキスト(.txt)をXMLファイルに変換する。

PowerShellコンソール上で以下のように入力する。予めPowerShellの実行セキュリティポリシーをRemoteSigned以下に設定しておくこと。設定ファイルの書式は後述。

.\scenario2xml.ps1 設定ファイル

シナリオテキストの書式

識別可能な要素は以下の通り。

行頭の文字や以降の書式によって文章の扱いが変化する:
【~】 …人物名
【~】(~) …人物名(演技指示)
【~/~】 …表示名/人物名
【~/~】(~) …表示名/人物名(演技指示)
「~」 …台詞
「~  …台詞(複数行)
   :
  ~」
■~ …イベント名
□~ …イベント名(どっちも同じ扱い)
◆~ …イベント概要
◇~ …イベント概要(どっちも同じ扱い)
●~ …柱
○~ …柱(どっちも同じ扱い)
◎~ …柱(どっちも同じ扱い)
※~ …演出指示
; …コメント(複数行ある場合は一まとめにする)
それ以外、行頭から始まる文字列 …地の文(複数行可。空行か次の要素が出現するまで1つの地の文と見なす)
以下は人物名、表示名、台詞、地の文の中でのみ使用できる:
|文字《ルビ》 …ルビ。人物名または表示名、台詞、地の文の中でのみ使用できる

注意事項

  • ■または□は、1シナリオテキスト内に最大1つあることを想定している(2つ以上あると最後の方を適用する)
  • ◆または◇は、1シナリオテキスト内に最大1つあることを想定している(2つ以上あると最後の方を適用する)
  • 【~】と「~」は、この順番で、かつペアで使われていないとエラーと見なす
  • 【~】「~」と並べる書き方には対応させていない。次のように改行が必要(一行の文字数が把握しやすいのでこうしている)
    【~】
    「~」
  • 表示名は、例えばゲーム画面では「男の声」と表示され、実際に喋っているのは登場人物のうちの誰かだった…というシーン(電話とか)での利用を想定している
    • ちなみに台本では喋っている人物名が出力される
  • |~《~》は以下のように複数行に分かれているとルビ指定と識別しない
    「|麻
    雀《マージャン》」
  • これならOK
    「|麻《マー》
    |雀《ジャン》」
  • @は改行と見なす(シナリオ中に@と記述するのは避けたほうが良い)
  • ルビなど各種要素をエスケープ(打ち消す)する書式は用意していない
  • ルビの書式が正しいかはチェックしていない(厳密に構文解析している訳じゃないので全体的に書式のチェックが甘い)
  • 多少、いい加減な書式でも受け入れるようにしてある*4
    • ;において、;は;(半角)でも良い
    • 【~/~】において、/は/(半角)でも良い
    • 【~/~】(~)において、()は()(半角)でも良い。また、最後の)はなくても良い
    • |~《~》において、|は|(半角)でも良い
  • いわゆる画面下にメッセージ枠があるタイプでの使用を想定している(なので人物名を強要している)
  • サウンドノベル(画面全体に文字列が並ぶ)タイプでの使用は想定していない(PowerShellモジュールの書き方次第だと思うが)
  • シナリオテキストはファイル名順にXMLファイルに登録される
  • $SCENARIO_FOLDERフォルダ下にサブフォルダがある場合、サブフォルダ以下も検索対象となる
  • シナリオテキストの追加/削除/更新後、再度、当スクリプトを実行しても良い(単にXMLファイルを作り直すだけだが)
  • シナリオIDには、シナリオテキストのベース名(拡張子なしのファイル名)の先頭$SCENARIO_ID_LENGTH文字を採用する
    • シナリオIDが重複してはならない
    • $SCENARIO_ID_LENGTHの値が0以下ならベース名をシナリオIDとして採用する

設定ファイル

設定ファイルの文字コードはShift JISのみ動作を確認している。

#
# scenario2xml.ps1 / xml2script.ps1用設定ファイル
#
$TITLE = 'サンプルシナリオ'      # ゲームタイトル
$AUTHOR = 'foo'          # 作者
$SCENARIO_ID_LENGTH = 4        # シナリオID(番号など)の桁数
$SCENARIO_FOLDER = 'C:\Sample\scenario'    # シナリオテキスト(.txt)のあるフォルダ
$XML_FILE_PATH = 'C:\Sample\scenario.xml'  # 出力するXMLファイルのフルパス(既存のファイルは上書き)
$SCRIPT_FOLDER = 'C:\Sample\output'    # スクリプトファイル出力先フォルダ
$VOICELIST_FOLDER = 'C:\Sample\voice'    # ボイス一覧表出力先フォルダ
$ACTOR_PREFIX = @{ 'エイラ'='E'; '恵'='M' }  # 登場人物(ボイス有り)のプレフィックス(音声ファイル名などに使う)
$SOUND_BUFFER = @{ 'エイラ'=1; '恵'=2 }    # 登場人物(ボイス有り)で使用するサウンドバッファ番号
#
# ‐←半角 # から改行までコメント
# ‐値はシングルクォーテーションで囲むこと
# ‐$SCENARIO_FOLDERと$SCRIPT_FOLDERは同じフォルダ名にできない(←これのチェックは完全ではない)
#

XMLファイル→各種ノベルエンジン用スクリプト化

xml2script.ps1は、scenario2xml.ps1が出力したXMLファイルから、KAGシナリオファイル、台本ファイルを得る。*5

XMLファイル→KAGシナリオファイル用

PowerShellコンソール上で以下のように入力する。予めPowerShellの実行セキュリティポリシーをRemoteSigned以下に設定しておくこと。設定ファイルはscenario2xml.ps1のものと同じ。

.\xml2script.ps1 kag3 設定ファイル

XMLファイル→台本用

PowerShellコンソール上で以下のように入力する。予めPowerShellの実行セキュリティポリシーをRemoteSigned以下に設定しておくこと。

台本出力にはO's Editor 2とpLaTeX(藤田眞作氏のfurikana.sty使用)に対応させている。

O's Editor 2版台本を出力する場合:

.\xml2script.ps1 oseditor2 設定ファイル

pLaTeX版台本を出力する場合:

.\xml2script.ps1 platex 設定ファイル

XMLファイル→ボイス用音声ファイル一覧表

.\xml2voicelist.ps1は、scenario2xml.ps1が出力したXMLファイルから、ボイス用音声ファイル一覧表(.csv)を得る。

PowerShellコンソール上で以下のように入力する。予めPowerShellの実行セキュリティポリシーをRemoteSigned以下に設定しておくこと。設定ファイルはscenario2xml.ps1のものと同じ。

.\xml2voicelist.ps1 kag3 設定ファイル

サンプル

シナリオテキスト

入力として以下のサンプルシナリオ0000.txtと0010.txtを用意したと仮定する。設定ファイルは前述のものを使用。

□カレー地獄
◇エイラがカレーライスに開眼してしまう
○キッチン、夜
【琢己】
「明日は違うメニューにしような」
【恵】
「最近、魚が恋しくなってきたわ…」
【琢己】
「いいねえ焼き魚とか」
【エイラ】
「いえ! ぜひカレーで!!」
【琢己】
「…」
【恵】
「…」
5日前、たまたま恵がカレーライスを作ったのが全ての始まりだった。
妙にヒットしてしまったらしいエイラは、以来、毎日のようにカレーを
ねだってくるようになった。
毎日はさすがに飽きるだろうと、野菜カレーとかシーフードカレーとか
恵が変化をつけてくれたのだが、これが完全に裏目。
エイラをますますカレーにのめり込ませる結果になってしまった。
もちろん大学でも昼食はカレーライスだ。
学食はとうに制覇、今や近隣の店にまで出向く始末。
これで俺が同伴でなければ好きにしてくれと言うところなんだが…。
ヨーヨーカレーのスイートクラスの量は凄まじいの一言だった。
※口元で手を組むエイラ
【エイラ】(すがるように)
「お願い」
【琢己】
「う…」
【恵】
「兄さんってエイラの『お願い』に弱いよねー」
【琢己】
「…」
あんな風にすがるように見つめてくるんだもんなぁ。
■夜間中波DX
◆遠方のAMラジオを聴く
◎居間、夕方
【琢己】
「えーと、今晩は全国的に晴れか…もしかしたら聴けるかもしれないぞ?」
【エイラ】
「…本当?」
【琢己】
「まぁ、あまり期待しないで待ってろ」
【エイラ】
「?」
母さんと一緒に新聞のラジオ欄を読んでいるから何かと思えば、
今晩、ラジオなにわの「アニメ宝箱」でエイラお気に入りの声優、
中畑均(渋い…)がゲスト出演すると知って、ぜひ聴きたいのだとか。
関西のAMラジオ局など関東の新聞に掲載されているはずがなく、
なぜ載ってないのか、聴けないのか、母さんに訊いていたらしい。
◎ベランダ、20:45頃、晴れ
※ノイズ混じりのAMラジオ放送が鳴っている
【エイラ】
「なぜ関西のラジオ番組が聴こえるのですか?
 ここは関東なのに」
【琢己】
「夜になると電離層がAMラジオ放送の電波を反射するんだ。
 でAM放送が遠くまで届くらしい。
 …ノイズが多いな。ちょっと待ってろ」
※部屋から出て行く足音。しばらくして部屋に戻ってくる足音
【エイラ】
「…この金網みたいなものは何ですか?」
【琢己】
「ループアンテナ。こいつをラジオに繋げて感度を上げるんだよ」
感度最強と名高い瑞穂エレクトロニクスのループアンテナだ。
加えて|中波《AM》最強と名高い関東通信工業のラジオ。
この組み合わせでダメなら諦めるしかない。
※徐々にノイズが少なくなる
【アナウンサー】
「…いて天気予報です。関西地方の明日の天気は…」
【エイラ】
「すごい!!」
【琢己】
「よっし」
※時報
【パーソナリティ】
「土曜日夜の超無計画番組・アニメ宝箱!」
※BGM
【パーソナリティ】
「今晩のゲストは中畑均さんでーす!」
【中畑】(渋い声で)
「こんばんはー」
【エイラ】
「きゃー♪」
うれしそうだなぁ。

XMLファイル

scenario2xml.ps1で作成されたscenario.xmlは以下のようになる。

<?xml version="1.0" encoding="utf-8"?>
<!--
  「サンプルシナリオ」シナリオ用XMLファイル
  2010/11/14 00:00:00
-->
<scenario config="C:\Sample\sample_j.ini">
  <event id="0000" fullname="C:\Sample\scenario\0000.txt" basename="0000" eventname="カレー地獄" synopsis="エイラがカレーライスに開眼してしまう">
    <scene><![CDATA[キッチン、夜]]></scene>
    <speech actor="琢己" id="1"><![CDATA[明日は違うメニューにしような]]></speech>
    <speech actor="恵" id="1"><![CDATA[最近、魚が恋しくなってきたわ…]]></speech>
    <speech actor="琢己" id="2"><![CDATA[いいねえ焼き魚とか]]></speech>
    <speech actor="エイラ" id="1"><![CDATA[いえ! ぜひカレーで!!]]></speech>
    <speech actor="琢己" id="3"><![CDATA[…]]></speech>
    <speech actor="恵" id="2"><![CDATA[…]]></speech>
    <narration><![CDATA[5日前、たまたま恵がカレーライスを作ったのが全ての始まりだった。@妙にヒットしてしまったらしいエイラは、以来、毎日のようにカレーを@ねだってくるようになった。]]></narration>
    <narration><![CDATA[毎日はさすがに飽きるだろうと、野菜カレーとかシーフードカレーとか@恵が変化をつけてくれたのだが、これが完全に裏目。@エイラをますますカレーにのめり込ませる結果になってしまった。]]></narration>
    <narration><![CDATA[もちろん大学でも昼食はカレーライスだ。@学食はとうに制覇、今や近隣の店にまで出向く始末。@これで俺が同伴でなければ好きにしてくれと言うところなんだが…。]]></narration>
    <narration><![CDATA[ヨーヨーカレーのスイートクラスの量は凄まじいの一言だった。]]></narration>
    <direction><![CDATA[口元で手を組むエイラ]]></direction>
    <speech actor="エイラ" id="2" advice="すがるように"><![CDATA[お願い]]></speech>
    <speech actor="琢己" id="4"><![CDATA[う…]]></speech>
    <speech actor="恵" id="3"><![CDATA[兄さんってエイラの『お願い』に弱いよねー]]></speech>
    <speech actor="琢己" id="5"><![CDATA[…]]></speech>
    <narration><![CDATA[あんな風にすがるように見つめてくるんだもんなぁ。]]></narration>
  </event>
  <event id="0010" fullname="C:\Sample\scenario\0010.txt" basename="0010" eventname="夜間中波DX" synopsis="遠方のAMラジオを聴く">
    <scene><![CDATA[居間、夕方]]></scene>
    <speech actor="琢己" id="1"><![CDATA[えーと、今晩は全国的に晴れか…もしかしたら聴けるかもしれないぞ?]]></speech>
    <speech actor="エイラ" id="1"><![CDATA[…本当?]]></speech>
    <speech actor="琢己" id="2"><![CDATA[まぁ、あまり期待しないで待ってろ]]></speech>
    <speech actor="エイラ" id="2"><![CDATA[?]]></speech>
    <narration><![CDATA[母さんと一緒に新聞のラジオ欄を読んでいるから何かと思えば、@今晩、ラジオなにわの「アニメ宝箱」でエイラお気に入りの声優、@中畑均(渋い…)がゲスト出演すると知って、ぜひ聴きたいのだとか。]]></narration>
    <narration><![CDATA[関西のAMラジオ局など関東の新聞に掲載されているはずがなく、@なぜ載ってないのか、聴けないのか、母さんに訊いていたらしい。]]></narration>
    <scene><![CDATA[ベランダ、20:45頃、晴れ]]></scene>
    <direction><![CDATA[ノイズ混じりのAMラジオ放送が鳴っている]]></direction>
    <speech actor="エイラ" id="3"><![CDATA[なぜ関西のラジオ番組が聴こえるのですか?@ ここは関東なのに]]></speech>
    <speech actor="琢己" id="3"><![CDATA[夜になると電離層がAMラジオ放送の電波を反射するんだ。@ でAM放送が遠くまで届くらしい。@ …ノイズが多いな。ちょっと待ってろ]]></speech>
    <direction><![CDATA[部屋から出て行く足音。しばらくして部屋に戻ってくる足音]]></direction>
    <speech actor="エイラ" id="4"><![CDATA[…この金網みたいなものは何ですか?]]></speech>
    <speech actor="琢己" id="4"><![CDATA[ループアンテナ。こいつをラジオに繋げて感度を上げるんだよ]]></speech>
    <narration><![CDATA[感度最強と名高い瑞穂エレクトロニクスのループアンテナだ。@加えて|中波《AM》最強と名高い関東通信工業のラジオ。@この組み合わせでダメなら諦めるしかない。]]></narration>
    <direction><![CDATA[徐々にノイズが少なくなる]]></direction>
    <speech actor="アナウンサー" id="1"><![CDATA[…いて天気予報です。関西地方の明日の天気は…]]></speech>
    <speech actor="エイラ" id="5"><![CDATA[すごい!!]]></speech>
    <speech actor="琢己" id="5"><![CDATA[よっし]]></speech>
    <direction><![CDATA[時報]]></direction>
    <speech actor="パーソナリティ" id="1"><![CDATA[土曜日夜の超無計画番組・アニメ宝箱!]]></speech>
    <direction><![CDATA[BGM]]></direction>
    <speech actor="パーソナリティ" id="2"><![CDATA[今晩のゲストは中畑均さんでーす!]]></speech>
    <speech actor="中畑" id="1" advice="渋い声で"><![CDATA[こんばんはー]]></speech>
    <speech actor="エイラ" id="6"><![CDATA[きゃー♪]]></speech>
    <narration><![CDATA[うれしそうだなぁ。]]></narration>
  </event>
</scenario>

KAGシナリオファイル

xml2script.ps1で作成されたKAGシナリオファイルは以下のようになる(一部のみ)。*6

;□イベント名:カレー地獄
;◇イベント概要:エイラがカレーライスに開眼してしまう
;◎キッチン、夜
-0000|カレー地獄
[cm]
[nowait]【琢己】[r][endnowait]
「明日は違うメニューにしような」[p]
-0000_f702c905_36b6_4c1a_bb3e_23e902bd94e7|
[cm]
[nowait]【恵】[r][endnowait]
[pv b=2 s="M-0000-0001.ogg"]「最近、魚が恋しくなってきたわ…」[sv][p]
-0000_dab5a99e_56bc_47ae_975b_8d9e1aebef8c|
[cm]
[nowait]【琢己】[r][endnowait]
「いいねえ焼き魚とか」[p]
-0000_e3d1db4f_15d3_448b_819d_028c7b4d8b33|
[cm]
[nowait]【エイラ】[r][endnowait]
[pv b=1 s="E-0000-0001.ogg"]「いえ! ぜひカレーで!!」[sv][p]
-0000_1751c889_0411_47b0_8ffe_5bc96b979554|
[cm]
[nowait]【琢己】[r][endnowait]
「…」[p]
-0000_bb4e1483_9221_441d_92c5_68b73b1a23d6|
[cm]
[nowait]【恵】[r][endnowait]
[pv b=2 s="M-0000-0002.ogg"]「…」[sv][p]
-0000_e1a1df09_2090_499b_995d_73e683355fac|
[cm]
5日前、たまたま恵がカレーライスを作ったのが全ての始まりだった。[r]
妙にヒットしてしまったらしいエイラは、以来、毎日のようにカレーを[r]
ねだってくるようになった。[p]
-0000_43f79016_ec52_4e00_bfc9_db2eebd24e54|
[cm]
毎日はさすがに飽きるだろうと、野菜カレーとかシーフードカレーとか[r]
恵が変化をつけてくれたのだが、これが完全に裏目。[r]
エイラをますますカレーにのめり込ませる結果になってしまった。[p]
-0000_ef4fa0ff_2df7_4148_8dc5_629a1ae82db1|
[cm]
もちろん大学でも昼食はカレーライスだ。[r]
学食はとうに制覇、今や近隣の店にまで出向く始末。[r]
これで俺が同伴でなければ好きにしてくれと言うところなんだが…。[p]
-0000_c36bfc18_b20a_4f71_a3de_9427df86da16|
[cm]
ヨーヨーカレーのスイートクラスの量は凄まじいの一言だった。[p]
;※口元で手を組むエイラ
-0000_30250f17_3987_433c_806e_a7e455198140|
[cm]
[nowait]【エイラ】[r][endnowait]
[pv b=1 s="E-0000-0002.ogg"]「お願い」[sv][p]
-0000_249a306c_5298_4fc8_b6f5_cc89afd9cb21|
[cm]
[nowait]【琢己】[r][endnowait]
「う…」[p]
-0000_3fd53b9d_ab4a_46a0_b19d_1a20db1e0210|
[cm]
[nowait]【恵】[r][endnowait]
[pv b=2 s="M-0000-0003.ogg"]「兄さんってエイラの『お願い』に弱いよねー」[sv][p]
-0000_e7f82e8e_1feb_468d_a93c_66e35d922759|
[cm]
[nowait]【琢己】[r][endnowait]
「…」[p]
-0000_9d54af19_d452_496d_9d8b_d581d8b7cabe|
[cm]
あんな風にすがるように見つめてくるんだもんなぁ。[p]

台本

O's Editor 2版

xml2script.ps1で作成されたO's Editor 2用台本ファイル(.txt)は以下のようになる(一部のみ)。

『夜間中波DX』
□遠方のAMラジオを聴く
○居間、夕方
琢己「えーと、今晩は全国的に晴れか…もしかしたら聴けるかもしれないぞ?」
エイラ「…本当?」
琢己「まぁ、あまり期待しないで待ってろ」
エイラ「?」
母さんと一緒に新聞のラジオ欄を読んでいるから何かと思えば、今晩、ラジオなにわの「アニメ宝箱」でエイラお気に入りの声優、中畑均(渋い…)がゲスト出演すると知って、ぜひ聴きたいのだとか。
関西のAMラジオ局など関東の新聞に掲載されているはずがなく、なぜ載ってないのか、聴けないのか、母さんに訊いていたらしい。
○ベランダ、20:45頃、晴れ
※ノイズ混じりのAMラジオ放送が鳴っている
エイラ「なぜ関西のラジオ番組が聴こえるのですか? ここは関東なのに」
琢己「夜になると電離層がAMラジオ放送の電波を反射するんだ。でAM放送が遠くまで届くらしい。…ノイズが多いな。ちょっと待ってろ」
※部屋から出て行く足音。しばらくして部屋に戻ってくる足音
エイラ「…この金網みたいなものは何ですか?」
琢己「ループアンテナ。こいつをラジオに繋げて感度を上げるんだよ」
感度最強と名高い瑞穂エレクトロニクスのループアンテナだ。加えて中波(AM)最強と名高い関東通信工業のラジオ。この組み合わせでダメなら諦めるしかない。
※徐々にノイズが少なくなる
アナウンサー「…いて天気予報です。関西地方の明日の天気は…」
エイラ「すごい!!」
琢己「よっし」
※時報
パーソナリティ「土曜日夜の超無計画番組・アニメ宝箱!」
※BGM
パーソナリティ「今晩のゲストは中畑均さんでーす!」
中畑「こんばんはー《渋い声で》」
エイラ「きゃー♪」
うれしそうだなぁ。

oseditor2.jpg

pLaTeX版:藤田眞作氏のfurikana.sty使用

xml2script.ps1で作成されたpLaTeX用台本ファイル(.tex)は以下のようになる(一部のみ)。pLaTeX版は、設定ファイルの$ACTOR_PREFIXを頼りに各声優用の台本と、完全版の台本を出力する。別途CTANのindent.styが必要。

%
% DVIファイルを得るには、コマンドプロンプトから以下のコマンドラインを2回実行する(2回実行しないと目次が出力されない)
%     platex サンプルシナリオ_エイラ役用.tex
% PDFファイルを得るには、コマンドプロンプトから以下のコマンドラインを実行する
%     dvipdfmx -l サンプルシナリオ_エイラ役用.dvi
% 以下のパッケージが利用可能な状態になっていること
%     furikanaパッケージ(http://xymtex.com/fujitas2/texlatex/)
%     indentパッケージ(http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=indent)
%
\documentclass[12pt,a4j,landscape,titlepage]{tarticle}  % 一段組み、A4、横置き、片面印刷
% ページレイアウトの設定(tarticleでgeometryパッケージを使うとエラーになる)
\setlength{\topmargin}{18mm}
\addtolength{\topmargin}{-1in}
\setlength{\headheight}{7mm}
\setlength{\headsep}{5mm}
\setlength{\footskip}{12mm}
\setlength{\oddsidemargin}{18mm}
\addtolength{\oddsidemargin}{-1in}
\setlength{\textheight}{260mm}
\setlength{\textwidth}{150mm}
% 傍注を使わないので\marginparpush, \marginparsep, \marginparwidthも設定していない
\usepackage{indent}	% http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=indent
\def\target{エイラ}	% 台詞出力時、目立たせる人物名を {} 内に記入(目立たせる必要がなければ \def\target{} とする)
%
% \eventマクロ
%
% 使い方:
%   \event{シナリオID}{シナリオテキスト名}{イベント名}
%
% 概要:
% ‐シナリオIDとイベント名を出力する(セクション扱い)
% ‐右ヘッダにイベント名を出力する(fancyhdrを縦組みで使うと\leftmarkが正しく出力されない…)
% ‐中ヘッダにシナリオテキスト名を出力する
%
\newcommand{\event}[3]{%
  \section{[#1]\ #3}%
  \chead{#2}%
  \rhead{\arabic{section}.\ #3}%
}
%
% \sceneマクロ
%
% 使い方:
%   \scene{柱}
%
% 概要:
% ‐柱を出力する(サブセクション扱い)
%
\newcommand{\scene}[1]{%
  \subsection*{#1}%
}
%
% \speechマクロ
%
% 使い方:
%   \speech[演技指導]{ボイスID}{人物名}{台詞} …演技指導ありの場合
%   \speech{ボイスID}{人物名}{台詞}           …演技指導なしの場合
%
% 概要:
% ‐台詞を出力する
% ‐人物名が \target と同じ場合、ボイスIDを出力し、台詞の文字を大きくし、角の丸い矩形で囲む
% ‐人物名の長さによって文字サイズ、表組みのセル高さを変更する
%     4文字以下は\normalsize、5文字以上は\footnote、8文字以上は\scriptsize
%       文字サイズは\adjustsizeマクロで、表組みのセル高さは\adjustheightマクロで調整している
%     人物目の長さは12文字までなら改行なしに出力できる(13文字以上だと改行されてちょっとみっともない)
%
\makeatletter
\newcommand{\adjustheight}[1]{%
  \@tempcnta=0%
  \@tfor\member:=#1\do{\advance\@tempcnta 1}%
  \ifnum \@tempcnta>9 \begin{tabular}{p{13mm}p{32mm}p{85mm}} \else \ifnum \@tempcnta>6 \begin{tabular}{p{13mm}p{27mm}p{90mm}} \else \ifnum \@tempcnta>4 \begin{tabular}{p{13mm}p{22mm}p{95mm}} \else \begin{tabular}{p{13mm}p{17mm}p{100mm}} \fi \fi \fi%
}
\newcommand{\adjustsize}[1]{%
  \@tempcnta=0%
  \@tfor\member:=#1\do{\advance\@tempcnta 1}%
  \ifnum \@tempcnta>7 \textgt{\scriptsize{#1}} \else \ifnum \@tempcnta>4 \textgt{\footnotesize{#1}} \else \textgt{#1} \fi \fi%
}
\makeatother
\newcommand{\speech}[4][.]{%
  \def\speeker{#3}%
  \ifx \speeker\target \begin{screen} \fi%
  \adjustheight{#3}%
    \ifx \speeker\target \texttt{\scriptsize{#2}} \else \ \fi & \adjustsize{#3} & \ifx \speeker\target \large{#4} \else #4 \fi \ifx .#1 \else \scriptsize{《#1》} \fi \\%
  \end{tabular}%
  \ifx \speeker\target \end{screen} \fi%
}
%
% \narrationマクロ
%
% 使い方:
%   \narration{地の文}
%
% 概要:
% ‐地の文を出力する
%
\newcommand{\narration}[1]{%
  \begin{indentation}{13zw}{0zw}%
  \footnotesize{#1}%
  \end{indentation}%
}
%
% \directionマクロ
%
% 使い方:
%   \direction{演出指示}
%
% 概要:
% ‐演出指示を出力する
%
\newcommand{\direction}[1]{%
  \begin{indentation}{13zw}{0zw}%
  \textgt{\scriptsize{※#1}}%
  \end{indentation}%
}
\usepackage{furikana}	% http://xymtex.com/fujitas2/texlatex/
\usepackage{ascmac}
\usepackage{lastpage}
\usepackage{fancyhdr}
\setlength{\headwidth}{\textheight}	% 縦組み時の不具合に対処(http://oku.edu.mie-u.ac.jp/~okumura/texfaq/qa/32033.html)
\pagestyle{fancy}
\lhead{サンプルシナリオ}
\chead{}
\rhead{}
\lfoot{\thepage{}/\pageref{LastPage}}
\cfoot{}
\rfoot{2010/11/20 04:48}
\renewcommand{\headrulewidth}{0.4pt}	% ヘッダ側横線
\renewcommand{\footrulewidth}{0.4pt}	% フッタ側横線
% 以下は http://xymtex.com/fujitas2/texlatex/tateyoko/daihon.sty から拝借したマクロ
\makeatletter
%
% 目次の出力様式
%
\def\l@section{\@dottedtocline{1}{1zw}{5zw}}
\def\l@subsection{\@dottedtocline{2}{2zw}{6zw}}
%
%目次の三点リーダー
%藤田眞作「LaTeXまくろの八衢」
%アジソンウェスレイジャパン(1995)第19章参照
%
\def\@dottedtocline#1#2#3#4#5{%
  \vskip\toclineskip \@plus.2\p@%
  {\leftskip #2\relax \rightskip \@tocrmarg \parfillskip -\rightskip
    \parindent #2\relax\@afterindenttrue
   \interlinepenalty\@M
   \leavevmode
   \@lnumwidth #3\relax
   \advance\leftskip \@lnumwidth \hbox{}\hskip -\leftskip
    {#4}\nobreak
 \leaders\hbox to 0.33333zw{\hfil\raise.26zw\hbox{.}\hfil}%
     \hfill \nobreak\hbox to\@pnumwidth{%
         \hss\reset@font\rmfamily\small \normalcolor #5}\par}}
\makeatother
\begin{document}
\title{サンプルシナリオ \\ \large{エイラ役用}}
\author{foo}
\date{平成\rensuji{22}年\rensuji{11}月\rensuji{20}日}
%\date{平成22年11月20日}
\maketitle
\tableofcontents
\newpage
\input{0000.tex}	% 0000.texをインクルード
\input{0010.tex}	% 0010.texをインクルード
\end{document}
\event{0010}{0010.txt}{夜間中波DX}
◆遠方のAMラジオを聴く
\scene{居間、夕方}
\speech{0010-0001}{琢己}{えーと、今晩は全国的に晴れか…もしかしたら聴けるかもしれないぞ?}
\speech{0010-0001}{エイラ}{…本当?}
\speech{0010-0002}{琢己}{まぁ、あまり期待しないで待ってろ}
\speech{0010-0002}{エイラ}{?}
\narration{母さんと一緒に新聞のラジオ欄を読んでいるから何かと思えば、今晩、ラジオなにわの「アニメ宝箱」でエイラお気に入りの声優、中畑均(渋い…)がゲスト出演すると知って、ぜひ聴きたいのだとか。}
\narration{関西のAMラジオ局など関東の新聞に掲載されているはずがなく、なぜ載ってないのか、聴けないのか、母さんに訊いていたらしい。}
\scene{ベランダ、20:45頃、晴れ}
\direction{ノイズ混じりのAMラジオ放送が鳴っている}
\speech{0010-0003}{エイラ}{なぜ関西のラジオ番組が聴こえるのですか? ここは関東なのに}
\speech{0010-0003}{琢己}{夜になると電離層がAMラジオ放送の電波を反射するんだ。でAM放送が遠くまで届くらしい。…ノイズが多いな。ちょっと待ってろ}
\direction{部屋から出て行く足音。しばらくして部屋に戻ってくる足音}
\speech{0010-0004}{エイラ}{…この金網みたいなものは何ですか?}
\speech{0010-0004}{琢己}{ループアンテナ。こいつをラジオに繋げて感度を上げるんだよ}
\narration{感度最強と名高い瑞穂エレクトロニクスのループアンテナだ。加えて\kana{中波}{AM}最強と名高い関東通信工業のラジオ。この組み合わせでダメなら諦めるしかない。}
\direction{徐々にノイズが少なくなる}
\speech{0010-0001}{アナウンサー}{…いて天気予報です。関西地方の明日の天気は…}
\speech{0010-0005}{エイラ}{すごい\rensuji{!!}}
\speech{0010-0005}{琢己}{よっし}
\direction{時報}
\speech{0010-0001}{パーソナリティ}{土曜日夜の超無計画番組・アニメ宝箱!}
\direction{BGM}
\speech{0010-0002}{パーソナリティ}{今晩のゲストは中畑均さんでーす!}
\speech[渋い声で]{0010-0001}{中畑}{こんばんはー}
\speech{0010-0006}{エイラ}{きゃー♪}
\narration{うれしそうだなぁ。}
\newpage

platex.jpg

ボイス用音声ファイル一覧表

xml2voicelist.ps1で作成されたボイス用音声ファイル一覧表(.csv)は以下のようになる(一部のみ)。

"タイトル","シナリオテキスト","音声ファイル名","セリフ"
"サンプルシナリオ","0000.txt","E-0000-0001.ogg","【エイラ】いえ! ぜひカレーで!!"
"サンプルシナリオ","0000.txt","E-0000-0002.ogg","【エイラ】お願い"
"サンプルシナリオ","0010.txt","E-0010-0001.ogg","【エイラ】…本当?"
"サンプルシナリオ","0010.txt","E-0010-0002.ogg","【エイラ】?"
"サンプルシナリオ","0010.txt","E-0010-0003.ogg","【エイラ】なぜ関西のラジオ番組が聴こえるのですか? ここは関東なのに"
"サンプルシナリオ","0010.txt","E-0010-0004.ogg","【エイラ】…この金網みたいなものは何ですか?"
"サンプルシナリオ","0010.txt","E-0010-0005.ogg","【エイラ】すごい!!"
"サンプルシナリオ","0010.txt","E-0010-0006.ogg","【エイラ】きゃー♪"
> ,"","8",""

ダウンロード*7

動作環境

  • WindowsXP SP3
  • .NET Framework 4
  • Windows PowerShell 2.0
  • W32TeX

W32TeXセットアップ手順

HDD容量に2GB以上の余裕があるなら、TeXインストーラ3を使うのが手っ取り早い。

  1. あべのりページサイトのTeXインストーラ3ページから、最新版のTeXインストーラ3(0.81r2)をダウンロードし、解凍
  2. 管理者権限のあるユーザーアカウントでabtexinst.exeを実行し、案内に従ってインストールする
    • インストール時、必要なアーカイブをダウンロードするタイプなのでインターネットに繋がっている必要がある
    • dviout for Windows 3.18.1は複数ユーザーアカウントに対応していないようで、インストール時とは異なるユーザーアカウントでdvioutを実行すると、DVIファイルが正しく表示されない
      • [Option‐Setup Parameters]メニューから[DVIOUTのプロパティ]を開き、設定内容を丸写しすると良い

必要なスタイルファイル(indent.sty、furikana.styなど)をダウンロードし、インストールする。以下は、W32TeXのインストール先がC:\w32texだった場合の例。それ以外のフォルダ/ドライブにインストールした場合は、C:\w32texを読み替えること。*8

  1. エクスプローラでC:\w32tex\share\texmf-localフォルダ下にctanフォルダ、fujitasフォルダを作成する(どういうフォルダ構成にするかは好みで)
  2. ctanフォルダ下にindent.styをコピー
  3. fujitasフォルダ下にfurikana.styその他をコピー(furikana.styだけあれば良いはず)

スタイルファイルが正しくインストールされているか確認するため、コマンドプロンプトを起動し、以下のコマンドラインを入力する。

kpsewhich indent.sty furikana.sty

以下のようにスタイルファイルのフルパスが出力されていれば、pLaTeXがスタイルファイルの所在を識別できていることが判る(\は/で表示されるので注意)

c:/w32tex/share/texmf-local/tex/ctan/indent.sty
c:/w32tex/share/texmf-local/tex/fujitas/furikana.sty

OMakeによる自動化

pLaTeX版台本を出力する場合、OMakeを使えば、dvi/pdf化が自動化できて便利である。

OMake 0.9.8.5インストール後、コマンドプロンプトを起動し、以下のコマンドラインを入力する。ここで C:\Sample\output とは設定ファイルの $SCRIPT_FOLDER の値を意味している(各自の環境に応じて読み替えること)。

cd /d C:\Sample\output
omake --install

出来たOMakefileをテキストエディタで開き、以下のように修正する。なお、日本語が含まれる場合は文字コードをShift JISにする。

LATEX = platex
TETEX2_ENABLED = false
DVIPDFM = dvipdfmx
DVIPDFMFLAGS = -l
TEXDEPS = 0000.tex 0010.tex 1000凡例.tex
LaTeXDocument(サンプルシナリオ_完全版, サンプルシナリオ_完全版)
.DEFAULT: サンプルシナリオ_完全版.dvi サンプルシナリオ_完全版.pdf
  • LaTeXDocument()関数の第一引数はLaTeXドキュメント名、第二引数はLaTeXファイル名(いずれも拡張子なし)を指定する
  • TEXDEPS にはLaTeXファイル名が依存(内部でインクルード)しているLaTeXファイル名を指定する

続けてコマンドプロンプトで以下のコマンドラインを入力する。

omake -P --verbose

以降、texファイルが変更されるたびに自動的にdvi/pdfファイルが生成されるようになる。

参考


*1 最も理想的なのは「スクリプト化作業そのものがなくなる」こと、つまりシナリオ=スクリプトとなることだ。KAGEXはこちら側のアプローチを採用している。
*2 と言うか、改造・拡張しないと使い物にならない。
*3 この手のツールは別に珍しいモノでも何でもない。シナリオライターとスクリプターを擁する制作チームなら、多かれ少なかれ類似のモノを用意しているはずだ。
*4 シナリオライターとは難儀なもので、改行位置はおろか、句読点の置き方一つ取っても凄いこだわりがあるのに、スクリプター側から「この書式に合わせて下さい」といくら懇願しても守ってくれない人がいたりする…。
*5 PowerShellモジュールという形で実装しているため、例えばNScripter用モジュールなども簡単に追加できるはずだ。
*6 マクロpv, svは「KAG System リファレンス」の「TJSをもっと使うために」で紹介しているpv, svマクロを想定している(実際にこんな出力にすることはないと思うが例ってことで…)。
*7 行き当たりばったりで実装しているため、将来、仕様を大きく変更する可能性がある。その旨を理解した上で利用されたい。
*8 .insファイルが添付されている場合、インストール手順は異なるので注意。
*9 フルインストール時、ディスク容量を約1GB(内ダウンロードファイル約300MB)消費する。フルインストールする際には、2GB程度のディスク空き容量があった方が良いだろう。