🎙️ LIFELOG STT Cron フロー
job: lifelog-record-stt-daily
0 1 * * * JST
id: 25fa1a71b018
host: 🟡hermes_micro
ボイスレコーダー(LIFELOG / F:)に溜まった WAV を、毎日 JST 01:00に
耐久 systemd --user ワーカーへ渡す。ローカル Whisper → Buffalo(E:)退避 → zettelkasten要約の後、
completion-monitor が完了結果だけをDiscordへ1回返す流れ。
1. 実機構成(写真)
撮影セットアップ例:上段の黒い筐体に USB 接続されたストレージ群。
青LED点灯=電源/認識中。STT 実行時は E:(Buffalo)を差したまま、
処理後のレコーダー(F:)は抜いて再録音してよい。
| 文字 | デバイス | 役割 |
| F: |
LIFELOG(ACTIONS USB DISK) |
録音本体。入力は F:\RECORD\*.WAV |
| E: |
BUFFALO HD-CD-A |
外部記憶。出力 E:\2026\yyyymmdd\ |
| WSL |
🟡hermes_micro |
cron / ffmpeg / Whisper / Hermes 要約 |
運用メモ
・処理中は E: を抜かない
・RECORD が空になったら F: レコーダーは抜いてOK(再録音)
・Windows 側ドライブは powershell.exe 経由で R/W
2. 全体アーキテクチャ(図)
3. ステップ詳細フロー
Launcher(script-only)
Hermes cron 0 1 * * *(JST 01:00) / job lifelog-record-stt-daily
F: と E: の接続を20秒以内に確認。実処理は systemd-run --user の lifelog-stt-batch.service(最大12時間)へ渡してから即終了。
no_agent: true
runningなら二重起動しない
workdir: lifelog-stt
Discover —
F:\RECORD\*.WAV を一覧
- 書き込み中スキップ(mtime が直近15分以内)
._* / 極小ファイル除外
- すでに STT 済み(state / 既存 txt)はスキップ
Copy → Preprocess
- WAV を WSL staging へコピー(PowerShell)
- ffmpeg: highpass → denoise → silenceremove → loudnorm
- 出力: 16kHz mono PCM(Whisper向け)
STT(local Whisper)
- engine:
faster-whisper / CPU int8
- model: config の
whisper.model_size(運用で small/medium 切替)
- 1 WAV = ちょうど1回(再実行してもスキップ)
- 失敗は state に記録し、その WAV は F: に残す
Write + Move
- 全文:
E:\2026\{yyyymmdd}\{stem}.txt(UTF-8)
- yyyymmdd は WAVファイル名の録音日
- txt が size>0 で成功してから原WAVを同フォルダへ MOVE
- → LIFELOG(F:)の容量を空ける
日次要約(Hermes headless)
- 主:
gpt-5.6-luna → 失敗時 grok-4.3
- 台帳:
zettelkasten/dagnetz/daily/yyyymmdd.md
- 日記リンク:
1000-eternal-daily/📓MMDD.md に ~200字 + wikilink
- git commit/push(mdのみ。音声バイナリは git に入れない)
Report
- 実処理serviceは
durable-batch-status.json とログを残して終了
- Discord通知は次章の completion-monitor が担当する
- 生の全文は貼らない(件数・日付・失敗数だけ)
4. completion-monitor — 完了時だけDiscordへ1回通知
役割を分離
lifelog-record-stt-daily は起動だけ。実処理serviceが長時間走ってもcronの実行枠に縛られない。
lifelog-record-stt-completion-monitor は15分ごとに確認するだけで、STTを起動も再実行もしない。
15分ごとの script-only cron
*/15 * * * * / job lifelog-record-stt-completion-monitor / no_agent: true
id: a261443a2879deliver: origin(このスレ)
serviceが実行中?
systemctl --user is-active lifelog-stt-batch.service が active なら、まだ処理中。stdoutは空でDiscordへ通知しない。
終了後の状態を読む
logs/durable-batch-status.json の開始・終了・exit code・実行ログを読む。前回と同じ完了キーなら重複通知しない。
新しい完了だけを1回通知
ログの stt_ok_moved / stt_failed を日付別に集計して送る。成功でも失敗でも結果を出し、通知済みキーを durable-batch-reported-at に保存する。
例: moved=70failed=0days={20260830:33}
| 状態 | monitorの動作 | Discord |
| batch 実行中 | 何もしない | 沈黙 |
| statusなし / 既通知 | 何もしない | 沈黙 |
| 新しい done | moved / failed / 日付別件数を集計 | 1回だけ完了報告 |
| 新しい failed | exit codeとログを明示 | 1回だけ障害報告 |
なぜ必要?
長いWAV処理はcronのagent実行枠を超えることがある。起動・実処理・報告を分けることで、
「起動しただけ」を「完了」と誤報しない。空stdoutは正常な沈黙である。
5. データ配置
F:\RECORD\
YYYY-MM-DD-HH-MM-SS.WAV ← 録音入力
E:\2026\{yyyymmdd}\
YYYY-MM-DD-HH-MM-SS.txt ← 全文(STT)
YYYY-MM-DD-HH-MM-SS.WAV ← 移動後アーカイブ
(比較用) *.medium.txt
~/.hermes/workspace/lifelog-stt/
config.yaml / run.sh / state.jsonl / logs/
transcripts/ ← 中間テキスト
zettelkasten/
dagnetz/daily/yyyymmdd.md ← 日次サマリ台帳
1000-eternal-daily/📓MMDD.md ← 200字 + [[リンク]]
6. ガード(壊さないための約束)
| 項目 | ルール |
| STT回数 | 1 WAV = 1回。state / 既存txt で永久スキップ(--force-stt のみ例外) |
| MOVE順序 | txt 成功後のみ WAV を E: へ |
| 日付 | 処理日ではなく 録音日(ファイル名) |
| 録音中 | mtime 15分ガードで触らない |
| 秘密 | Discord に全文・トークンを出さない |
| git | md のみ。WAV/大容量は E: のみ |
7. 手動コマンド
cd ~/.hermes/workspace/lifelog-stt
./run.sh status
./run.sh run # 日次と同じ本線
./run.sh run --date 20260809
./run.sh summarize --date 20260809 --force
cron 文言と config
job プロンプトに “Whisper small” と書かれている場合がある。
実際のモデルは config.yaml の whisper.model_size が正。
medium 本線にするなら config と cron プロンプトを揃える。
8. 実績メモ(参考)
- 手動一括(8/8前後): RECORD を空にし E: へ退避・要約まで成功
- cron 2026-08-10: last_status=ok、8/9 分 STT→MOVE→要約・git 成功
- small vs medium 同日比較: 精度はほぼ同着、所要は medium の方が長い