Manufacturing Engineer & Data Analyst with 18 years of experience, specializing in data analysis, open source contribution, and business automation. (製造業にて18年の経験を持つエンジニア。データ分析・OSS貢献・業務自動化を専門としています)
stackchan-lab — M5 Stack-chan Development Log (Active)
Official M5Stack Stack-chan (M5STACK-K151) moved off its stock cloud assistant onto a self-hosted stack on a Raspberry Pi 5 - 19 server-side tools · 11 device tools over MCP · ~2s from end of speech to first audio · stock firmware, unmodified
How the voice loop runs
| Stage | |
|---|---|
| Speech in | sherpa-onnx / ReazonSpeech, on the Pi |
| Reply | hosted 120B model, free tier |
| Speech out | Open JTalk, on the Pi (0.27s per sentence) |
| Tools | weather, FX, indices, crypto, NHK headlines, JMA quake / warning / typhoon, heat index, train delays, on-this-day, moon and sun, fuel surcharge, travel advisories, baseball scores and standings, roster notices, cheer-song lyrics, singing a cheer song |
| Device tools | camera, head angles, LED, volume, screen, battery - called through the same function-call array |
| Interrupting | the device sends no mic while it is playing, so the server stops the audio and listens at a silent point |
What went wrong, and what it turned out to be
| Symptom | Cause |
|---|---|
Pairing failed as No devices found |
Factory firmware nine releases behind. OTA needs Wi-Fi, Wi-Fi setup needs pairing - USB was the only way in |
| Device kept talking to the stock server | A hand-appended NVS entry padded its key with 0xFF instead of 0x00: valid CRC, invisible to my own parser, permanently missed by ESP-IDF |
| OOM-killed at 7GB RSS, twice | A VAD that starts counting at speech never fires on an always-streaming mic |
| Speech played in slow motion | Not length - the same 30 morae read fine as nonsense but break in a real sentence, and one comma puts it right. The server times each synthesis and re-splits what came out slow |
| The tail of every reply dragged | Open JTalk pads ~0.58s of silence after each synthesis - 27-56% of a short reply was silence |
| Speech came out chopped mid-word | The model answered with a comma-less list, so the splitter fell back to counting characters - and its guard protected digits and Latin but not kanji compounds or a number and its unit |
| Asking the prompt to keep replies short | Cost tool calls, 7/9 to 1/9 on the same probe. Shape is enforced in code instead |
| Nothing could interrupt a long answer | The listening window was opened on an estimate of what the device still had buffered, and closed 0.5-1.1s before the device said it had started listening. It waits for that signal now |
| Questions came back as different sentences | The device sends its whole listening buffer - 18s of it around a one-word question - and all of that reached the recogniser. Trimming to the speech and levelling it halved the error rate |
| It sang the cheer songs, and they were unlistenable | Taken out twice. Both times my measurements passed and it still was not a tune, so the bar was wrong rather than the singing |
| The rhythm would not come back, whatever I changed | The wall was the ruler. Against a real recording, comparing sound to sound has a floor of 142-680ms: singing at the onsets of the recording itself, which cannot be wrong as rhythm, still reads that, and every difference I had been reading between methods sat inside it. Measured by times against times, with a random control beside it, the notes now land 20-60ms from the onsets against 55-105ms for random - and it sings |
Write-up, measurements and tests: stackchan-lab
M5Stack CoreS3 (ESP32-S3) / Raspberry Pi 5 / Python (aiohttp, WebSocket) / sherpa-onnx + ReazonSpeech / Open JTalk / MCP / Opus
rpi5-infra 🔒 (private, config record)
Configuration record for the Raspberry Pi 5 that hosts the robot's server, kept so the box can be rebuilt after an SD failure and so a change like opening a port leaves a trace.
What it records, and what it deliberately leaves out
| Recorded | firewall rules, systemd units, cron entries, listening ports, an inventory of what is actually running |
| Left out | secrets - unit files reference their EnvironmentFile without containing values, and credential files are excluded |
Raspberry Pi OS / systemd / ufw / cron / Tailscale
Minami Baseball OB — Alumni Association Site (In Production)
Full-stack web app for a high school baseball alumni association — 11 active users · 44 pages · 23 DB tables · 19 e2e tests · ¥0/mo running cost (156 files, ~18200 LOC). Technical Documentation
| PC (Light) | Game Results |
![]() |
![]() |
5-tier RBAC (Middleware + RLS), automated member pipeline (Form → GAS → Actions → Supabase), 681 match records (1955–present)
Architecture & features
- 5-tier RBAC (guest → admin): Next.js Middleware + Supabase RLS — authorization at route, row, and component level
- Automated member pipeline: Google Form → Apps Script → GitHub Actions auto-PR → Supabase role sync. Personal names never touch Git
- Custom CMS: 9 editor pages + 5 inline edit, soft delete (7-day trash + auto-purge), change history, audit logs
- 681 match records (1955–present): cross-source verification, generation-based grouping, per-game photo management
- UX: Unsaved warning, Web Share + LINE fallback, Calendar registration, ripple feedback, Suspense skeleton UI, weather forecast (Open-Meteo, 10 venues), automated game detection (2 sources → auto-PR)
- Security: RLS on all 22 tables (16 main + 6 history),
server-onlyadmin, CODEOWNERS, branch protection, secret scanning, cookie consent, 60-min session timeout - Silent-fail monitoring — built after a 1-month silent outage (a Form trigger silently lost its OAuth grant):
- Hourly health-check probes the full member-request + feedback pipeline (Vercel proxy / dispatch chain / GAS time trigger / gas-issue-form secret match / role-sync recency)
- Workflow-run failure + sync-roles liveness (cron-stall) detection auto-opens a tracking GitHub issue and auto-closes it on recovery
- Dual-channel alerts: GitHub Actions email + GAS Gmail
Next.js 15 / TypeScript 5.8 / Tailwind CSS 4 / Supabase (PostgreSQL + Auth + Storage) / Vercel / GitHub Actions / Google Apps Script / GA4
Yokohama Funnies — Amateur Baseball Team Site (In Production)
Companion site for an amateur baseball team, forked from Minami Baseball OB — 23-player roster · 48 pages · 31 DB tables · 18 e2e tests · ¥0/mo running cost (165 files, ~19600 LOC). Technical Documentation
5-tier RBAC (Middleware + RLS), PR-based member approval (Form → GAS → Actions auto-PR → merge → role sync), custom amateur-baseball stats schema (per-game batting / pitching / attendance) with manual-input + spreadsheet-migration ingestion
Architecture & features
- 5-tier RBAC (guest → admin): Next.js Middleware + Supabase RLS — authorization at route, row, and component level (Google OAuth)
- PR-based member approval (same topology as Minami): Google Form → Apps Script → Vercel proxy → GitHub App auto-creates an approval PR adding a per-member role file (
config/members/<uid>.yml); merging triggers a polling role-sync to Supabase + an approval email to the member — approve by merge. Personal data stays minimal in Git - Amateur-baseball stats schema:
players(jersey / bats / throws / is_guest / photo / comment), per-gamegame_player_batting(14 cols) +game_player_pitching,attendances(○/△/×); aggregated views + client-side season filter compute 打率 / 出塁率 / 長打率 / OPS / ERA / WHIP / K9 - Stat ingestion: spreadsheet migration + editor manual-input UI (
/edit/game-stats, scorebook image side-by-side + per-player grid); editors upload scorebook images straight from the result page - Custom CMS / UX: dedicated + inline editor pages, soft delete (7-day trash + auto-purge), change history, audit logs, public No. 06 ROSTER section (photo + jersey + role + comment) via
players_publicview, Open-Meteo weather forecast with WBGT heat-stress display - Security: Supabase RLS on all tables, anon-readable roster view with sensitive columns filtered, server-only admin, gitleaks secret scanning, notifications isolated on a separate public Actions repo
- Silent-fail monitoring:
- Hourly health-check probes every notification path (Vercel proxy / dispatch ack / GAS heartbeat / feedback webhook secret)
- Workflow-run failure + sync-roles liveness detection auto-opens/closes a GitHub issue, with email alerts on any silent failure
Next.js 15 / TypeScript 5.8 / Tailwind CSS 4 / Supabase / Vercel / GitHub Actions / Google Apps Script
| Japan Geohazard Monitor | Persian Gulf Ship Tracker |
![]() |
|
| 31 geophysical data sources → ML earthquake prediction (walk-forward AUC ~0.80 via ConvLSTM, CSEP Molchan 0.981) + real-time monitoring dashboard | AIS vessel tracking across the Persian Gulf & Gulf of Oman with land mask filtering 🛑 Stopped — RPi5 SSD failure (2026-05-16). |
Real-time API / WebSocket → SQLite → FastAPI + Leaflet.js (dark theme) — All projects
Japan Geohazard Monitor — Earthquake prediction research
Data sources, evaluation and the Kumamoto InSAR result
- 85 features from 25+ sources — USGS, NASA Earthdata, INTERMAGNET, NMDB, NOAA, IOC
- Walk-forward evaluation — HistGBT + elastic-net + ConvLSTM, best walk-forward AUC ~0.80 (Kaggle T4)
- Open data & automation — features published as a public Hugging Face dataset, weekly CI pipeline on GitHub Actions
- Co-seismic InSAR — 2026 Kumamoto M7.1 measured from open Sentinel-1 on ASF HyP3: line-of-sight displacement −21.7 to +15.0 cm and a coherence-change damage proxy (method, figures and caveats)
| Project | Description | Demo |
|---|---|---|
| NPB Season Prediction | Bayesian ensemble (Marcel 35% + Stan/Ridge 40% + ML 25%) + Monte Carlo team simulation + 24 foreign player individual projections | Live |
| NPB 2021 Backtest | Could Bayesian model predict Yakult & Orix last→champion? 25 foreign players with FanGraphs data | Analysis |
| MLB Win Probability Engine | 3-engine ensemble WP (Normal + Empirical + LightGBM) + Gemini AI commentary | Live |
| Baseball MLOps Pipeline | Statcast MLOps: 5-model ensemble — weekly auto-retrain paused (BigQuery retired 2026-04, data layer being rebuilt on Hugging Face) | Live |
| MLB Data Pipeline | Shared data platform — FanGraphs + Savant + Statcast published as a public Hugging Face dataset, weekly auto-refresh via GitHub Actions | HF Dataset |
Prediction accuracy & details
| System | Key Metric | Articles |
|---|---|---|
| NPB 2026 | 8-yr backtest wOBA MAE .0498, 97% prob. of beating Marcel. 10K Monte Carlo sims | JP / EN |
| NPB 2021 Backtest | MAE 10.7W — Yakult & Orix last→champion driven by JP player breakouts, not foreign players | Repo |
| MLB WP Engine | 3-engine ensemble, 367K+ play states (2015–2024), inverse-Brier weighted + Isotonic calibration | Live |
| Baseball MLOps | Batter wOBA MAE .0287 (Marcel: .0326) / Pitcher xFIP MAE 0.483 (Marcel: 0.558) | Live |
Baseball Skeleton Analysis — 3D skeleton visualization from Driveline OpenBiomechanics C3D data
| Pitching Skeleton (3D C3D) | Hitting Skeleton (3D C3D) |
![]() |
![]() |
Trunk rotation range vs pitch speed: r=0.425 (strongest). Contributed bug fix PR #384 to ezc3d. Article (JP) / Article (EN)
Handwritten Scorebook OCR 🔒 (private R&D, active)
Amateur Baseball Scorebook Reader — reads handwritten Japanese paper scorebooks (紙スコアブック) from photos into structured at-bat data. 76% → 93% on the hardest mark class, evaluated on 29 hand-transcribed ground-truth sheets.
How it reads the sheets, and how it is evaluated
- No paid APIs, no cloud OCR — deterministic computer vision (OpenCV on a Raspberry Pi 5)
- Game-logic constraint solver — only accepts readings consistent with legal base-running; fused with template matching it lifted the hardest mark class from 76% to 93% pooled
- Honest, live evaluation — the ground-truth archive is complete and still growing (the latest game was transcribed the day it was played); every new sheet serves as a held-out generalization test before joining the pool — 27 consecutive held-out sheets so far, some read perfectly
- Real output — my team's 2026 season batting stats are compiled from this ground truth
Private repo (the method is the product) — public technical write-up: baseball-scorebook-ocr-docs (JP)
6 analyses covering Japanese MLB pitchers and Ohtani batting data.All analyses (6)
| Analysis | Key Finding | Article |
|---|---|---|
| Kikuchi Slider Revolution (2019-2025) | SL 17%→37% after Astros trade | Zenn / DEV.to / Kaggle |
| Senga Ghost Fork (2023-2025) | FO whiff rate 58%→39%, decline pre-injury | Zenn / DEV.to / Kaggle |
| Imanaga 2nd Year (2024-2025) | 3-pitch concentration (97%), 1st TTO xwOBA .505 | Zenn / DEV.to / Kaggle |
| Darvish Evolution (2021-2025) | SL/ST halved, CU became putaway pitch | Zenn / DEV.to / Kaggle |
| Ohtani Spray Chart | spraychart() one-liner vs matplotlib manual | Zenn |
| Ohtani Heatmap | Stadium drawing + hit density heatmap | Zenn |
(85 PRs / 44 Merged) across 39 repositories. See [oss-contributions](https://github.com/yasumorishima/oss-contributions) for full details.
PR highlights (click to expand)
| Repository | PR | Description |
|---|---|---|
| dfinity/icp-js-core | #1270 | Improve Candid decode error messages |
| dfinity/icp-js-core | #1277 | Deduplicate parallel fetchSubnetKeys |
| dfinity/pic-js | #235 | Add fetchCanisterLogs() method |
| line/line-bot-mcp-server | #369 | Add get_follower_ids tool |
| pyomeca/ezc3d | #384 | Fix __eq__ early return bug |
| codeforjapan/mapprint | #556 | Share buttons on the disaster print map |
| codeforjapan/mapprint | #564 | Deterministic list order on the printable map |
| codeforjapan/mapprint | #563 | 2026 Kumamoto earthquake paper map |
| codeforjapan/BirdXplorer | #281 | Statement timeouts for the Community Notes API |
| openclimatefix/graph_weather | #241 | Restore CI: torch pinned to match the PyG wheels it loads |
| openclimatefix/graph_weather | #242 | MOSAIC block-sparse attention, from the paper |
| optuna/optuna | — | Hyperparameter optimization framework |
| pandas-dev/pandas | — | Data analysis library |
| jldbc/pybaseball | #498-504 | Bug fixes & documentation |
team-mirai — Civic Tech OSS (26 PRs (14 Merged / 4 Open / 8 Closed))
Civic tech projects for political transparency & citizen participation in Japan. Next.js / TypeScript / Supabase / Vitest.
| Repository | Highlights |
|---|---|
| action-board | 48 unit tests, RPC tests, breadcrumb nav, cache fix + 5 more |
| marumie | Category filter total |
| mirai-gikai | Supabase CLI v2.106 seed permission fix, Safari/iOS ruby spacing fix |
| post-checker | Timezone fix |
| fact-checker | X API investigation + 5 PRs |
Notebooks Expert | 🥉 14 Bronze Notebook Medals
Active:
- ROGII Wellbore Geology Prediction — $50K, wellbore TVT regression (public LB 7.311, rank 1406/5063)
- SIGNATE AI Engineering Challenge — NTT Data, LLM / RAG / agentic retrieval over a messy corporate drive (¥1.2M prize pool, Jul–Aug 2026)
- SIGNATE NEDO Challenge — Baggage-Loading Optimization — 3D bin packing for airline ULD containers, hybrid offline+online packing agent (¥15M prize pool, Jul–Oct 2026)
Finished 2026: Playground Series S6E6 - Stellar Classification (macro-F1, private LB 0.95939) · NIR Moisture Prediction (SIGNATE, wood spectroscopy) · Stanford RNA 3D Folding 2 · BirdCLEF+ 2026
Bronze Medal Notebooks (14)
| Notebook | Topic |
|---|---|
| savant-extras Defense & Pitching Quality | Defense metrics & pitching quality (savant-extras) |
| MLB Statcast Spray Charts for WBC 2026 | WBC 2026 spray + pitch zone charts (baseball-field-viz) |
| March Machine Learning Mania 2026 | NCAA tournament prediction (LightGBM) |
| NFL Geometric Rules Baseline | Physics-based rules, No ML, RMSE 2.921 |
| CAFA 6 Baseline | Protein function prediction (PyTorch MLP) |
| Dataset | Description |
|---|---|
| 🥈 MLB Bat Tracking Leaderboard (2024-2025) | 452 batters, 19 swing metrics |
| 🥈 WBC 2026 Scouting | 306 players, 20 countries |
Other datasets (4)
| Dataset | Description |
|---|---|
| Baseball Savant Leaderboards (2024-2025) | 15 leaderboards, 2 seasons combined |
| Japanese MLB Players Statcast (2015-2025) | 34 Japanese MLB players, 174k pitches+hits |
| MLB Pitcher Arsenal Evolution (2020-2025) | 4,253 pitcher-seasons, 111 metrics |
| MLB Statcast + Bat Tracking (2024-2025) | Combined Statcast + bat tracking data |
DrivenData Competitions — Automated pipeline: GitHub Actions + GPU training + GPU→CPU fallback. Most recently competed in On Top of Pasketti (Children's ASR, $120K prize, Wav2Vec2 CTC; submission deadline 2026-04-06).
| App | Description | Link |
|---|---|---|
| MLB Bat Tracking Dashboard | Leaderboard, Player Comparison, Team Lineup Builder. Powered by savant-extras | Live |
| WBC 2026 Scouting Dashboard | 30 Statcast apps across 19 countries. Zone heatmaps, spray charts, pitch movement | Live |
| Daily Diary | Flutter mobile app, 10 languages, offline-first, biometric app lock, daily reminder, Android Auto Backup, AdMob | Google Play |
| Fire Tablet Google Play Helper | Detects Fire OS from the browser UA, then lists the four required APKs in install order with step gating and saved progress | Live |
WBC 2026 Scouting Dashboard details (30 apps)
30 Statcast scouting apps across 19 countries (batters + pitchers). Zone heatmaps, spray charts, pitch movement, LHP/RHP splits. Auto-fetched via GitHub Actions. → USA Batters / Japan Pitchers / All 30 apps
6 packages (click to expand)
| Package | Description |
|---|---|
| savant-extras | 17 Baseball Savant leaderboards + date range support. Complements pybaseball |
| baseball-field-viz | Statcast coordinate transform + field drawing + spray charts + pitch zone charts |
| kaggle-notebook-deploy | Deploy Kaggle Notebooks via git push + GitHub Actions |
| kaggle-wandb-sync | Sync W&B offline runs from Kaggle to W&B cloud |
| signate-deploy | SIGNATE competition workflow via GitHub Actions |
| signate-wandb-sync | Record SIGNATE scores to W&B runs |
| Project | Description |
|---|---|
| ICP Learning Project | Persistent counter dApp on Internet Computer (Motoko, dfx CLI) |
| OpenClaw Twitter Bot | Raspberry Pi 5 + OpenClaw + Gemini API auto-tweet bot (stopped) — Article (JP) |
| alexa-rpi5 🔒 | RPi5 ↔ Fire TV Cube 操作 hub (Echo speaker 不要環境)。 cube wrapper + watchers + integrations、 機能詳細は repo README 参照 |
Past Projects
| Project | Description |
|---|---|
| GAS Calendar Tool | Batch calendar event registration with senior-friendly mobile UI |
| Dune Analytics | On-chain data analysis — JPYC Stablecoin Dashboard |
| selenium-to-playwright 🔒 | Playwright browser automation: 20+ scripts + night batch runner with auto GitHub Issues |
| Archived Projects | Selenium automation, business workflow tools, etc. |
| Category | Technologies |
|---|---|
| Data Analysis & ML | Python, pandas, scikit-learn, LightGBM, XGBoost, CatBoost, PyTorch, matplotlib, seaborn, DuckDB, W&B |
| Data Platform | Hugging Face Datasets (MLB / NPB / geohazard — public, auto-refreshed via GitHub Actions), SQLite, |
| Data Sources | Baseball Savant (Statcast), pybaseball, USGS, NASA Earthdata, AIS |
| Web & Dashboards | Streamlit, Next.js, TypeScript, Supabase, Vercel, shadcn/ui |
| Mobile App | Flutter, Dart, Hive, Google AdMob |
| Automation & DevOps | GitHub Actions, Google Apps Script, VBA, Power Query |
| Tools | Claude Code, Kaggle, Google Colab, Excel, Looker Studio |
| Manufacturing | Statistical Quality Control, Process Engineering |
- 2024 - Present: Quality Management @ Marubun Corporation (丸文株式会社)
- 2008 - 2024: Semiconductor Manufacturing Process Engineer (半導体製造プロセスエンジニア)
Stencil mask and manufacturing method thereof (ステンシルマスク及びその製造方法)
- Patent No: 6307851 (特許第6307851号)
- Role: Inventor (発明者)
- Assignee: Toppan Printing Co., Ltd. (凸版印刷株式会社)
- Link: Google Patents (JP6307851B2)
- Site: https://yasumorishima.github.io — tools and blog hosted on this domain
- Blog: DEV.to (EN) / Zenn (JP) / Quarto Blog (EN)
- Kaggle: https://www.kaggle.com/yasunorim
- Wantedly: https://www.wantedly.com/id/yasunori_morishima_b
- LinkedIn: https://www.linkedin.com/in/morishima-yasunori-b70229241








