Refactoring English: Month 9

Michael Lynch

Refactoring English:9か月目

一言でいうと

動画インタビュー編集の楽しさと苦しさについてです。

ハイライト

  • 章構成について、初期の読者の方々から有益なフィードバックをいただきました。
  • インタビュー動画の編集には手を焼きましたが、書き起こしの作成は楽しく取り組めました。
  • フリーランスのブログ編集サービスを宣伝する計画が、想像以上にうまくいきました。

目標の振り返り

毎月のはじめに、その月に達成したいことを宣言しています。結果は次のとおりでした。

これまで話したことのない読者20人にパーソナライズしたメールを送る

何人かの読者と話す中で、現段階では個別にメールを送るよりも、すべての読者に向けた幅広いアンケートを取った方がよいと気づきました。

Refactoring Englishの新しい章を公開する

  • 結果:「Get to the Point」を公開しました
  • 評価:A

ようやく導入部についての章を書き終えました。この章が一番書くのが大変でした。導入部は私自身が文章を書くうえで最も苦手としている部分だからです。つまりこの章は、導入そのものであると同時に、自分がどうやって導入を書いているかをリバースエンジニアリングする試みでもありました。

この章には予算を大幅にオーバーしてしまいました。当初は6時間で終える予定でしたが、実際には19時間もかかってしまいました。

残りのマーケティングタスクを完了する

  • 結果:インタビューの編集は終えましたが、コール・トゥ・アクションには着手できませんでした
  • 評価:B+

大きな残タスクだったインタビューの編集は終えました。一方で、書籍サイトのデザインを、無料メーリングリストへの登録ではなくアーリーアクセスの購入を前面に出す形へ変更する作業には、まだ手をつけられていません。

Refactoring Englishの指標

指標2025年7月2025年8月変化
ユニーク訪問者数8,0612,863-5,198 (-64%)
予約販売による収益$800.04$312.63-$487.41 (-61%)
スポンサー収益$48.25$48.25$0.00 (0%)
収益合計$848.29$360.88-$487.41 (-57%)

先月は、書籍の指標は健全だと思っていました。新しい人気記事がないにもかかわらず、サイトへの訪問数も収益も増加していたからです。

その後、指標をグラフ化してみると、違う傾向が見えてきました。書籍の収益は、書籍サイトへの訪問者数と密接に連動しているようです。7月は人気記事がなかったと思っていましたが、8月にサイトへ何も公開しなかった途端、指標が急落したのです。

ここから得た教訓は、やはり新しいものをサイトに公開し続ける必要があるということです。そうしなければ新しい読者、とりわけ書籍を購入してくれる読者に出会い続けられません。

章構成に対する読者フィードバックの読み解き

読者の方々と個別に話していると、どの章を重要だと感じるかには大きなばらつきがあると感じました。どの章が最も求められているかを知るには、アンケートを取った方がよいと考えました。

これまでメーリングリストでフィードバックをお願いしても数件しか返事がなかったので、今回も回答率は低いだろうと予想していました。ところが今回は読者の反応がずっと熱心で、2週間で133件もの回答が集まり、驚きました。

回答について詳しく分析した内容は、書籍のウェブサイトに掲載しています。

端的に言うと、有益なフィードバックを得られたおかげで、章の順序を入れ替え、不評だった章の切り口を変えることができました。

今回と過去のフィードバック依頼とで回答率が大きく違ったのも興味深い点でした。以前はサンプル章を送ったうえでフィードバックを求めていました。今回との違いは、読者にお願いする作業量だと思います。今回のアンケートは数分で終わりますが、章へのフィードバックとなると、30分かけて章を読んで考えなければならず、アンケートが届いたタイミングではなかなか手が回らないのかもしれません。

30分の動画インタビュー編集に想像以上に手こずった話

2024年7月、ブログ講座『Hit the Front Page of Hacker News』を再始動させる一環として、Adam Gordon Bellさんにインタビューを収録しました。結局、育児休暇に入る前に講座を完成させられなかったため、再始動は無期限で棚上げになりました。

そのため、このインタビューは宙に浮いた状態になってしまいました。Adamさんはわざわざ時間を割いて協力してくださったのに、一度も公開しないのは申し訳ないと感じていました。

Refactoring English』のアーリーアクセスを提供し始めたとき、このインタビューを公開するのに良いタイミングだと思いました。インタビューを気に入ってくれた方が、書籍にも興味を持ってくれるかもしれないと考えたのです。

いつまでも先延ばしにしているタスクってありますよね。「あんなに長く放置してバカみたいだ、腰を据えてやれば1時間で終わって頭の中から消せるのに」と思うようなタスクです。このインタビューも、きっとそうだと思い込んでいました。

実際はそうではありませんでした。

音ズレという厄介な問題の再来

インタビューの収録にはRiversideというサービスを使いました。通話後、Riversideは通話の両端それぞれの動画ファイルと、会話を同期して結合したバージョンを生成してくれます。当時はざっと確認して動作することを確かめただけで、じっくりは見ていませんでした。

作業としては、結合済みのバージョンをそのままYouTubeに上げるだけで済むと思っていました。もし中断や長い脱線があればカットするかもしれませんが、ほぼ完成しているはずだと考えていました。

1年後にようやく動画をじっくり見返してみると、音声と映像がズレていることに気づきました。口の動きよりも先に声が聞こえてしまうのです。

Riversideが生成した動画では、音声と映像がわずかにズレていました。

まあ問題ないだろう、FFmpegで音声を少しずらせば直せると思いました。

ところが、音ズレの量は会話の両端で異なっていました。Adamさん側は約425ミリ秒、私側は約150ミリ秒のズレでした。つまり、元のそれぞれの未結合の動画に戻り、そこでズレを修正してから、自分で再び結合し直す必要があったのです。

使えるオープンソースの動画エディタを探して

私が普段動画編集に使っていたのはAdobe Premiereでしたが、昨年Linuxに乗り換えてからは使えなくなりました。PremiereはLinuxに対応していませんし、正直もうAdobeという会社自体にうんざりしていました。

そこで、昨夏から学んでいたShotcutという動画エディタで編集を始めました。Shotcutで動画を横に並べて表示させる方法を理解するだけでも時間がかかりましたが、なんとかズームやクロップのフィルターを駆使してやりくりしました。

Shotcutで編集していると、再生が非常にカクカクしました。比較的新しくハイスペックなデスクトップを使っているにもかかわらず、1080pの動画2本を結合する処理で手一杯になっていたのです。そのため、実際の音を確かめるには動画を書き出す必要がありました。しかもShotcutは動画の一部だけを書き出す機能に対応していないので、毎回30分全体を書き出すことになり、1回につき数時間かかっていました。余談ですが、後になって編集中のプレビューをダウンスケールすれば動作が軽くなることに気づきました。

書き出してみると、クリップを分割するたびに大きな「ポン」というノイズが入ることに気づきました。分割した箇所で何もカットしていなくても起こるのです。ひと続きのクリップを隣り合う2つのクリップに分割しただけで、そのノイズが生じていました。

クリップを分割しただけで何も変更していないのに、音声に「ポン」というノイズが入りました。

このノイズはShotcutの既知の不具合だとわかり、信じられませんでした。分割するたびに耳障りなノイズが入るのに、どうやって動画編集ができるというのでしょうか。ただ、多くのコメントでは、どの動画・音声編集ツールでも同じ問題が起きると書かれていました。

はぁ!?

私はこれまでに他のツールで何百ものメディアファイルを編集してきましたが、クリップを分割しただけでノイズが入ったことなど一度もありませんでした。

Linux向けの他のオープンソース動画編集ツールも試しました。Kdenliveは編集を始めて数分でクラッシュしました。Flowbladeはそもそも起動すらできませんでしたが、なんとか回避策を見つけました。FlowbladeはShotcutよりシンプルに見えたので、また一からFlowbladeで編集をやり直し、横並びの動画を作る方法を調べ直しました。

Flowbladeで1時間ほど編集した後、動画を書き出してみると、また同じノイズが再発しました。Flowbladeでも同様のバグが報告されており、その説明はShotcutの作者であるDan Dennedy氏の解説に基づくものでした。しかもFlowbladeはShotcutを動かしているのと同じメディアフレームワーク「MLT」を基盤にしているようでした。つまり、まったく同じバグに逆戻りしたわけです。

ともあれ、この編集騒動の顛末をこれ以上長々と語っても退屈なだけなので、結論だけ言うと、動画の音声サンプリングレートを44.1 kHzから48 kHzに変換することで、このノイズを回避できました。なぜこれで直るのかは、よくわかりません。

他にも編集中にたくさんのバグに遭遇しましたが、どれも語るにはあまりに地味なので省略します。

動画編集で得た教訓

  • できる限りの前処理はFFmpegスクリプトで済ませておきます。
  • 前処理を後で微調整する必要が出た場合に備えて、FFmpegスクリプトは保存しておきます。
    • たとえ「もう前処理をやり直すことは絶対にない」と確信していても、スクリプトは保存しておきます。できればバージョン管理下に置きます。
  • FFmpegスクリプトが意図どおりに動いているか、極端な値でテストして確認します。
    • 音ズレを200ミリ秒ずらして修正してみましたが、まだズレていました。次に300ミリ秒、さらに400ミリ秒と試しても直りません。最終的に2000ミリ秒にしてみて、200ミリ秒のときとまったく同じに聞こえたことで、スクリプトにバグがあると気づきました。
  • 最適な設定がわからないときは、FFmpegでいくつかのバリエーションを生成して比較できるようにします。
    • 自分の側の会話に入った背景ノイズを除去するさまざまな手法を試す際に、この方法を使いました。
  • 音声サンプリングレートが44.1 kHzだと編集時に問題が起きるようです。
    • 前処理の段階で48 kHzに変換すると、ノイズの問題は解消しました。
    • なぜそうなるのかはわかりません。
  • 編集を始めて間もない段階で一度動画を書き出し、最終的な出力を確認します。
  • 動画・音声のフィルターはクリップ単位ではなくトラック単位で適用します。
    • たとえ最初は巨大なクリップが1つだけだったとしても、編集を進めるとすぐに何十ものクリップに分かれ、それぞれに独立したフィルター設定ができてしまいます。
    • フィルターの設定を間違えたと気づいたとき、すべてのクリップでやり直す羽目になります。

インタビュー書き起こしにハマりすぎた話

Adam Gordon Bellさんとの動画を編集し終えたら、それで終わりのはずですよね。あれだけ時間をかけて編集したのだから、早く公開して終わりにしたかったはずです。

ところが、そうはなりませんでした!

動画の編集が終わると、今度は書き起こしにこだわり始めました。ただ、こちらは本当に楽しく作業できました。

世の中にあるインタビューの書き起こしを見ると、まるで「60年前の法廷のタイプ打ちの書き起こしを、そのままの面白さと操作性でウェブに再現しよう」とでも考えたかのように感じます。

ウェブブラウザを使えば、会話の書き起こしをもっと面白くできるはずだと思いませんか?

せっかくのウェブなのですから、タイプライターではできないことをやってみましょう。

そこで、whisper-ctranslate2で初期の書き起こしを生成し、正確で、インタラクティブで、読んでいて楽しいものにするためにたっぷり時間をかけました。

インタビューの書き起こしを楽しく読めるように、小さな工夫を加えました。

  • 会話の両端をそれぞれ色の違う吹き出しで表示し、誰が話しているかが一目でわかるようにしました。
  • 各吹き出しには小さな再生ボタンがあり、クリックするとページが動画の該当箇所までスクロールし、書き起こしのその時点から再生が始まります。
  • お気に入りの引用を抜き出してコールアウトとして配置しました。
  • 議論の構造がわかるように見出しを加えました。
  • 書き起こしの誤りをチェックして修正しました。

動画はまだ公開していません。というのも、金曜日にメーリングリストの購読者の方々へ新しい章を送ったばかりだからです。今週末(2025-09-12)までに、書籍のブログで公開する予定です。

Tyler Ciprianiさんの記事をHacker Newsで1位にするお手伝い

ときには、計画が予想以上にうまくいくこともあります。

実際の書き手にフィードバックをすることで本の執筆にも役立つので、インディー開発者のブロガーの方々向けにフリーランスで編集の仕事をしています。編集サービスを紹介するページに、自分の編集事例を載せたいと思いましたが、すでにお金を払ってくれたクライアントの成果物を、自分の宣伝のために使わせてほしいと頼むのは気が引けました。

そこで考えたのが、無料で記事を編集させてもらい、その代わりに編集メモを公開し、相手に編集者としてクレジットを入れてもらうという方法でした。

欲張った目標としては、その記事がHacker NewsやLobsters、redditなど、書籍の潜在的な読者が集まる場所で注目されることでした。記事を最後まで読んだ人が「Edited by Refactoring English」と目にして、「おや、これは何だろう?」と思ってくれればと考えたのです。

また、過去のクライアントを指して「この方は私に依頼し、あなたが目指す場所で成果を出しました」と言えれば、将来のクライアントに対しても良いアピールになります。

数か月前、Tyler Ciprianiさんからブログ全体への高レベルなレビューを依頼されました。結果に満足していただけたようだったので、この無料編集のアイデアを提案してみたところ、快諾してくれました。

Tylerさんとは、彼の記事「The future of large files in Git is Git.」について何度かフィードバックを重ねました。一緒に作業するのは楽しく、本の執筆にも良いヒントをもらえました。

ボーナス目標はHacker Newsのフロントページに載ることでしたが、結果はそれを大きく上回り、Hacker Newsで1位、さらにLobstersredditでも1位になりました。

二人にとって大きな学びの一つは、文章を読者の対象に合わせて調整することの重要性でした。Tylerさんの記事の初期のドラフトでは、読者がGit LFS(Gitで大きなファイルを扱うための拡張機能)を知っていることを前提にしていました。

私は、平均的なGitユーザーであれば、記事の内容をすべて理解できるほどGit LFSに詳しいわけではないと提案しました。Tylerさんは当初、大きなファイルを扱ったことのある平均的なGitユーザーならGit LFSを知っているはずだと反論しました。

読者が想定以上にGit LFSを知らないことをTylerさんに納得してもらうため、私自身のGit LFSに関する知識と経験を列挙しました。

  • 大きなファイルをGitリポジトリに入れたり、バイナリデータを頻繁に更新したりする場合は、Git LFSを使うべきだと聞いています
  • Git LFSを使ったことはありません
    • Git LFSを使っているオープンソースプロジェクトに1〜2件関わったことはありますが、LFSの部分には一度も触れたことがありません。
  • 各種ホスティングサービス(forge)のサイズ制限は知りませんが、制限に達したらサービス側が警告してくれるだろうし、そのときに対処すればいいと思っています
    • Gitリポジトリに5MBを超えるファイルを置きたいと思ったら、まずはそれを避ける方法を探し始めます
  • Git LFSはどのホスティングサービスでも使える、サービスに依存しない機能だと思っていました。
  • Git LFSは10年以上の歴史があり、成熟して安定している技術だと思っていました。
  • 一度Git LFSを使い始めると、そのリポジトリはGit LFSから抜け出せなくなるとは知りませんでした。
  • Gitで大きなファイルを扱う方法には興味があり、Hacker NewsやLobstersでそういった記事を見つけたらクリックすると思いますが、自分が大きなファイルをリポジトリに置きたいという具体的な状況に直面しない限り、積極的に解決しようとは考えません。

Tylerさんは、このリストが「なるほど」と思える瞬間だったと言ってくれました。それまでは、読者はGit LFSを知っているはずだという自信からフィードバックに抵抗があったそうです。私のリストを見て、読者が表面的にはGit LFSの存在や用途を知っていても、仕組みまでは知らないかもしれないと気づいたのです。

面白いのは、Tylerさん自身でもこのリストを書けたはずだということです。彼は対象読者が何を知っているかについて、私と同じ予測を持っていました。ただ、「知っている」ということが何を意味するのかを、もう一歩深く考える必要があったのです。

サイドプロジェクト

Hacker News Observerを時系列データベースに移行して500倍高速化した話

ここ数年、「時系列データベース」という言葉を耳にしてきましたが、それが何をするものなのか、通常のリレーショナルデータベースとどう違うのかがよくわかりませんでした。昨年もGrafanaと互換性が必要だったため、サイドプロジェクトでInfluxDBを使いましたが、それでもなぜそれが「時系列」データベースなのか、なぜSQLiteではだめなのかが理解できていませんでした。

最近、ある開発者と話していたとき、彼が時系列データベースを使って、秒単位の粒度と日単位の粒度など、データの見せ方を切り替えていると聞きました。詳しい説明はなかったのですが、その一言で頭の中の電球がつき、「ああ、時系列データベースというのはそういうためのものなのか!」と腑に落ちました。

Hacker News Observerは、Hacker Newsを1分ごとにクエリし、過去数週間分のすべてのストーリーについて、アップボート数やコメント数、ランクを記録するサイドプロジェクトです。いずれはもっと深く掘り下げて面白いパターンを見つけたいと思っていますが、今のところはフロントページの総アップボート数や総コメント数といった大まかな集計を見ているだけです。

DuckDBに切り替えたことで、このページの表示が500倍高速になりました

当初はデータベースにSQLiteを使っていて、上のグラフの描画に2分もかかっていました。考えてみれば当然で、1日に何千ものストーリーがあり、各ストーリーについて何千ものスナップショットがあり、そこから各スナップショットで上位30件(フロントページ)を抽出し、さらにそれを1時間単位のバケットにまとめなければなりません。SQLiteには分単位のデータを時間単位のビューに集計するための特別な機能がないため、非常に高コストなクエリになっていました。

時系列データベースのイメージがつかめたので、LLMにSQLiteに近い時系列データベースの選択肢を尋ねたところ、DuckDBを勧められました。そして、そのままLLMにデータベースをSQLiteからDuckDBへ移行させました。この移行だけで、グラフの読み込み時間は2分から250ミリ秒へと短縮され、約500倍の高速化になりました。

なるほど、これが時系列データベースの使いどころというわけですね。

Gleam Chat Log Parserで古いログを少しずつ処理する

チャットログのパーサープロジェクトは、少しずつしか進みませんでした。離席メッセージを含むログや、Windows形式の改行(\r\n)を含むログに対応しました。不思議なことに、Erlang(そしてGleamも)では、\r\nが1文字としてカウントされるため、しばらくハマってしまいました。

まとめ

今月できたこと

学んだこと

  • 動画編集はもっと規律を持って行うこと
  • インタビュー動画の編集は面倒ですが、書き起こしの編集やスタイリングは楽しいということ。
  • 30分の作業を求める場合に比べ、数分で終わる作業であれば、10倍もの人がフィードバックに応じてくれるということ。

来月の目標

  • Refactoring Englishのウェブサイトに新しい読者を呼び込む何かを公開する。
  • Refactoring Englishの新しい章を公開する。
  • これまで話したことのない読者20人にパーソナライズしたメールを送る。

原文は Michael Lynch により に公開されました。

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。