シルバーウィークに、脚本エディタをMacとWindowsのアプリにした
20年以上Webで動かしてきた脚本エディタを、AIと一緒にMac(Swift)とWindows(Tauri)のアプリにした。縦書きで打てる欄と日本語入力に2日間振り回された。GitHubで公開中のフリーウェア、いまβ7。
シルバーウィークが終わる。前半は集落の行事でバテバテになり、後半はほとんどMacの前で脚本エディタを作っていた。
今回はNGWの話ではない。まったく別の、ずっと昔からの付き合いの話である。
劇団と、20年もののCGI
地元で友人たちと劇団を立ち上げて、もう40年以上になる。私の担当は音楽とWEBである。脚本は書かない。書くのは、小学校からの同級生の天才脚本家だ。
この男、若い頃から紙に文字を書くより、キーボードを打つほうが好きなタイプなのである。ワープロを買ったのも、まわりの誰よりかなり早かった。
20年以上前のある日、その脚本家から「どこにいても脚本を書けるソフトはないか」と言われた。探した。いいのが無かった。無いなら作るしかない。「どこにいても」がキーワードで、インターネットを使えば、それができる環境がもう手の届くところにあった。家でも稽古場でも出先でも、ブラウザさえあれば同じ脚本の続きが書ける。そうやってできたのが ScenarioWriter である。
最初の版は2004年、PerlのCGIだった。文字コードはShift_JIS、データはCSVみたいなテキストファイル。いま見ると化石のようなものだが、これが2024年まで20年間ちゃんと現役で動いていたのだからエライ。途中でPHP+MySQLの公開サービスにも作り替えて、劇団の仲間や、よそで脚本を書いている人たちにも使ってもらっていた。
この9月には、そのWeb版をPHP 8とSQLiteに載せ替えてGitHubで公開し、劇団の何人かで一緒に書ける「コラボ版」も派生させた。ここまでで1週間。われながらずんずん進んだ。
ところが、である。ひとりで使うだけなのに、手元で動かすにはPHPが要る。MAMPを入れたり php -S を叩いたり。脚本を書きたい人にそんなことをさせてはいけない。ひとり用ならWebサーバもログインも要らないはずなのだ。
20年前の「どこにいても」はWebで叶えた。いまはノートパソコンを持ち歩く時代で、今度は「サーバが無くても」書けるほうがいい。というわけで、ネイティブアプリにすることにした。
35分でDMGが出た、そこから2日かかった
9月22日の昼前、AIに「このWeb版をSwiftでMacのアプリにしたい」と頼んだ。35分後には、1.0.0のDMGができていた。 Web版と同じ形のデータ、全角化、禁則、和暦、テキストとWordとXMLの書き出しまで入っている。むむむ、と唸った。
しかし、そこからが長かった。時間を食ったのはほぼ全部、次の3つである。
- 縦書きで入力できる欄
- 日本語入力(IME)
- SwiftUIのレイアウト計算の往復
脚本は縦書きで読むものだ。印刷した台本は右から左へ、列が並ぶ。だから縦書きのまま打てることがこのアプリの目玉で、同時に一番の泥沼だった。

横書きにもボタンひとつで切り替わる。

落とし穴をいくつか
全部書くと本が1冊できてしまうので、印象に残ったものだけ。
Web版の作品を取り込んだら、台詞の本文が途中から空っぽ。 Web版のSQLiteはWALモードで、最近の更新が swdata.sqlite-wal という隣のファイルに残っていた。本体だけ読むと、行はあるのに中身が古い。本体と -wal を一緒に一時フォルダへ写してから開くようにして、20年分の作品がようやく全部、本文付きで入った。
日本語を打っている最中に落ちる。 変換中の文字があるのに、SwiftUIが画面の更新で文字列を差し替えにいって、AppKitが「おいおい」と例外を投げていた。直したらまた落ちた。今度は文字の大きさを測るためだけに裏で持っていた見えない入力欄が、IMEのセッションを横取りしにいっていた。測るだけなら入力欄は要らない、というので、計測は画面を持たない仕組みに替えた。
全画面から戻すと30秒固まる。 縦書きの列を「右から左」に並べる設定にしていたら、SwiftUIが見えていない列まで律儀に作っていた。数えたら、全画面に入るだけで入力欄が123個増えていた。400行ある場面なら400行ぶん作り直す。そりゃ固まる。列の位置を自前で計算して、見えている範囲だけ作るようにしたら6個になった。
取り込んだ作品を開くと固まる(公開した直後に見つかった)。 SwiftUIに「あなたの幅はいくつ?」と聞かれた本文欄が、提案された幅をそのままオウム返ししていた。すると親が462ptと328.5ptの2つの幅で交互に測り直し、永遠に終わらない。普段は数百回で済む計測が、数十万回。SwiftUIに幅を聞かれたら、オウム返ししてはいけない。 今回いちばん身に沁みた教訓である。
⌘⏎で行を足すと、画面が280pt飛ぶ。 これは原因が分かるまでが面白かった。後の節に書く。
Windows版は「形式」ではなく「欄」で決まった
Macで動いたら、Windowsでも使いたくなる。役所や学校で使ってもらうなら、なおさらWindowsは外せない。
ここで私は「作品ファイルをSQLiteにこだわる必要ある? 独自形式でいいんじゃない?」と言った。それで作品ファイル(.scwd)の中身をJSONにした。一方でAIは「Windowsの本当の壁は形式ではなく、縦書きで入力できる欄です」と言った。WPFにもWinUIにもFlutterにもQtにも、縦書きで打てる入力欄が無い。あるのはHTMLだけ。
だからWindows版はTauri(中身はWebView2)にした。縦書きはCSSの writing-mode: vertical-rl で打てる。Rustで書いたのはファイルの読み書きのところだけで51行、あとは全部TypeScriptだ。しかもMac上でクロスビルドして、Windowsの実機には一度も触らずにインストーラまで出てきた。

「私の直感」と「AIの指摘」の両方がそろって、初めて「JSON+Tauri」が決まった。どちらか片方だけだったら、たぶんWindows版はまだ「開発予定」のままだったと思う。
役所でも使える、と思う
脚本エディタというと劇団専用に聞こえるが、実はそうでもない。
役所のイベント関連の部署は、意外とアナウンス原稿を書く。式典の司会台本、祭りの場内放送、表彰式の進行表。「誰が」「何を言う」「そのとき音響は」「照明は」を行ごとに並べるのは、まさに脚本そのものなのである。学校の学芸会や卒業式、地域の団体の行事にも使えると思う。もちろん普通の劇団や、映像の脚本家にも。
Wordで書き出せば、そのまま配れる台本になる。インストールも登録もいらない。
配布の中身
GitHubで公開しているフリーウェアである。 → ICTCacao/ScenarioWriterSolo
いまのバージョンはβ7。Mac版はDMG(アプリ・見本の作品・マニュアルPDF入り)、Windows版はインストーラと、インストール不要の単体exe。見本の作品「夕暮れの谷」は架空の一幕三場の小品で、台詞・ト書・歌詞・テロップ・音響・照明・フェードを一通り使っているので、まずこれを開いて触ってみてほしい。
Windows版は署名していないので、SmartScreenに止められたら「詳細情報 → 実行」で進む。ここは正直に書いておく。
これから色々フィードバックをもらいながら、正式版にしていきたい。使ってみて「ここが変だ」「これが欲しい」があれば、ぜひ教えてほしい。
数字で見る
| 項目 | 値 |
|---|---|
| 最初のPerl版から | 22年(2004年〜) |
| 依頼から最初のDMG | 約35分 |
| 依頼からβ7 | 2日(コミット17) |
| Mac版 Swift(アプリ / コア / テスト) | 4,537 / 2,511 / 213行 |
| Windows版 TypeScript / Rust | 1,496 / 51行 |
| データの持ち方の変更 | 4回(最後はJSON) |
| 全画面の出入りで作られた入力欄 | 123個 → 6個 |
| 固まった作品の計測回数 | 数百回 → 数十万回 → 数百回 |
| ⌘⏎で飛んだ幅 | 280pt |
| 配布物 | DMG 6.2MB、setup.exe 1.4MB、単体exe 4.5MB |
AIとの協働作業での学び
素朴な質問が設計を変えた。 途中で「保存は自動保存ですか?」「⌘Zはどこまで効きますか?」と聞いた。AIは「データベースに即時書き込んでいるので、構造的な操作は戻せません」と正直に答えた。そこから「見えない作業用コピーで編集して、⌘Sで本ファイルに書くのは?」→「書類アプリの常識どおりにします」と進んだ。仕様書を書くより、使う人の疑問を投げたほうが早い。
目はAI、手は人間。 ⌘⏎で画面が280pt飛ぶ件は、最初「アプリの補正がおかしい」のか「AppKitがカーソルを見せようとした」のか分からなかった。画面収録を見せ、AIがスクロールを全部ログに出すビルドを作り、私が⌘⏎を押して「押した」と返す。この往復を何度かやって、縦書きの画面がサイドバーの下まで広がっていて、左に280ptの余白ぶん数え方がずれていたと分かった。AIは私のウインドウを動かせない。私はログを読むのが遅い。役割を分けたら決着した。
古いビルドを見て「直ってない」と言っていた。 何度か「まだ直ってない」と文句を言ったら、私が古いアプリを開いていただけだった。フリーズのレポートもデバッグ用のビルドだった。むむむ。「どのバイナリを見ているか」を先に揃える。 人間のほうが間違えるのである。
AIの確認作業が、私の環境を踏んだ。 動作確認のスクリプトが、私が使っていた同じアプリを終了させたり、「最近使った作品」の一覧を撮影のたびに消したりした。以後は「起動中なら待つ、勝手に終了させない」「退避してから撮って、戻す」をルールにした。貼ったクラッシュレポートの1件は、AI自身の自己テストが出したものだった。
「確かめていないこと」を毎回書いてくる。 「Windowsの実機ではまだ一度も動かしていません」「IMEで実際に打つ確認はできていません」。報告の最後のこの一行が、そのまま私が次に試すことの一覧になった。
モデルが替わっても続きが書ける。 1日目と2日目で違うモデルが相手だったが、リポジトリとコミットメッセージとメモを読んで、何事もなかったように続きから書いてくれた。台本と同じで、ちゃんと書き残しておけば、役者が替わっても芝居は続くのである。