<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>CLI on 思いつきそうで思いつかなくていたときに</title><link>https://blog.fuga.jp/tags/cli/</link><description>Recent content in CLI on 思いつきそうで思いつかなくていたときに</description><generator>Hugo -- gohugo.io</generator><language>ja-jp</language><copyright>Copyright(c) 2022-2025 SATO Daisuke. All rights reserved.</copyright><lastBuildDate>Wed, 26 Aug 2026 06:00:00 +0900</lastBuildDate><atom:link href="https://blog.fuga.jp/tags/cli/index.xml" rel="self" type="application/rss+xml"/><item><title>podcast-tool 開発日記 #12 — 現在形 — 今日のpodcast-tool</title><link>https://blog.fuga.jp/posts/2026-08-26-podcast-tool-devdiary-12-todays-shape/</link><pubDate>Wed, 26 Aug 2026 06:00:00 +0900</pubDate><guid>https://blog.fuga.jp/posts/2026-08-26-podcast-tool-devdiary-12-todays-shape/</guid><description>&lt;p&gt;前回（第11回）は、5月後半にPythonの外へエンジンを持ち出したSwift統合の話だった。動画書き出しを速くする「速さ」の軸を追った回だ。今回はほぼ同じ時期に並行して積まれていた、もう一つの軸を追う。台本を書き終えたあとの「配信物を組み立てる」工程——タイムライン、topics画像、概要欄、リンク——を自動化していく5月末から6月にかけての流れだ。連載はこれで最終回になる。&lt;/p&gt;
&lt;h2 id="7分間で3つの部品が生まれた日"&gt;&lt;a href="#7%e5%88%86%e9%96%93%e3%81%a73%e3%81%a4%e3%81%ae%e9%83%a8%e5%93%81%e3%81%8c%e7%94%9f%e3%81%be%e3%82%8c%e3%81%9f%e6%97%a5" class="header-anchor"&gt;&lt;/a&gt;7分間で3つの部品が生まれた日
&lt;/h2&gt;&lt;p&gt;5月24日の朝、9時44分。&lt;code&gt;bed037b&lt;/code&gt;「timeline_generator モジュール追加（テスト含む）」で、&lt;code&gt;timeline_generator.py&lt;/code&gt;（106行）とテスト163行が追加された。台本や音声セグメントから、動画のタイムライン情報を組み立てるモジュールだ。&lt;/p&gt;
&lt;p&gt;2分後の9時46分、&lt;code&gt;6b6c487&lt;/code&gt;「topics_image_composer モジュール追加（テスト含む）」。こちらは285行、テスト147行というより厚みのある実装で、トピック紹介用の画像を合成する役割を持つ。&lt;/p&gt;
&lt;p&gt;さらに5分後の9時51分、&lt;code&gt;a94cbfa&lt;/code&gt;「CLIに compose-topics-image / timeline-generate サブコマンド追加」で、この2つのモジュールが &lt;code&gt;commands_topics.py&lt;/code&gt; とmain.pyのディスパッチ経由でコマンドラインから呼べるようになった。&lt;/p&gt;
&lt;p&gt;モジュール2本とCLI配線を合わせて7分。第1回で書いた「26分でCLI骨格からVoicevox連携・m4a出力まで到達した」あの初日のスピード感が、11か月後のこの日にも形を変えて残っている。翌25日の&lt;code&gt;43d807f&lt;/code&gt;では、timeline_generatorが&lt;code&gt;speakers.json&lt;/code&gt;を参照して話者を動的に検出するよう手直しが入り、ハードコードだった話者名の扱いが一段汎用的になった。&lt;/p&gt;
&lt;h2 id="16分間で概要欄とリンクが片付いた日"&gt;&lt;a href="#16%e5%88%86%e9%96%93%e3%81%a7%e6%a6%82%e8%a6%81%e6%ac%84%e3%81%a8%e3%83%aa%e3%83%b3%e3%82%af%e3%81%8c%e7%89%87%e4%bb%98%e3%81%84%e3%81%9f%e6%97%a5" class="header-anchor"&gt;&lt;/a&gt;16分間で概要欄とリンクが片付いた日
&lt;/h2&gt;&lt;p&gt;5日後の5月29日、14時46分。&lt;code&gt;9670fc9&lt;/code&gt;「description-generate サブコマンドを追加」。&lt;code&gt;commands_description.py&lt;/code&gt;（37行）が新設され、&lt;code&gt;--template&lt;/code&gt;/&lt;code&gt;--intro&lt;/code&gt;/&lt;code&gt;--timeline&lt;/code&gt;/&lt;code&gt;--links&lt;/code&gt;/&lt;code&gt;--output&lt;/code&gt;の各パスを上書きしながら配信用の概要欄を生成できるようになった。コミットメッセージには「timeline-generateと同じサブコマンド形式」と書かれていて、直前に作ったパターンをそのまま横展開したことが読み取れる。&lt;/p&gt;
&lt;p&gt;14分後の15時00分から15時02分にかけて、今度はリンク周りが一気に片付く。まず&lt;code&gt;21f3871&lt;/code&gt;「is.gd/TinyURLフォールバック短縮を追加」。&lt;code&gt;link_shortener.py&lt;/code&gt;（113行）に実装された&lt;code&gt;shorten_url&lt;/code&gt;は、is.gdを試してダメならTinyURLへフォールバックする2段構え。&lt;code&gt;shorten_links_in_file&lt;/code&gt;は&lt;code&gt;links.source.json&lt;/code&gt;のうち&lt;code&gt;short_url&lt;/code&gt;が未設定の項目だけを短縮して書き戻す、冪等な作りになっている。ネットワークI/Oをこの1ファイルに閉じ込めた設計が意識されている。&lt;/p&gt;
&lt;p&gt;1分後、&lt;code&gt;56adecb&lt;/code&gt;「links.source.jsonからlinks.txt生成を追加」。&lt;code&gt;links_text.py&lt;/code&gt;の&lt;code&gt;render_links_text&lt;/code&gt;が、トピックごとに一次情報→参考情報の順で整形し、短縮URLがあればそちらを優先する。&lt;/p&gt;
&lt;p&gt;さらに1分後、&lt;code&gt;e5a3a45&lt;/code&gt;「links 抽出・短縮・整形サブコマンドを追加」。&lt;code&gt;commands_links.py&lt;/code&gt;（55行）に&lt;code&gt;extract-source-links&lt;/code&gt;・&lt;code&gt;shorten-links&lt;/code&gt;・&lt;code&gt;build-links-text&lt;/code&gt;の3コマンドがまとまり、ここまでの部品がCLIから使える形に組み上がった。&lt;/p&gt;
&lt;p&gt;description生成とlinks処理、合わせて16分。5月24日の7分間burstと合わせると、この時期は「モジュールを書く→即CLIに配線する」を数分〜十数分でこなすリズムが定着していたようだ。&lt;/p&gt;
&lt;h2 id="6月細部を詰める"&gt;&lt;a href="#6%e6%9c%88%e7%b4%b0%e9%83%a8%e3%82%92%e8%a9%b0%e3%82%81%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;6月、細部を詰める
&lt;/h2&gt;&lt;p&gt;6月に入ると、5月末に生まれた仕組みの周辺を締める修正が続く。6月3日には&lt;code&gt;55fc6ba&lt;/code&gt;/&lt;code&gt;c451d12&lt;/code&gt;でcompose-topics-imageの&lt;code&gt;base_dir&lt;/code&gt;解決にフォールバックが入り、パス解決がマシン非依存になった。6月26日の&lt;code&gt;d9ead70&lt;/code&gt;では、descriptionのリンク取得タイトルでHTML実体参照が誤って残る不具合が修正されている。28日には&lt;code&gt;d20fd44&lt;/code&gt;でsource_reportの参考文献URL抽出の不具合が2点直り、同日&lt;code&gt;32abd2e&lt;/code&gt;でパーサと正規化処理が一本化された。&lt;/p&gt;
&lt;p&gt;同じ28日、黒板（&lt;code&gt;@panel&lt;/code&gt;記法）まわりにも手が入った。&lt;code&gt;dfd5f18&lt;/code&gt;「黒板anchor安定化（内容アンカーA改・指紋自動埋め込み）」、続く&lt;code&gt;b592413&lt;/code&gt;「static_checkが黒板指紋(&lt;code&gt;@panel[#xxxx]:&lt;/code&gt;)を取りこぼす不具合を修正」。翌29日の&lt;code&gt;e554e69&lt;/code&gt;では、&lt;code&gt;@panel_close&lt;/code&gt;の書き忘れがそれまで警告どまりだったのを、エラーとして止めるよう昇格させている。第6回で扱ったASS字幕の話者別スタイリングから半年、黒板の配置そのものを機械的にチェックする層が育ってきているのが分かる。前日27日の&lt;code&gt;cc271c3&lt;/code&gt;「監査を『ゲート』化」は、この一連の静的チェックをCIの通過条件として組み込む動きで、後半の回で触れた監査ワークフローの実装側がここでも進んでいる。&lt;/p&gt;
&lt;h2 id="軌跡から見えてくるもの"&gt;&lt;a href="#%e8%bb%8c%e8%b7%a1%e3%81%8b%e3%82%89%e8%a6%8b%e3%81%88%e3%81%a6%e3%81%8f%e3%82%8b%e3%82%82%e3%81%ae" class="header-anchor"&gt;&lt;/a&gt;軌跡から見えてくるもの
&lt;/h2&gt;&lt;p&gt;この連載の起点は、2025年7月11日、&lt;code&gt;pyproject.toml&lt;/code&gt;一つだけのリポジトリだった。単一ファイルの&lt;code&gt;main.py&lt;/code&gt;が295行、依存ライブラリは4つ、その日のうちに音が出た。いま&lt;code&gt;main.py&lt;/code&gt;は316行——分量はほとんど変わっていないが、中身はディスパッチ表だけになり、実際のロジックは&lt;code&gt;src/podcast_tool&lt;/code&gt;配下245個のPythonファイルに散らばっている。第7回で追った近代化リファクタが土台を作り、今回追った5月〜6月の動きは、その土台の上に「配信物を組み立てる」ための部品を一つずつ足していく作業だった。&lt;/p&gt;
&lt;p&gt;構成設計書を書いた6月12日時点でコミット数は1068、そこから今日までにさらに900以上積まれている。休眠期を挟みながらも、月ごとに姿を変えながら11か月ぶん積み上がってきた開発の記録を、この12回で追ってきたことになる。次に見るとしたら、それはまた別の「今日」の話だ。&lt;/p&gt;</description></item></channel></rss>